web-dev-qa-db-fra.com

Ce nouveau comportement de la barre de navigation dans xcode 11 beta est-il un bug ou prévu?

J'ai remarqué après avoir compilé une de mes applications dans Xcode 11 beta, que les barres de navigation n'ont pas d'arrière-plan lorsque prefersLargeTitles est défini. Est-ce le comportement voulu?

J'ai remarqué que c'est ainsi que l'application de messages fonctionne maintenant lorsque vous faites défiler vers le bas et qu'un grand titre est visible, il n'y a pas d'arrière-plan de barre de navigation.

Voici le code utilisé pour configurer les attributs navBar:

 override func viewWillAppear(_ animated: Bool) {
    let textAttributes = [NSAttributedString.Key.foregroundColor:ThemeManager.shared.default1]
    self.navigationController?.navigationBar.largeTitleTextAttributes = textAttributes
    self.navigationController?.navigationBar.titleTextAttributes = textAttributes
    self.navigationController?.navigationBar.tintColor = ThemeManager.shared.default1
 self.navigationController?.setNavigationBarHidden(false, animated: true)
    self.navigationController?.navigationBar.prefersLargeTitles = true
    let nav = self.navigationItem
    nav.title = "My Profile"
}

Voici quelques images montrant la différence:

à gauche, compilé sur Xcode 10, à droite, Xcode 11 beta:

enter image description hereenter image description here

Une fois que vous faites défiler vers le haut sur la version 11 Beta, l'arrière-plan revient en arrière. Notez que les applications qui ne sont pas compilées dans Xcode 11 beta se comporteront toujours de la manière normale, ne changent qu'après la compilation pour une raison quelconque. Est-ce prévu, et comment pourrais-je ramener le comportement d'origine?

9
Peter Ruppert

Il s'agit d'un comportement prévu pour iOS 13.

L'idée d'Apple (terrible à mon avis) est que le titre devrait fusionner avec le contenu pour montrer qu'il est lié. Une fois que vous commencez à faire défiler, lorsque le contenu passe derrière la barre de titre, la barre de titre prendra l'apparence "correcte".

La raison pour laquelle c'est terrible est que tout le monde a actuellement planifié toute son interface utilisateur sans ce comportement. Donc, le nouveau comportement devrait être opt-in au lieu de forcer tout le monde à se retirer (c.-à-d. Que le changement casse le code de tout le monde et si vous allez casser le code de tout le monde au moins, vous devriez être clair sur la façon de garder le comportement éprouvé de 10 dernières années).

Comme dans votre cas, le résultat semble horrible. Le résultat semble horrible dans mon cas aussi.

Apple ne donne pas de réponses mais dit que vous devriez utiliser

- scrollEdgeAppearance

Depuis UINavigationBar afin de contrôler l'apparence de la barre lorsque le contenu est aligné du haut du contenu au bas de la barre de navigation ... dans mon cas, cette méthode retourne à zéro, donc je ne suis actuellement pas sûr de la façon dont nous sommes censés utiliser ce.

Cela semble également être discuté ici:

Nouvelle apparence UINavigationBar dans le volet de détail d'UISplitViewController dans iOS 1

Ainsi, la solution de contournement actuelle semble être la suivante dans votre contrôleur de vue:

- (void)viewDidLoad;
{
    [super viewDidLoad];
    if (@available(iOS 13,*)){
        UINavigationBar *bar =self.navigationController.navigationBar;
        bar.scrollEdgeAppearance = bar.standardAppearance;
    }
}

Cela fonctionne, mais si c'est l'approche envisagée, je ne sais pas ...

ÉDITER:

Cela semble bloquer toute personnalisation directe supplémentaire de l'UINavigationBar, comme cela a été noté. Il est possible que le réglage de scrollEdgeAppearance à partir d'ici soit la voie à suivre. Laid. Laid. Laid.

EDIT: Progress ... cela fonctionne maintenant pour gérer l'arrière-plan. Vous devez l'appeler au lieu de définir directement barTint.

@interface UINavigationBar (Compatibility)
- (void)setCompatibleTint:(UIColor *)fg andBarTint:(UIColor *)bg;
@end

@implementation UINavigationBar (Compatibility)
- (void)setCompatibleTint:(UIColor *)fg andBarTint:(UIColor *)bg;
{
    self.tintColor = fg;
    self.barTintColor = bg;
    if (@available(iOS 13,*)){
        // we need to tell it to adopt old style behavior first
        UINavigationBarAppearance *appearance = self.standardAppearance;
        appearance.backgroundColor = bg;
        NSDictionary *attributes = self.titleTextAttributes;
        appearance.titleTextAttributes = attributes;
        attributes = self.largeTitleTextAttributes;
        appearance.largeTitleTextAttributes = attributes;
        self.scrollEdgeAppearance = appearance;
        self.standardAppearance = appearance;
        self.compactAppearance = appearance;
    }
}
@end

Je ne suis pas encore tout à fait sûr des attributs du texte mais il semble découler de la couleur d'arrière-plan. C'est un PITA complet.

Il serait plus agréable de définir cela comme une sous-classe et de remplacer barTint, mais bien sûr, de nombreux objets UIKit créent eux-mêmes ces barres afin que vous n'obteniez pas la sous-classe.

11
dbquarrel

Version rapide de la solution de dbquarrel.

Déclarez d'abord vos textAttributes:

let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.red]

Utilisez-les dans une UINavigationBarAppearance() pour vous permettre de changer la couleur du texte dans 3 modes différents (scollEdge, standard et compact).

override func viewDidLoad() {
    super.viewDidLoad()
    if #available(iOS 13.0, *) {
        let appearance = UINavigationBarAppearance()
        appearance.largeTitleTextAttributes = textAttributes
        appearance.titleTextAttributes = textAttributes
        let bar = self.navigationController?.navigationBar
        bar?.scrollEdgeAppearance = appearance
        bar?.standardAppearance = appearance
        bar?.compactAppearance = appearance
    } else {
        // Fallback on earlier versions
    }
}
7
Peter Ruppert