简体   繁体   English

iOS11 UIToolBar 内容视图

[英]iOS11 UIToolBar Contentview

In iOS 11 buttons and text field are unresponsive being subviews of UIToolBar .iOS 11按钮和文本字段作为UIToolBar子视图没有响应。 Comparing view hierarchy to iOS 10 we see there is a _UIToolBarContentView over all subview of UIToolBar .将视图层次结构与iOS 10进行比较,我们看到_UIToolBarContentView的所有子视图上UIToolBar一个UIToolBar

For instance, this new layout of the UIToolBar breaks slacktextviewcontroller https://github.com/slackhq/SlackTextViewController/issues/604例如, UIToolBar这个新布局打破了slacktextviewcontroller https://github.com/slackhq/SlackTextViewController/issues/604

Need a solution working in iOS 10/11 .需要一个适用于iOS 10/11的解决方案。

To solve the problem for iOS11 (compatible with lower versions) you only need to make layoutSubview right after UIToolBar was added as a subview to UI hierarchy.为了解决iOS11 (兼容低版本)的问题,你只需要在UIToolBar作为子视图添加到UI层次结构后UIToolBar制作layoutSubview

In this case _UIToolbarContentView lowers to the first subview of UIToolBar, and you can add all your subviews higher as before.在这种情况下_UIToolbarContentView降低到_UIToolbarContentView的第一个子视图,您可以像以前一样将所有子视图添加到更高的位置。

For example in ObjC ,例如在ObjC

    UIToolbar *toolbar = [UIToolbar new];
    [self addSubview: toolbar];
    [toolbar layoutIfNeeded];

    <here one can add all subviews needed>

The same problem happens with slacktextviewcontroller slacktextviewcontroller 也会出现同样的问题

I have solved this problem in my case.我已经解决了这个问题。 I rewrite the layoutSubviews method in subclass of UIToobar and change the userInteractionEnable of _UIToolbarContentView into NO.我在 UIToobar 的子类中重写了layoutSubviews方法,并将 _UIToolbarContentView 的userInteractionEnable _UIToolbarContentView为 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;
         }
     }

}

You can just use the hitTest(_:with:) method.您可以只使用hitTest(_:with:)方法。

  1. First, create a property contentView in UIToolbar :首先,在UIToolbar创建一个属性contentView

     open private(set) var contentView: UIView = UIView()
  2. Then, make the contentView 's frame the same as the UIToolbar 's.然后,使contentView的框架与UIToolbar的框架相同。 For example:例如:

     contentView.frame = bounds contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight] addSubview(contentView)
  3. Finally, override the hitTest(_:with:) method:最后,覆盖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 } }

In this situation, if you want to customize a toolbar by simply adding additional views, you should add them to the contentView so they will be positioned appropriately.在这种情况下,如果您想通过简单地添加其他视图来自定义工具栏,您应该将它们添加到contentView以便它们被适当地定位。

The new UIToolbar object actively uses layout based on constraints, so it is better to override - (void)updateConstraints method.新的UIToolbar对象主动使用基于约束的布局,所以最好重写- (void)updateConstraints方法。 To present custom views over UIToolbar object it is better to subclass it and add custom container view:要在UIToolbar对象上显示自定义视图,最好将其子类化并添加自定义容器视图:

- (UIView *)containerView
{
    if (_containerView) {
        return _containerView;
    }
    _containerView = [[UIView alloc] initWithFrame:self.bounds];
    _containerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    return _containerView;
}

Now you can safely add your custom views to the container view.现在您可以安全地将自定义视图添加到容器视图中。 To make the custom views responsive we need change the order of toolbar subviews after the constraints update:为了使自定义视图具有响应性,我们需要在约束更新后更改工具栏子视图的顺序:

- (void)updateConstraints
{
    [super updateConstraints];

    [self bringSubviewToFront:self.containerView];
}

Note, that if you are using UINavigationController with custom toolbar, you should force it to update its layout before adding your custom subviews.请注意,如果您将UINavigationController与自定义工具栏一起使用,则应在添加自定义子视图之前强制它更新其布局。

In Swift with autolayout and code only, what worked for me was to do layout as malex mentions just before adding items, but after setting constraints.在仅具有自动布局和代码的 Swift 中,对我有用的是在添加项目之前但在设置约束之后按照malex提到的方式进行布局。

  • Instantiate your toolbar实例化你的工具栏
  • Add it to your view将其添加到您的视图中
  • Add constraints添加约束

    toolbar.layoutIfNeeded()工具栏.layoutIfNeeded()

    toolbar.setItems([... (your items)], animated: true)工具栏.setItems([... (你的物品)], 动画: 真)

有一种奇怪的方法可以做到这一点。

[self.textInputbar sendSubviewToBack:[self.textInputbar.subviews lastObject]];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM