bottom - ios toolbar
iOS11 UIToolBar Contentview (5)
En iOS 11
botones y el campo de texto no responden como subvistas de UIToolBar
. Al comparar la jerarquía de vistas con iOS 10
vemos que hay una _UIToolBarContentView
sobre toda la subvista de UIToolBar
.
Por ejemplo, este nuevo diseño de la UIToolBar
rompe slacktextviewcontroller
https://github.com/slackhq/SlackTextViewController/issues/604
Necesita una solución que funcione en iOS 10/11
.
El nuevo objeto UIToolbar
utiliza activamente el diseño en función de las restricciones, por lo que es mejor anular el método - (void)updateConstraints
. Para presentar vistas personalizadas sobre el objeto UIToolbar
, es mejor UIToolbar
una subclase y agregar una vista personalizada de contenedor:
- (UIView *)containerView
{
if (_containerView) {
return _containerView;
}
_containerView = [[UIView alloc] initWithFrame:self.bounds];
_containerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
return _containerView;
}
Ahora puede agregar de manera segura sus vistas personalizadas a la vista de contenedor. Para que las vistas personalizadas respondan, necesitamos cambiar el orden de las subvistas de la barra de herramientas después de la actualización de las restricciones:
- (void)updateConstraints
{
[super updateConstraints];
[self bringSubviewToFront:self.containerView];
}
Tenga en cuenta que si usa UINavigationController
con una barra de herramientas personalizada, debe obligarlo a actualizar su diseño antes de agregar sus subvistas personalizadas.
Hay una manera extraña de hacerlo.
[self.textInputbar sendSubviewToBack:[self.textInputbar.subviews lastObject]];
He resuelto este problema en mi caso. Reescribo el método layoutSubviews
en la subclase de UIToobar y cambio el userInteractionEnable
de _UIToolbarContentView
en 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;
}
}
}
Para resolver el problema para iOS11
(compatible con versiones inferiores), solo necesita hacer una layoutSubview
justo después de que se agregó UIToolBar
como subvista a la jerarquía de UI.
En este caso _UIToolbarContentView
desciende a la primera subvista de UIToolBar, y puede agregar todas sus subvistas más arriba como antes.
Por ejemplo en ObjC
,
UIToolbar *toolbar = [UIToolbar new];
[self addSubview: toolbar];
[toolbar layoutIfNeeded];
<here one can add all subviews needed>
El mismo problema ocurre con slacktextviewcontroller
Puedes usar el hitTest(_:with:)
.
Primero, crea una propiedad
contentView
enUIToolbar
:open private(set) var contentView: UIView = UIView()
Luego, haga que el marco de
contentView
el mismo que el deUIToolbar
. Por ejemplo:contentView.frame = bounds contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight] addSubview(contentView)
Finalmente, anule el
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 } }
En esta situación, si desea personalizar una barra de herramientas simplemente agregando vistas adicionales, debe agregarlas a contentView
para que se posicionen adecuadamente.