IOS11 UIToolBar Contentview
В iOS 11
кнопки и текстовое поле не отвечают за просмотр в UIToolBar
. Сравнивая иерархию представлений с iOS 10
, мы видим, что существует _UIToolBarContentView
по всему подзону UIToolBar
.
Например, этот новый макет UIToolBar
разбивает slacktextviewcontroller
https://github.com/slackhq/SlackTextViewController/issues/604
Требуется решение, работающее в iOS 10/11
.
Ответы
Ответ 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]];