web-dev-qa-db-fra.com

Comment passer en douceur de UINavigationBar iOS translucide à opaque?

Je rencontre des problèmes pour reconfigurer la UINavigationBar sous iOS 7 et 8 lors de la transition entre les vues.

Mon application contient actuellement le flux UIViewController suivant:

VC1 -> VC2 -> VC3

Dans ce flux

  • VC1 est l’écran d’accueil et a opaque UINavigationBar
  • VC2 a une translucide UINavigationBar
  • VC3 revient à avoir un opaque UINavigationBar

Le problème que j'ai rencontré est que les transitions entre ces vues sont toutes très bâclées. Pour commencer, j'ai essayé ce qui suit:

dans VC2

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    // configure appearance
    [self.navigationController.navigationBar configureTranslucentAppearance];
}

Et dans VC1 et VC3

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    // configure appearance
    [self.navigationController.navigationBar restoreDefaultAppearance];
}

Voici les implémentations des deux fonctions d'assistance listées ci-dessus:

- (void)restoreDefaultAppearance {
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

    [self setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor JTTextNavBar]}];
    [self setTintColor:[UIColor JTTextNavBar]];
    [self setBarTintColor:[UIColor JTBackgroundNavBarWithAlpha:1.0]];
    [self setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
    [self setBackgroundColor:[UIColor JTBackgroundNavBarWithAlpha:1.0]];
    [self setShadowImage:[UIImage navigationBarShadowImage]];
    [self setTranslucent:NO];
}

- (void)configureTranslucentAppearance {
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

    [self setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
    [self setBackgroundColor:[UIColor clearColor]];
    [self setShadowImage:[UIImage new]];
    [self setTranslucent:YES];
}

C’est le moyen le plus élémentaire de gérer cette transition. Il présente les artefacts visuels suivants:

  • Lorsque vous passez de VC1 -> VC2 au moment où vous commencez la transition, la barre de navigation devient noire. L'animation se termine normalement enter image description here
  • Lorsque vous passez de VC2 -> VC1, la barre de navigation passe instantanément à la couleur par défaut de l'application avant la fin du délai. enter image description here
  • Lorsque vous passez de VC2 -> VC3, la barre de navigation passe instantanément de la translucide à la couleur de la barre de navigation de l'application, puis les éléments de menu et le corps VC s'animent en. enter image description here
  • Lorsque vous passez de VC3 -> VC2, la barre de navigation devient instantanément noire et reste ainsi jusqu'à la fin de la transition. enter image description here

Aucune de ces transitions ne semble bonne. Idéalement, j'aimerais que les vues passent en douceur avec leur nouvelle UINavigationBar, mais la seule façon dont j'ai réussi à le faire est d'ajouter manuellement une barre d'outils à chaque xib.

Aucune suggestion? Toutes mes excuses si cette description est déroutante :(

Édition: Ajout d'images recadrées de UINavigationBar et de la partie supérieure de UIViewController pour chacune des transitions répertoriées.

27
alexgophermix

J'ai enfin trouvé une solution décente!

Il ne semble pas exister de moyen approprié pour passer en douceur d'un opaque à un transparent UINavigationBar MAIS vous pouvez passer en douceur d'un contrôleur de vue avec une barre d'état visible à un autre avec une barre d'état cachée.

Cela ouvre une solution de contournement possible qui consiste à ajouter ce qui suit dans la viewWillAppear de VC2 à partir de ci-dessus:

[self.navigationController setNavigationBarHidden:YES animated:YES];

Une fois que vous avez cela, ajoutez manuellement une UINavigationBar à votre xib et configurez-le pour qu'il soit transparent (et ajoutez tous les UIBarButtonItem et vues nécessaires).

Si tout est correctement raccordé, la transition de VC1 à VC2 masquera la variable UINavigationBar à la même vitesse que la transition de vue et VC2 s'affichera avec sa variable incorporée UINavigationBar

Remarque: Pour que cela fonctionne correctement, vous devez vous assurer que, dans la viewWillAppear des contrôleurs de vue accessibles depuis VC2 , vous réinitialisez la UINavigationBar pour qu'elle soit visible (si nécessaire) via:

[self.navigationController setNavigationBarHidden:NO animated:YES];

TL; DR - ajouter manuellement une UINavigationBar à votre contrôleur de vue de barre de navigation transparent et dans sa viewWillAppear masquer la valeur par défaut via setNavigationBarHidden:animated:

14
alexgophermix

La couleur noire que vous voyez est la couleur d'arrière-plan de la vue UINavigationController's. Une façon de minimiser le fait de le voir consiste à manipuler la couleur d'arrière-plan de cette vue afin qu'elle corresponde à celle de la vue du contrôleur de vue sortant/entrant. Cela fonctionne bien si vous travaillez avec des couleurs unies. Une autre approche consiste à étendre vos vues derrière la barre de navigation opaque en utilisant UIViewController.extendedLayoutIncludesOpaqueBars = YES;

14
TomSwift

Définissez la couleur d'arrière-plan UIWindow sur la teinteCouleur de votre barre de navigation.

4
user501836

toujours utiliser Translucent, plus ajouter un uiview avec une couleur en dessous et animer son alpha?

3
dOM

Vous pouvez créer votre propre barre de navigation en utilisant simplement UIView, ce qui vous permet de contrôler totalement son apparence, son agencement, son fondu, etc. .. J'ai abandonné l'utilisation de UINavigationBar il y a quelque temps, car il peut être difficile de découvrons, et maintenant je ne l'utilise jamais. 

J'ai un contrôleur de vue racine qui a un UIView qui représente la barre de navigation. Si je veux faire quelque chose comme ajouter un bouton de retour, changer la couleur, afficher la barre de navigation ou la masquer, changer la transparence, etc., tout est contrôlé par le RVC et les autres méthodes de contrôle de vue appellent le RVC pour changer la navigation. bar en fonction de leurs exigences d'aspect.

Le RVC a une vue de conteneur qui est la taille complète de la vue du contrôleur et les autres contrôleurs de vue sont chargés dans cette .. Un peu de configuration pour tout configurer, mais une fois cela fait, sa structure peut être utilisée dans chaque projet qui utilise une barre de navigation très rapidement.

1
Gruntcakes

Alors j'ai eu du mal avec ça aussi.

Malheureusement, je n'ai pas réussi à ajouter ma propre barre de navigation via le storyboard. Au lieu de cela (et je vous préviens que c'est hacky), j’ajoute une vue dans ViewController avec la barre de navigation opaque dotée d’une marge négative et s’étendant sous la barre de navigation.

Lorsque le ViewController avec la barre de navigation transparente est poussé, la barre devient immédiatement transparente, mais en raison de la vue de couleur identique que j'ai placée directement derrière elle, le changement n'est pas perceptible. Et voilà.

Le code que j'ai est assez basique et écrit en C # (Xamarin) mais pour des raisons d’exhaustivité ....

  var backing = new UIView(new CGRect(0, -68, this.View.Frame.Width, 64f));
  backing.BackgroundColor = UIColor.Green;
  this.View.AddSubview(backing);
1
James Mundy

J'ai lutté avec un problème presque identique. Il n'y a pas vraiment de transition en douceur utilisant une barre de navigation ou une barre d'outils floue. La meilleure option que j'ai trouvée * consiste à transformer une image en image, puis à utiliser cette image pour la transition. Surtout si vous en avez juste besoin pour les transitions, il s’agit de l’option la moins chère qui offre toujours une interface utilisateur/UX exceptionnelle.

* L'avertissement est que certains des effets d'interface utilisateur dans une barre de navigation et une barre d'outils n'apparaissent pas lorsque vous prenez un instantané, une capture d'écran ou pixellisez une vue UIV en tant qu'image. Ceci est négligeable si utilisé pour une transition.

1
Fennelouski

Changer le travail de couleur de fond pour moi

window?.backgroundColor = Color.red.toUIColor()
0
luhuiya

J'ai encore une solution .. pour ceux qui refacturent maintenant le projet et ne peuvent pas ajouter la barre de navigation partout .. Ce n'est pas une solution parfaite, tout comme @alexgophermix. Mais ce n'est pas mal non plus:

let transition = CATransition()
        transition.duration = 0.6
        transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
        transition.type = kCATransitionFade
        navigationController?.navigationBar.shadowImage = UIImage()
        navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
        navigationController?.navigationBar.isTranslucent = true
        navigationController?.navigationBar.layer.add(transition, forKey: nil)
        navigationController?.view.backgroundColor = .clear

Je suis en train de régler ma barre de navigation dans viewDidLoad () afin que cela fonctionne partout et donne une légère transition différente. Dans mon cas, je fixais des arrière-plans clairs quelque part et déposais une image en dégradé. Donc, ce petit changement va bien pour partout. Cette transition est peu perceptible mais elle n’a pas l’air mauvais non plus :)

0
Amber K