web-dev-qa-db-fra.com

iOS11 UIToolBar Contentview

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 slacktextviewcontrollerhttps://github.com/slackhq/SlackTextViewController/issues/604

Besoin d'une solution fonctionnant dans iOS 10/11.

32
Mustard

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

31
malex

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;
         }
     }

}
3
dk_checkitPortal

Vous pouvez simplement utiliser la méthode hitTest(_:with:).

  1. Créez d'abord une propriété contentView dans UIToolbar:

    open private(set) var contentView: UIView = UIView()
    
  2. Ensuite, rendez le cadre de contentView identique à celui de UIToolbar. Par exemple:

    contentView.frame = bounds
    contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    addSubview(contentView)
    
  3. 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.

1
hengyu

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.

0
voromax