Dans iOS 11
Les boutons et le champ de texte ne répondent pas étant des sous-vues de UIToolBar
. En comparant la hiérarchie des vues à iOS 10
, Nous voyons qu'il existe un _UIToolBarContentView
Sur toute la sous-vue de UIToolBar
.
Par exemple, cette nouvelle disposition des UIToolBar
casse slacktextviewcontroller
https://github.com/slackhq/SlackTextViewController/issues/604
Besoin d'une solution fonctionnant dans iOS 10/11
.
Pour résoudre le problème pour iOS11
(compatible avec les versions antérieures), il vous suffit de créer layoutSubview
juste après que UIToolBar
a été ajouté en tant que sous-vue à la hiérarchie de l'interface utilisateur.
Dans ce cas _UIToolbarContentView
descend à la première sous-vue de UIToolBar, et vous pouvez ajouter toutes vos sous-vues plus haut que précédemment.
Par exemple dans ObjC
,
UIToolbar *toolbar = [UIToolbar new];
[self addSubview: toolbar];
[toolbar layoutIfNeeded];
<here one can add all subviews needed>
Le même problème se produit avec slacktextviewcontroller
J'ai résolu ce problème dans mon cas. Je réécris la méthode layoutSubviews
dans la sous-classe de UIToobar et change le 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;
}
}
}
Vous pouvez simplement utiliser la méthode hitTest(_:with:)
.
Créez d'abord une propriété contentView
dans UIToolbar
:
open private(set) var contentView: UIView = UIView()
Ensuite, rendez le cadre de contentView
identique à celui de UIToolbar
. Par exemple:
contentView.frame = bounds
contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
addSubview(contentView)
Enfin, substituez la méthode 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
}
}
Dans ce cas, si vous souhaitez personnaliser une barre d'outils en ajoutant simplement des vues supplémentaires, vous devez les ajouter au contentView
afin qu'elles soient positionnées de manière appropriée.
Le nouvel objet UIToolbar
utilise activement la mise en page en fonction des contraintes, il est donc préférable de remplacer la méthode - (void)updateConstraints
. Pour présenter des vues personnalisées sur un objet UIToolbar
, il est préférable de le sous-classer et d'ajouter une vue de conteneur personnalisée:
- (UIView *)containerView
{
if (_containerView) {
return _containerView;
}
_containerView = [[UIView alloc] initWithFrame:self.bounds];
_containerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
return _containerView;
}
Vous pouvez maintenant ajouter en toute sécurité vos vues personnalisées à la vue du conteneur. Pour rendre les vues personnalisées réactives, nous devons modifier l'ordre des sous-vues de la barre d'outils après la mise à jour des contraintes:
- (void)updateConstraints
{
[super updateConstraints];
[self bringSubviewToFront:self.containerView];
}
Notez que si vous utilisez UINavigationController
avec la barre d'outils personnalisée, vous devez la forcer à mettre à jour sa disposition avant d'ajouter vos sous-vues personnalisées.