iOS11 UIToolBar 内容视图
iOS11 UIToolBar Contentview
在 iOS 11
中,按钮和文本字段作为 UIToolBar
的子视图没有响应。将视图层次结构与 iOS 10
进行比较,我们看到 UIToolBar
的所有子视图都有一个 _UIToolBarContentView
。
例如,UIToolBar
的新布局打破了 slacktextviewcontroller
https://github.com/slackhq/SlackTextViewController/issues/604
需要一个适用于 iOS 10/11
的解决方案。
有一种奇怪的方法。
[self.textInputbar sendSubviewToBack:[self.textInputbar.subviews lastObject]];
解决iOS11
的问题(兼容低版本)只需要
在 UIToolBar
作为子视图添加到 UI 层次结构之后立即制作 layoutSubview
。
在这种情况下 _UIToolbarContentView
降低到 UIToolBar 的第一个子视图,您可以
像以前一样将所有子视图添加得更高。
例如 ObjC
,
UIToolbar *toolbar = [UIToolbar new];
[self addSubview: toolbar];
[toolbar layoutIfNeeded];
<here one can add all subviews needed>
同样的问题发生在slacktextviewcontroller
你可以只使用hitTest(_:with:)
方法。
首先,在UIToolbar
中创建一个属性contentView
:
open private(set) var contentView: UIView = UIView()
然后,使contentView
的帧与UIToolbar
的帧相同。例如:
contentView.frame = bounds
contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
addSubview(contentView)
最后,覆盖hitTest(_:with:)
方法:
open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if self.point(inside: point, with: event) {
if let hitTestView = contentView.hitTest(point, with: event) {
return hitTestView
} else {
return self
}
} else {
return nil
}
}
在这种情况下,如果您想通过简单地添加额外的视图来自定义工具栏,您应该将它们添加到 contentView
中,以便将它们放置在适当的位置。
我已经解决了这个问题。我在 UIToobar 的子类中重写了 layoutSubviews
方法,并将 _UIToolbarContentView
的 userInteractionEnable
更改为 NO.
- (void)layoutSubviews {
[super layoutSubviews];
NSArray *subViewArray = [self subviews];
for (id view in subViewArray) {
if ([view isKindOfClass:(NSClassFromString(@"_UIToolbarContentView"))]) {
UIView *testView = view;
testView.userInteractionEnabled = NO;
}
}
}
新的UIToolbar
对象主动使用基于约束的布局,所以最好覆盖- (void)updateConstraints
方法。要在 UIToolbar
对象上显示自定义视图,最好将其子类化并添加自定义容器视图:
- (UIView *)containerView
{
if (_containerView) {
return _containerView;
}
_containerView = [[UIView alloc] initWithFrame:self.bounds];
_containerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
return _containerView;
}
现在您可以安全地将自定义视图添加到容器视图中。为了使自定义视图具有响应性,我们需要在约束更新后更改工具栏子视图的顺序:
- (void)updateConstraints
{
[super updateConstraints];
[self bringSubviewToFront:self.containerView];
}
请注意,如果您将 UINavigationController
与自定义工具栏一起使用,您应该在添加自定义子视图之前强制它更新其布局。
在仅使用自动布局和代码的 Swift 中,对我有用的是按照 在添加项目之前但在设置约束之后提到的布局。
- 实例化您的工具栏
- 将其添加到您的视图中
添加约束
toolbar.layoutIfNeeded()
toolbar.setItems([...(您的项目)],动画:真)
在 iOS 11
中,按钮和文本字段作为 UIToolBar
的子视图没有响应。将视图层次结构与 iOS 10
进行比较,我们看到 UIToolBar
的所有子视图都有一个 _UIToolBarContentView
。
例如,UIToolBar
的新布局打破了 slacktextviewcontroller
https://github.com/slackhq/SlackTextViewController/issues/604
需要一个适用于 iOS 10/11
的解决方案。
有一种奇怪的方法。
[self.textInputbar sendSubviewToBack:[self.textInputbar.subviews lastObject]];
解决iOS11
的问题(兼容低版本)只需要
在 UIToolBar
作为子视图添加到 UI 层次结构之后立即制作 layoutSubview
。
在这种情况下 _UIToolbarContentView
降低到 UIToolBar 的第一个子视图,您可以
像以前一样将所有子视图添加得更高。
例如 ObjC
,
UIToolbar *toolbar = [UIToolbar new];
[self addSubview: toolbar];
[toolbar layoutIfNeeded];
<here one can add all subviews needed>
同样的问题发生在slacktextviewcontroller
你可以只使用hitTest(_:with:)
方法。
首先,在
UIToolbar
中创建一个属性contentView
:open private(set) var contentView: UIView = UIView()
然后,使
contentView
的帧与UIToolbar
的帧相同。例如:contentView.frame = bounds contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight] addSubview(contentView)
最后,覆盖
hitTest(_:with:)
方法:open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { if self.point(inside: point, with: event) { if let hitTestView = contentView.hitTest(point, with: event) { return hitTestView } else { return self } } else { return nil } }
在这种情况下,如果您想通过简单地添加额外的视图来自定义工具栏,您应该将它们添加到 contentView
中,以便将它们放置在适当的位置。
我已经解决了这个问题。我在 UIToobar 的子类中重写了 layoutSubviews
方法,并将 _UIToolbarContentView
的 userInteractionEnable
更改为 NO.
- (void)layoutSubviews {
[super layoutSubviews];
NSArray *subViewArray = [self subviews];
for (id view in subViewArray) {
if ([view isKindOfClass:(NSClassFromString(@"_UIToolbarContentView"))]) {
UIView *testView = view;
testView.userInteractionEnabled = NO;
}
}
}
新的UIToolbar
对象主动使用基于约束的布局,所以最好覆盖- (void)updateConstraints
方法。要在 UIToolbar
对象上显示自定义视图,最好将其子类化并添加自定义容器视图:
- (UIView *)containerView
{
if (_containerView) {
return _containerView;
}
_containerView = [[UIView alloc] initWithFrame:self.bounds];
_containerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
return _containerView;
}
现在您可以安全地将自定义视图添加到容器视图中。为了使自定义视图具有响应性,我们需要在约束更新后更改工具栏子视图的顺序:
- (void)updateConstraints
{
[super updateConstraints];
[self bringSubviewToFront:self.containerView];
}
请注意,如果您将 UINavigationController
与自定义工具栏一起使用,您应该在添加自定义子视图之前强制它更新其布局。
在仅使用自动布局和代码的 Swift 中,对我有用的是按照
- 实例化您的工具栏
- 将其添加到您的视图中
添加约束
toolbar.layoutIfNeeded()
toolbar.setItems([...(您的项目)],动画:真)