web-dev-qa-db-fra.com

Question de positionnement UITabBar UITabBarItem ios 11

J'ai construit mon application à l'aide de la nouvelle version bêta de Xcode 9 pour ios 11. J'ai trouvé un problème avec UITabBar dans lequel les éléments sont disséminés dans la barre UITabBar et où le titre est aligné à droite sur l'image. J'ai essayé de changer le code pour le faire fonctionner mais je n'ai toujours pas réussi.

iOS 10+

enter image description here

iOS 11

enter image description here

Je pourrais changer la position du titre en utilisant tabBarItem.titlePositionAdjustment, Mais ce n’est pas mon exigence, elle devrait automatiquement apparaître au-dessous de l’image elle-même. J'ai essayé de régler tabbar.itemPositioning to UITabBarItemPositioningCentered Et j'ai aussi essayé de changer itemSpacing et width, mais je n'ai toujours pas fonctionné. Quelqu'un peut-il m'aider à comprendre pourquoi cela se produit et comment résoudre ce problème? Je veux qu'il aime la version iOS 10+ et les images sont prises depuis le coin le plus à gauche d'un iPad.

44
Gihan

Je maintiens une grande application iPad écrite principalement en Objective-C qui a survécu à plusieurs versions d'iOS. J'ai rencontré la situation dans laquelle j'avais besoin de l'apparence de la barre d'onglets antérieure à iOS 11 (avec les icônes au-dessus des titres au lieu d'être à côté d'eux) pour quelques barres d'onglets. Ma solution consistait à créer une sous-classe de UITabBar qui remplace la méthode traitCollection afin qu'elle renvoie toujours une collection de traits horizontalement compacts. Ainsi, iOS 11 affiche les titres sous les icônes de tous les boutons de la barre d'onglets.

Pour l'utiliser, définissez la classe personnalisée des barres d'onglets du storyboard sur cette nouvelle sous-classe et modifiez les points de vente du code pointant vers les barres d'onglets afin qu'ils soient de ce nouveau type (n'oubliez pas d'importer le fichier d'en-tête. au dessous de).

Le fichier .h est à peu près vide dans ce cas:

//
//  MyTabBar.h
//

#import <UIKit/UIKit.h>

@interface MyTabBar : UITabBar

@end

Voici le fichier .m avec l'implémentation de la méthode traitCollection:

//
//  MyTabBar.m
//

#import "MyTabBar.h"

@implementation MyTabBar

// In iOS 11, UITabBarItem's have the title to the right of the icon in horizontally regular environments
// (i.e. the iPad).  In order to keep the title below the icon, it was necessary to subclass UITabBar and override
// traitCollection to make it horizontally compact.

- (UITraitCollection *)traitCollection {
    return [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact];
}

@end
38
John C.

D'après la réponse de John C, voici la version Swift 3) qui peut être utilisée par programmation sans recourir à Storyboard ou à un sous-classement:

extension UITabBar {
    // Workaround for iOS 11's new UITabBar behavior where on iPad, the UITabBar inside
    // the Master view controller shows the UITabBarItem icon next to the text
    override open var traitCollection: UITraitCollection {
        if UIDevice.current.userInterfaceIdiom == .pad {
            return UITraitCollection(horizontalSizeClass: .compact)
        }
        return super.traitCollection
    }
}
33
massimobio

Pour éviter de gâcher d’autres traits, il n’est pas préférable de les combiner avec les super-classes:

- (UITraitCollection *)traitCollection
{
  UITraitCollection *curr = [super traitCollection];
  UITraitCollection *compact = [UITraitCollection  traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact];

  return [UITraitCollection traitCollectionWithTraitsFromCollections:@[curr, compact]];
}
18
Andy C

REMARQUE: Ce correctif ci-dessus semble fonctionner assez bien. Je ne sais pas comment cela fonctionnera à l'avenir, mais pour l'instant cela fonctionne assez bien.


Selon cette discussion WWDC , il s’agit du nouveau comportement de:

  • iPhone en paysage
  • iPad tout le temps

Et si je lis correctement, ce comportement ne peut pas être changé:

Nous avons cette toute nouvelle apparence pour la barre d'onglets, à la fois en mode paysage et sur iPad, où nous affichons l'icône et le texte côte à côte. Et en particulier sur les iPhones, l’icône est plus petite et la barre d’onglet est plus petite pour donner un peu plus de place verticalement.

14
Dan Rosenstark

Version Swift 4 avec une sous-classe qui évite les conflits de noms d'extension/catégorie:

class TabBar: UITabBar {
  override var traitCollection: UITraitCollection {
    guard UIDevice.current.userInterfaceIdiom == .pad else {
      return super.traitCollection
    }

    return UITraitCollection(horizontalSizeClass: .compact)
  }
}

Si vous utilisez Interface Builder et les storyboards, vous pouvez sélectionner la vue de la barre d'onglets dans votre scène UITabBarController et changer sa classe en TabBar dans l'inspecteur d'identité:

enter image description here

10
Max Desiatov

En plus de la réponse de John:

Si vous avez plus de 4 éléments dans la barre d'onglets et que vous ne voulez pas le bouton "Plus", vous devez choisir une classe de taille différente. Et si vous voulez la disposition centrée originale des éléments, vous devez ajouter une autre méthode comme celle-ci:

#import "PreIOS11TabBarController.h"

@interface PreIOS11TabBarController ()

@end

@implementation PreIOS11TabBarController

// In iOS 11, UITabBarItem's have the title to the right of the icon in horizontally regular environments
// (i.e. the iPad).  In order to keep the title below the icon, it was necessary to subclass UITabBar and override
// traitCollection to make it horizontally compact.

- (UITraitCollection *)traitCollection {
    return [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassUnspecified];
}


- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    self.tabBar.itemPositioning = UITabBarItemPositioningCentered;
}

@end
2
twofish