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.