首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >模拟Facebook隐藏/显示扩展/收缩导航栏

模拟Facebook隐藏/显示扩展/收缩导航栏
EN

Stack Overflow用户
提问于 2013-11-07 01:50:40
回答 20查看 95K关注 0票数 129

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

您自己如何实现此行为?我知道下面的解决方案,但它马上就消失了,而且它与用户滚动手势的速度没有任何关系。

代码语言:javascript
运行
复制
[navigationController setNavigationBarHidden: YES animated:YES];

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

EN

回答 20

Stack Overflow用户

发布于 2014-01-11 00:54:47

@peerless给出的解决方案是一个很好的开始,但它只在拖动开始时启动动画,而没有考虑滚动的速度。这比你在Facebook应用程序中得到的体验更不稳定。为了与Facebook的行为相匹配,我们需要:

  • 隐藏/显示导航栏的速率与拖动
  • 启动动画的速率成正比。如果滚动停止,则完全隐藏导航栏。
  • 在导航栏缩小时淡入淡出导航栏的项目。

首先,您需要以下属性:

代码语言:javascript
运行
复制
@property (nonatomic) CGFloat previousScrollViewYOffset;

下面是UIScrollViewDelegate方法:

代码语言:javascript
运行
复制
- (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];
    }
}

您还需要以下助手方法:

代码语言:javascript
运行
复制
- (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];
    }];
}

对于稍有不同的行为,请将滚动时重新定位条的行(scrollViewDidScroll中的else块)替换为以下行:

代码语言:javascript
运行
复制
frame.origin.y = MIN(20, 
                     MAX(-size, frame.origin.y - 
                               (frame.size.height * (scrollDiff / scrollHeight))));

这将根据上次滚动百分比而不是绝对量来定位条形图,这会导致较慢的淡入度。最初的行为更像Facebook,但我也喜欢这个。

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

票数 162
EN

Stack Overflow用户

发布于 2015-02-24 23:59:56

编辑:仅适用于iOS 8及更高版本。

您可以尝试使用

代码语言:javascript
运行
复制
self.navigationController.hidesBarsOnSwipe = YES;

这对我很有效。

如果你在swift中编码,你必须使用这种方式(来自https://stackoverflow.com/a/27662702/2283308)

代码语言:javascript
运行
复制
navigationController?.hidesBarsOnSwipe = true
票数 52
EN

Stack Overflow用户

发布于 2014-06-27 22:28:08

这是另一个实现: v1.0.0发布!

在尝试了提供的解决方案后,我决定自己制作一个解决方案,对我来说,它们要么表现不佳,要么具有很高的入门门槛和样板代码,要么缺乏导航栏下的扩展视图。要使用这个组件,您需要做的就是:

代码语言:javascript
运行
复制
self.shyNavBarManager.scrollView = self.scrollView;

哦,而且它在我们自己的应用程序中经过了战斗测试。

票数 43
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19819165

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档