guidelines bottom bar ios uitoolbar ios11

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:) .

  1. Primero, crea una propiedad contentView en UIToolbar :

    open private(set) var contentView: UIView = UIView()

  2. Luego, haga que el marco de contentView el mismo que el de UIToolbar . Por ejemplo:

    contentView.frame = bounds contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight] addSubview(contentView)

  3. 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.