模仿Facebook隐藏/显示扩展/收缩导航栏 [英] Imitate Facebook hide/show expanding/contracting Navigation Bar

查看:113
本文介绍了模仿Facebook隐藏/显示扩展/收缩导航栏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在新的iOS7 Facebook iPhone应用程序中,当用户向上滚动时, navigationBar 会逐渐隐藏到完全消失的程度。然后当用户向下滚动时, navigationBar 逐渐显示出来。

In the new iOS7 Facebook iPhone app, when the user scrolls up the navigationBar gradually hides itself to a point where it completely vanishes. Then when the user scrolls down the navigationBar gradually shows itself.

您将如何自己实施此行为?我知道以下解决方案,但它立即消失,它根本不依赖于用户的滚动手势的速度。

How would you implement this behavior yourself? I am aware of the following solution but it disappears right away and it isn't tied to the speed of the user's scroll gesture at all.

[navigationController setNavigationBarHidden: YES animated:YES];

我希望这不是重复,因为我不确定如何最好地描述扩展/收缩行为。

I hope this isn't a duplicate as I'm not sure how best to describe the "expanding/contracting" behavior.

推荐答案

@peerless给出的解决方案是一个很好的开始,但它只会在拖动时启动动画开始,不考虑滚动的速度。这会导致比Facebook应用程序更糟糕的体验。为了匹配Facebook的行为,我们需要:

The solution given by @peerless is a great start, but it only kicks off an animation whenever dragging begins, without considering the speed of the scroll. This results in a choppier experience than you get in the Facebook app. To match Facebook's behavior, we need to:


  • 以与拖动率成比例的速率隐藏/显示导航栏

  • 如果在部分隐藏栏时滚动停止,则启动动画以完全隐藏栏。

  • 在栏缩小时淡化导航栏的项目。

首先,您需要以下房产:

First, you'll need the following property:

@property (nonatomic) CGFloat previousScrollViewYOffset;

以下是 UIScrollViewDelegate 方法:

- (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];
    }
}

您还需要这些辅助方法:

You'll also need these helper methods:

- (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];
    }];
}

对于略有不同的行为,请更换重新定位栏的行使用以下内容滚动( else scrollViewDidScroll ):

For a slightly different behavior, replace the line that re-positions the bar when scrolling (the else block in scrollViewDidScroll) with this one:

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

这会根据最后一个滚动百分比定位条形,而不是绝对数量,这会导致慢慢褪色。原来的行为更像Facebook,但我也喜欢这个。

This positions the bar based on the last scroll percentage, instead of an absolute amount, which results in a slower fade. The original behavior is more Facebook-like, but I like this one, too.

注意:此解决方案仅适用于iOS 7+。如果您支持旧版本的iOS,请务必添加必要的检查。

Note: This solution is iOS 7+ only. Be sure to add the necessary checks if you're supporting older versions of iOS.

这篇关于模仿Facebook隐藏/显示扩展/收缩导航栏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆