web-dev-qa-db-ja.com

iOS11 UIToolBar Contentview

iOS 11では、ボタンとテキストフィールドはUIToolBarのサブビューであるため応答しません。ビュー階層をiOS 10と比較すると、UIToolBarのすべてのサブビューに_UIToolBarContentViewがあります。

たとえば、UIToolBarのこの新しいレイアウトはslacktextviewcontrollerを壊します https://github.com/slackhq/SlackTextViewController/issues/604

iOS 10/11で動作するソリューションが必要です。

32
Mustard

iOS11(下位バージョンとの互換性)の問題を解決するには、UI階層のサブビューとしてlayoutSubviewを追加した直後にUIToolBarを作成するだけです。

この場合、_UIToolbarContentViewはUIToolBarの最初のサブビューに下がり、すべてのサブビューを以前のように上に追加できます。

たとえば、ObjCでは、

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

    <here one can add all subviews needed>

slacktextviewcontroller でも同じ問題が発生します

31
malex

私の場合、この問題を解決しました。 UIToobarのサブクラスのlayoutSubviewsメソッドを書き換え、_UIToolbarContentViewuserInteractionEnableを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;
         }
     }

}
3

hitTest(_:with:)メソッドを使用するだけです。

  1. まず、contentViewにプロパティUIToolbarを作成します。

    _open private(set) var contentView: UIView = UIView()
    _
  2. 次に、contentViewのフレームをUIToolbarのフレームと同じにします。例えば:

    _contentView.frame = bounds
    contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    addSubview(contentView)
    _
  3. 最後に、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に追加する必要があります。

1
hengyu

新しい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を使用している場合、カスタムサブビューを追加する前に、レイアウトを強制的に更新する必要があることに注意してください。

0
voromax