129 votes

Imiter l’iOS 7 Facebook masquer/afficher expansion/sous-traitance de barre de Navigation

Dans le nouvel iOS7 Facebook application iPhone, lorsque l'utilisateur fait défiler jusqu'à l' navigationBar progressivement se cache lui-même à un point où il disparaît complètement. Ensuite, lorsque l'utilisateur fait défiler la navigationBar montre peu à peu lui-même.

Comment voulez-vous mettre en œuvre ce problème vous-même? Je suis conscient de la solution suivante, mais il disparaît immédiatement et il n'est pas lié à la vitesse de l'utilisateur de faire défiler geste.

[navigationController setNavigationBarHidden: YES animated:YES];

J'espère que ce n'est pas un doublon car je ne suis pas sûr de la meilleure façon de décrire la "dilatation/contraction" de comportement. Salut et merci d'avance!

162voto

lwburk Points 29313

La solution donnée par @peerless est un bon début, mais il ne démarre une animation à chaque fois que commence à faire glisser, sans tenir compte de la vitesse de défilement. Il en résulte une plus découpé de l'expérience que vous obtenez dans le Facebook app. Pour correspondre Facebook du comportement, nous avons besoin de:

  • masquer/afficher la barre de navigation à un taux qui est proportionnelle au taux de glisser
  • le coup d'envoi d'une animation à cacher complètement la barre si le défilement s'arrête lorsque la barre est partiellement caché
  • fondu de la barre de navigation des articles comme le bar se rétrécit.

Voici l' UIScrollViewDelegate méthodes:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGRect frame = self.navigationController.navigationBar.frame;
    CGFloat size = frame.size.height - 21;
    CGFloat framePercentageHidden = ((20 - frame.origin.y) / (frame.size.height - 1));
    CGFloat scrollOffset = scrollView.contentOffset.y;
    CGFloat scrollDiff = scrollOffset - self.previousScrollViewYOffset;
    CGFloat scrollHeight = scrollView.frame.size.height;
    CGFloat scrollContentSizeHeight = scrollView.contentSize.height + scrollView.contentInset.bottom;

    if (scrollOffset <= -scrollView.contentInset.top) {
        frame.origin.y = 20;
    } else if ((scrollOffset + scrollHeight) >= scrollContentSizeHeight) {
        frame.origin.y = -size;
    } else {
        frame.origin.y = MIN(20, MAX(-size, frame.origin.y - scrollDiff));
    }

    [self.navigationController.navigationBar setFrame:frame];
    [self updateBarButtonItems:(1 - framePercentageHidden)];
    self.previousScrollViewYOffset = scrollOffset;
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [self stoppedScrolling];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView 
                  willDecelerate:(BOOL)decelerate
{
    if (!decelerate) {
        [self stoppedScrolling];
    }
}

Vous aurez également besoin de ces méthodes d'aide:

- (void)stoppedScrolling
{
    CGRect frame = self.navigationController.navigationBar.frame;
    if (frame.origin.y < 20) {
        [self animateNavBarTo:-(frame.size.height - 21)];
    }
}

- (void)updateBarButtonItems:(CGFloat)alpha
{
    [self.navigationItem.leftBarButtonItems enumerateObjectsUsingBlock:^(UIBarButtonItem* item, NSUInteger i, BOOL *stop) {
        item.customView.alpha = alpha;
    }];
    [self.navigationItem.rightBarButtonItems enumerateObjectsUsingBlock:^(UIBarButtonItem* item, NSUInteger i, BOOL *stop) {
        item.customView.alpha = alpha;
    }];
    self.navigationItem.titleView.alpha = alpha;
    self.navigationController.navigationBar.tintColor = [self.navigationController.navigationBar.tintColor colorWithAlphaComponent:alpha];
}

- (void)animateNavBarTo:(CGFloat)y
{
    [UIView animateWithDuration:0.2 animations:^{
        CGRect frame = self.navigationController.navigationBar.frame;
        CGFloat alpha = (frame.origin.y >= y ? 0 : 1);
        frame.origin.y = y;
        [self.navigationController.navigationBar setFrame:frame];
        [self updateBarButtonItems:alpha];
    }];
}

Pour un comportement légèrement différent, remplacez la ligne que re-postes de la barre de défilement ( else bloc en scrollViewDidScroll) avec celui-ci:

frame.origin.y = MIN(20, 
                     MAX(-size, frame.origin.y - 
                               (frame.size.height * (scrollDiff / scrollHeight))));

Cela place la barre de la dernière défilement de pourcentage, au lieu d'un montant absolu, ce qui entraîne un ralentissement de l'évanouissement. Le comportement d'origine est plus Facebook-like, mais j'aime celui-ci, trop.

Remarque: Cette solution est iOS 7 uniquement. Assurez-vous d'ajouter les vérifications nécessaires si vous êtes en support des anciennes versions d'iOS.

43voto

Mazyod Points 6072

Voici encore une mise en œuvre: TLYShyNavBar

J'ai décidé de faire ma propre après avoir essayé les solutions proposées, et pour moi, ils étaient peu performants, avait une haute barrière de l'entrée et de la chaudière de la plaque de code, ou qui n'avaient pas l'extension de vue en dessous de la barre de navigation. Pour utiliser ce composant, tout ce que vous avez à faire est de:

self.shyNavBarManager = self.scrollView;

Oh, et c'est la bataille testés dans notre propre application.

33voto

Thuy Points 568

Vous pouvez jeter un oeil à mon GTScrollNavigationBar. J’ai une sous-classe UINavigationBar pour le rendre défilement basé sur le défilement d’un UIScrollView.

Remarque : Si vous avez une barre de navigation OPAQUE, le scrollview doit développer comme la barre de navigation devient cachée. C’est exactement ce que GTScrollNavigationBar. (Comme par exemple Safari sur iOS.)

12voto

peerless Points 435

J’ai une sorte d’une solution rapide et sale pour cela. N’ont pas fait n’importe quel test approfondi mais voici l’idée :

Cette propriété gardera tous les éléments dans la barre de navigation pour mon cours d’UITableViewController

Dans la même classe de UITableViewController j’ai :

C’est seulement pour ios > = 7, c' est laid, je sais, mais un moyen rapide d’y parvenir. Des commentaires ou suggestions sont les bienvenus  :)

10voto

Valentin Shergin Points 370

Voici mon implémentation : SherginScrollableNavigationBar.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X