类似 Instagram 的导航栏 (iOS 7)

Posted

技术标签:

【中文标题】类似 Instagram 的导航栏 (iOS 7)【英文标题】:Instagram-like navigation bar (iOS 7) 【发布时间】:2013-11-28 19:07:38 【问题描述】:

我正在尝试产生与 instagram 标题中相同的效果。我该怎么做?

我尝试了很多解决方案。

最佳 - https://github.com/andreamazz/AMScrollingNavbar

但它有一个大问题 - 它使用 uipangesturerecognizer 移动条。这对我很不利,因为如果桌子在顶部,我想显示栏。

我尝试将此控件的工作更改为滚动视图委托,但发现它有很多问题,您有什么想法,他们是如何做到的?

【问题讨论】:

【参考方案1】:

我找到了解决方案,就像你说的那样 - 你必须稍微弄乱滚动视图委托,但大约 2 小时后我就搞定了。我试图解决的问题是能够像在 Instagram 中那样以一个连续的动作将标题取出。

所以,首先检查 xib 设置,它在 (0 20, 320 85) 处有一个标题视图,它位于 (0 20, 320 548) 处的表视图后面

这是启动后的样子(黄色的表格视图框架):

这是我希望它在下拉后的样子(红色标题框):

所以我只是用 cmets 粘贴代码,我希望它可以理解。

定义

#define SIGNIFICANT_SCROLLING_DISTANCE 200

创建两个属性

@property (nonatomic) CGFloat lastScrollViewOffsetY;
@property (nonatomic) CGFloat distancePulledDownwards;

比为scrollViewDidScroll委托方法添加以下实现

- (void)scrollViewDidScroll:(UIScrollView *)scrollView

    // store current scroll view frame as we will change it later on and set it
    // back to the scroll view in the very end
    CGRect currentScrollViewRect = scrollView.frame;
    // same with the content offset
    CGPoint currentScrollViewOffset = scrollView.contentOffset;
    CGFloat offsetShiftY = self.lastScrollViewOffsetY - scrollView.contentOffset.y;

    if (offsetShiftY > 0) 
        // pulling downwards
        // keep trrack of the distance that we pulled downwards
        self.distancePulledDownwards += offsetShiftY;

        // header opens (table view shifts its frame down) in two cases:
        // 1. contentOffset.y<0
        // 2. scrolled downwards a significant amount or header is already open
        // but in both cases we have to make sure that it doesn't open further than we want it to
        CGFloat wantedOriginY = currentScrollViewRect.origin.y;
        if ((scrollView.contentOffset.y<0) || (self.distancePulledDownwards > SIGNIFICANT_SCROLLING_DISTANCE) || (currentScrollViewRect.origin.y>20))

            // shift scroll views frame by offset shift
            wantedOriginY = currentScrollViewRect.origin.y + offsetShiftY;
            // compensate that shift by moving content offset back
            currentScrollViewOffset.y += (wantedOriginY <= 105) ? offsetShiftY : 0;
        
        currentScrollViewRect.origin.y = (wantedOriginY <= 105) ? wantedOriginY : 105;

    
    else 
        // pulling upwards
        self.distancePulledDownwards = 0;

        // header closes (table view shifts its frame up) in one case: when it is open =) (and contentOffset.y>0 to eliminate closing on bounce)
        if (scrollView.contentOffset.y > 0) 
            CGFloat wantedOriginY = currentScrollViewRect.origin.y + offsetShiftY;
            currentScrollViewRect.origin.y = (wantedOriginY >= 20) ? wantedOriginY : 20;
            currentScrollViewOffset.y += (wantedOriginY >= 20) ? offsetShiftY : 0;
        
    

    // set the changed (if it was changed at all) frame to the scroll view
    [scrollView setFrame:currentScrollViewRect];

    // correct offset using a special trick
    // it ensures that scrollViewDidScroll: won't be called on setting the offset
    scrollView.delegate = nil;
    [scrollView setContentOffset:currentScrollViewOffset];
    scrollView.delegate = self;

    // and finally remember the current offset as the last
    self.lastScrollViewOffsetY = scrollView.contentOffset.y;

并享受您在屏幕上来回滚动的流畅表格 =) 这也可以修改,您可以添加和调整标题,使其与 Instagram 基本相同。

【讨论】:

scrollView.delegate = nil; [scrollView setContentOffset:currentScrollViewOffset]; scrollView.delegate = 自我;这为我节省了几个小时,谢谢 这应该被选为答案【参考方案2】:

在 tableViewController 中使用 AMScrollingNavbar 并覆盖 willDisplayCell 方法以在表格滚动到顶部时显示栏:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath

    if (indexPath.row == 0) 
        [self showNavbar];
    

【讨论】:

【参考方案3】:

您可以在您的课程中使用下面提到的方法,在其中您想要在导航栏上添加效果,就像在 Instagram 中一样。

- (void)scrollViewDidScroll:(UIScrollView *)sender 
//Initializing the views and the new frame sizes.
UINavigationBar *navbar =self.navigationController.navigationBar;
UIView *tableView = self.view;
CGRect navBarFrame = self.navigationController.navigationBar.frame;

CGRect tableFrame = self.view.frame;

//changing the origin.y based on the current scroll view.
//Adding +20 for the Status Bar since the offset is tied into that.

if (isios7) 
     navBarFrame.origin.y = MIN(0, MAX(-44, (sender.contentOffset.y * -1)))  +20 ;
     tableFrame.origin.y = navBarFrame.origin.y + navBarFrame.size.height;
else
    navBarFrame.origin.y = MIN(0, (sender.contentOffset.y * -1)) +20;
    tableFrame.origin.y = MIN(0,MAX(-44,(sender.contentOffset.y * -1))) ;


navbar.frame = navBarFrame;
tableView.frame = tableFrame;

【讨论】:

这很好用,但导航栏只有在您滚动到顶部时才会重新出现。如果您决定在任何时候向上滚动,如何再次显示导航栏?【参考方案4】:

使用该库,将其添加到您的视图控制器:

- (BOOL)scrollViewShouldScrollToTop 
    [self showNavbar];
    return YES;

【讨论】:

或 scrollViewDidScrollToTop 然后你就不必返回任何东西了。

以上是关于类似 Instagram 的导航栏 (iOS 7)的主要内容,如果未能解决你的问题,请参考以下文章

使用单独的 backstack 创建类似底部导航的 Instagram

ios 7状态栏不继承导航栏颜色

让导航栏与iOS 7中的状态栏重叠

iOS 7 导航栏中的搜索栏

iOS 7 清除导航栏

在iOS 7中隐藏导航栏时,如何更改状态栏的颜色?