像 Safari 应用程序一样拖动时如何隐藏标签栏?

Posted

技术标签:

【中文标题】像 Safari 应用程序一样拖动时如何隐藏标签栏?【英文标题】:How to hide tab bar when dragging like Safari app? 【发布时间】:2013-11-16 03:35:36 【问题描述】:

我想知道如何实现一个在向下拖动时隐藏标签栏的动画,例如 ios 7 上的 Safari 应用程序。如果您提供任何信息,我们将不胜感激。

类似问题:Show/hide UIToolbar, "match finger movement", precisely as in for example iOS7 Safari.

【问题讨论】:

尝试在cocoacontrols.com/controls上搜索您想要的自定义控件 谢谢,我现在正在检查。 cocoacontrols.com/search?utf8=%E2%9C%93&q=tabbar 拜托,所以你的代码。 【参考方案1】:

这样的事情应该可以工作。我不知道这是否与 Safari 应用程序的外观完全相同,但很接近:

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (nonatomic) CGRect originalFrame;
@end

@implementation ViewController

- (void)viewDidAppear:(BOOL)animated 
    [super viewDidAppear:animated];
    self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width, 1000);
    self.originalFrame = self.tabBarController.tabBar.frame;



-(void)scrollViewDidScroll:(UIScrollView *)scrollView 
    UITabBar *tb = self.tabBarController.tabBar;
    NSInteger yOffset = scrollView.contentOffset.y;
    if (yOffset > 0) 
        tb.frame = CGRectMake(tb.frame.origin.x, self.originalFrame.origin.y + yOffset, tb.frame.size.width, tb.frame.size.height);
    
   if (yOffset < 1) tb.frame = self.originalFrame;

【讨论】:

谢谢!有用!你和下面的这个网站对我帮助很大。 developers-life.com/… 我需要同样的效果。但是如果是 UITableview 我该如何实现呢?需要隐藏和显示导航栏和工具栏 UITableView 扩展了 UIScrollView 所以你可以使用与上面相同的方法 从逻辑上讲,这是有道理的。但我无法让它工作。标签栏框架始终为:0, 0, 0, 0。有没有其他人遇到过这个?【参考方案2】:

当您在表格视图中有很多单元格时,接受的答案不起作用 - 只有当您一直滚动到顶部时,标签栏才会显示。

我是这样改进的:

- (void)viewDidAppear:(BOOL)animated 
    [super viewDidAppear:animated];
    self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width, 1000);
    self.originalFrame = self.tabBarController.tabBar.frame;



-(void)scrollViewDidScroll:(UIScrollView *)scrollView

UITabBar *tabBar = self.tabBarController.tabBar;

NSInteger yOffset = scrollView.contentOffset.y;
CGFloat yPanGesture = [scrollView.panGestureRecognizer translationInView:self.view].y;
CGFloat heightTabBar = tabBar.frame.size.height;

CGFloat tabBarOriginY = tabBar.frame.origin.y;
CGFloat frameHeight = self.view.frame.size.height;

if(yOffset>=heightTabBar)
    yOffset = heightTabBar;

// GOING UP ------------------
if(yPanGesture >= 0 && yPanGesture < heightTabBar && tabBarOriginY > frameHeight-heightTabBar)
    yOffset = heightTabBar - fabsf(yPanGesture);

else if(yPanGesture >= 0 && yPanGesture < heightTabBar && tabBarOriginY <= frameHeight-heightTabBar)
    yOffset = 0;

// GOING DOWN ------------------
else if(yPanGesture < 0 && tabBarOriginY < frameHeight)
    yOffset = fabsf(yPanGesture);
else if(yPanGesture < 0 && tabBarOriginY >= frameHeight)
    yOffset = heightTabBar;

else
    yOffset = 0;


if (yOffset > 0) 
    tabBar.frame = CGRectMake(tabBar.frame.origin.x, self.originalFrame.origin.y + yOffset, tabBar.frame.size.width, tabBar.frame.size.height);

else if (yOffset <= 0)
    tabBar.frame = self.originalFrame;



    - (void)scrollViewWillEndDragging:(UIScrollView*)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset 

// Handle unfinished animations   
    UITabBar *tabBar = self.tabBarController.tabBar;
    CGFloat yPanGesture = [scrollView.panGestureRecognizer translationInView:self.view].y;
    CGFloat heightTabBar = tabBar.frame.size.height;
    CGFloat tabBarOriginY = tabBar.frame.origin.y;
    CGFloat frameHeight = self.view.frame.size.height;


    if(yPanGesture > 0)

        if(tabBarOriginY != frameHeight - heightTabBar) 

            [UIView animateWithDuration:0.3 animations:^(void)
                tabBar.frame = self.originalFrame;
            ];

        

    else if(yPanGesture < 0)

    if (tabBarOriginY != frameHeight) 
        [UIView animateWithDuration:0.3 animations:^(void)
            tabBar.frame = CGRectMake(tabBar.frame.origin.x, frameHeight, tabBar.frame.size.width, tabBar.frame.size.height);
        ];
    




【讨论】:

这在屏幕上看起来非常有问题。 非常适合我!虽然我并不真的需要 scrollViewWillEndDragging 位 对我来说效果很好。这应该是公认的答案。【参考方案3】:

老实说,我尝试了所有这些解决方案,但它们对我来说还不够强大。他们会隐藏应该显示的标签栏,或者他们以一种奇怪的方式向上移动标签栏。

我最终花了一整天的时间让他们工作。终于放弃使用了:https://github.com/tristanhimmelman/HidingNavigationBar。

这给了我隐藏导航栏和标签栏的功能(这是我最初真正想要的)。它运行得非常好,我在 10 分钟内就完成了设置。

希望这可以帮助其他人不要为此浪费一天的编码:-0。

【讨论】:

【参考方案4】:

您可以使用变量来保留 lastContentOffset 值。 关键思想是标签栏 origin.y 介于 CGRectGetMaxY(screenRect) 和 CGRectGetMaxY(screenRect) - CGRectGetHeight(tabBarRect) 之间。

它在我的项目中运行良好。

@interface ViewController ()
    @property (nonatomic, assign) CGFloat lastContentOffsetY;
@end

@implementation ViewController
-(void)scrollViewDidScroll:(UIScrollView *)scrollView

    if (!self.tabBarController) 
      return;
    

  BOOL isStatusBarHidden = [UIApplication sharedApplication].isStatusBarHidden;
  CGFloat kStatusBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height;

if (scrollView.contentOffset.y > (scrollView.contentSize.height - scrollView.frame.size.height)
    || (scrollView.contentOffset.y < (isStatsuBarHidden ? 0 : -kStatusBarHeight))) 
    // bottom & top bouncing - don't need to update
    return;


CGFloat offset = scrollView.contentOffset.y - self.lastContentOffsetY;
CGRect tabBarRect = self.tabBarController.tabBar.frame;
CGRect screenRect = [UIScreen mainScreen].bounds;

if (CGRectGetMaxY(tabBarRect) == CGRectGetMaxY(screenRect) + CGRectGetHeight(tabBarRect)) 
    //view could only scroll downward
    if (offset < 0) 
        tabBarRect.origin.y += offset;
    
 else if (CGRectGetMaxY(tabBarRect) == CGRectGetMaxY(screenRect)) 
    //view could only scroll upward
    if (offset > 0) 
        tabBarRect.origin.y += offset;
    
 else 
    //view could scroll upward & downward
    tabBarRect.origin.y += offset;


//safty reset handling
if (CGRectGetMaxY(tabBarRect) > CGRectGetMaxY(screenRect) + CGRectGetHeight(tabBarRect)) 
    tabBarRect.origin.y = CGRectGetMaxY(screenRect);
 else if (CGRectGetMaxY(tabBarRect) < CGRectGetMaxY(screenRect)) 
    tabBarRect.origin.y = CGRectGetMaxY(screenRect) - CGRectGetHeight(tabBarRect); // over bouncing, set it back


self.tabBarController.tabBar.frame = tabBarRect;
self.lastContentOffsetY = scrollView.contentOffset.y;

【讨论】:

【参考方案5】:

好吧,虽然其他人的所有答案都不起作用或部分起作用,但 @RobNorback 的 HidingNavigationBar 非常出色,而且实际上很容易设置。

但是,我在框架方面遇到了一些困难,并且花了 2 个小时来修复它,所以我加了两分钱,以免有人陷入同样的​​困境。

如果您的集合视图或表格视图中的项目或行数很少,它不会隐藏导航栏(或选项卡栏或工具栏),即使项目或行数足够大超出屏幕您应该添加更多项目或行以使框架正确隐藏栏。

【讨论】:

【参考方案6】:
static CGFloat navBarOriginY = 20.0;

为导航栏原点 Y 位置的基值创建常量

- (void)viewDidLoad 
[super viewDidLoad];
 self.navigationController.hidesBarsOnSwipe = true;
[self.navigationController.barHideOnSwipeGestureRecognizer addTarget:self action:@selector(swipe:)];

添加您的自定义选择器以处理将在 navBar 隐藏之前和隐藏期间触发的系统滑动手势

- (void)swipe:(UIPanGestureRecognizer *)recognizer 
if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled || recognizer.state == UIGestureRecognizerStateFailed) 

如果手势状态结束/取消或失败,您需要完全更改 tabBar 的框架

    CGRect finalFrame = self.tabBarController.tabBar.frame;
    if (self.navigationController.navigationBar.frame.origin.y < 0) 
         //Tab bar will be hidden
        finalFrame.origin.y = self.maxTabBarY;
     else 
         //Tab bar will be visible
        finalFrame.origin.y = self.minTabBarY;
    

    [self setFrameForTabBar:finalFrame animationDuration:0.3];

 else if (recognizer.state == UIGestureRecognizerStateChanged) 

如果 state == 发生变化,您需要像在 Safari 应用程序中一样使用 navBar 平移 tabBar。

    CGRect frame = self.tabBarController.tabBar.frame;
    CGFloat delta = navBarOriginY - self.navigationController.navigationBar.layer.presentationLayer.frame.origin.y;
    frame.origin.y = self.minTabBarY + delta;
    [self setFrameForTabBar:frame animationDuration:0.0];
  

- (void)setFrameForTabBar:(CGRect)frame animationDuration:(CGFloat)duration 
dispatch_async(dispatch_get_main_queue(), ^
    [UIView animateWithDuration:duration delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^
        self.tabBarController.tabBar.frame = frame;
     completion:^(BOOL finished) ];
);

【讨论】:

以上是关于像 Safari 应用程序一样拖动时如何隐藏标签栏?的主要内容,如果未能解决你的问题,请参考以下文章

ipad浏览器全屏隐藏状态栏

如何创建一个像 Instagram 主页一样的页面视图控制器,它也可以滚动标签栏?

用小标题隐藏导航栏iOS

防止 Safari 地址栏在 iOS 15 中展开

ios7 safari的地址栏用jquery怎么隐藏?

有没有办法从 iOS9 的状态栏中隐藏“返回 Safari”?