Подтвердить что ты не робот

IOS11 UIToolBar Contentview

В iOS 11 кнопки и текстовое поле не отвечают за просмотр в UIToolBar. Сравнивая иерархию представлений с iOS 10, мы видим, что существует _UIToolBarContentView по всему подзону UIToolBar.

Например, этот новый макет UIToolBar разбивает slacktextviewcontroller https://github.com/slackhq/SlackTextViewController/issues/604

Требуется решение, работающее в iOS 10/11.

4b9b3361

Ответ 1

Чтобы решить проблему для iOS11 (совместим с более низкими версиями), вам нужно только сделать layoutSubview сразу после того, как UIToolBar был добавлен как подчиненная иерархия пользовательского интерфейса.

В этом случае _UIToolbarContentView опускается до первого подпрограммы UIToolBar, и вы можете добавьте все свои подзоны выше, чем раньше.

Например, в ObjC,

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

    <here one can add all subviews needed>

То же самое происходит с slacktextviewcontroller

Ответ 2

Я решил эту проблему в моем случае. Я переписываю метод layoutSubviews в подклассе UIToobar и изменяю userInteractionEnable of _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;
         }
     }

}

Ответ 3

Вы можете просто использовать метод hitTest(_:with:).

  • Сначала создайте свойство contentView в UIToolbar:

    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, чтобы они были расположены соответствующим образом.

Ответ 4

Новый объект 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 с настраиваемой панелью инструментов, вы должны заставить его обновить свой макет перед добавлением пользовательских подпрограмм.

Ответ 5

Есть странный способ сделать это.

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