用动画同时隐藏导航栏和选项卡栏

2024-04-17

Edit:我将赏金授予了约翰,因为他在回答中付出了很多努力,并且无论如何都会得到它,但仍然没有可行的解决方案。我仍在寻找答案,如果有人知道如何做到这一点,我将不胜感激。

我想在我的应用程序中添加一个“最大化”按钮来隐藏导航和标签栏。导航栏和选项卡栏应平滑滑入/滑出,内部/内容视图也应以与导航栏和选项卡栏相同的速率扩展和收缩。

I used [self.navigationController setNavigationBarHidden: YES/NO animated: YES];对于导航栏并找到了这个线程如何隐藏uitabbarcontroller https://stackoverflow.com/questions/5272290/how-to-hide-uitabbarcontroller用于隐藏标签栏。

UITabBar 类扩展:

- (void) setTabBarHidden:(BOOL)hidden animated:(BOOL)animated {
    CGRect screenRect = [[UIScreen mainScreen] bounds];

    float screenHeight = screenRect.size.height;
    if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) {
        screenHeight = screenRect.size.width;
    }
    if (!hidden) {
        screenHeight -= self.tabBar.frame.size.height;
    }
    [UIView animateWithDuration: (animated ? UINavigationControllerHideShowBarDuration : 0) animations: ^{
        for (UIView* each in self.view.subviews) {
            if (each == self.tabBar) {
                [each setFrame: CGRectMake(each.frame.origin.x, screenHeight, each.frame.size.width, each.frame.size.height)];
            } else {
                [each setFrame: CGRectMake(each.frame.origin.x, each.frame.origin.y, each.frame.size.width, screenHeight)];
            }
        }
    } completion: ^(BOOL finished) {
        NSLog(@"Animation finished %d", finished);
    }];
}

问题是当我同时使用两者(隐藏/显示导航栏和选项卡栏)时,它不干净。如果导航栏先出现,则锚定到底部的任何内容都会跳转(请参见下面的示例),如果标签栏先出现,则顶部会跳转。

示例:我将 UIButton 放置在右下角并设置其自动调整大小蒙版

resizeButton.frame = CGRectMake(self.view.bounds.size.width - 50, self.view.bounds.size.height - 100, 32, 32); // hardcoded just for testing purposes
resizeButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin;

但是,当导航栏和选项卡栏最小化时,UIButton 在两种状态之间跳转(不与选项卡栏一起滑动)。但是,如果我将其更改为附加到右上角,它会与导航栏完美滑动。

有谁知道如何解决这个问题?


Edit: 这是迄今为止我拥有的最衣柜和最优雅的解决方案(只是想得到一个可行的概念):

[UIView animateWithDuration: UINavigationControllerHideShowBarDuration animations: ^{
    if (self.isMaximized) {
        self.tabBarController.view.frame = CGRectMake(0, 20, screenRect.size.width, screenRect.size.height + 49 - 20);
        [self.navigationController setNavigationBarHidden:YES animated:YES];
    } else {
        self.tabBarController.view.frame = CGRectMake(0, 20, screenRect.size.width, screenRect.size.height - 20);
        [self.navigationController setNavigationBarHidden:NO animated:YES];
    }
} completion: ^(BOOL finished) {
    NSLog(@"Frame done: %@", NSStringFromCGRect(self.view.frame));
    return;
}];

关于最大化:

  • 同时向上滑动导航栏并向下滑动选项卡栏
  • 内部/内容视图的顶部向上滑动,该视图的底部向下跳转

关于最小化:

  • 同时向下滑动导航栏并向上滑动选项卡栏
  • 内部/内容视图的顶部正确向下滑动,但底部跳转到最终值,留下空白,然后被滑动标签栏覆盖

如果我重新排列最小化动画的顺序(因此首先调用导航栏动画),则内部/内容视图中的顶部会跳转


我使用的解决方案应该消除您看到的跳跃问题。

该解决方案源自 Objective-C 类别发现卡洛斯·奥利瓦 (Carlos Oliva) 的 github 页面 https://github.com/idevsoftware/Cocoa-Touch-Additions/blob/master/UITabBarController_setHidden/UITabBarController+HideTabBar.m,虽然该代码的版权是“保留所有权利”,但我写信给他,他提供了使用许可。

我的类别代码与他的代码仅略有不同。另外,在类别代码下方找到我在应用程序中使用的调用代码。

来自 UITabBarController+HideTabBar.m

// the self.view.frame.size.height can't be used directly in isTabBarHidden or
// in setTabBarHidden:animated: because the value may be the rect with a transform.
//
// further, an attempt to use CGSizeApplyAffineTransform() doesn't work because the
// value can produce a negative height.
// cf. http://lists.apple.com/archives/quartz-dev/2007/Aug/msg00047.html
//
// the crux is that CGRects are normalized, CGSizes are not.

- (BOOL)isTabBarHidden {
    CGRect viewFrame = CGRectApplyAffineTransform(self.view.frame, self.view.transform);
    CGRect tabBarFrame = self.tabBar.frame;
    return tabBarFrame.origin.y >= viewFrame.size.height;
}


- (void)setTabBarHidden:(BOOL)hidden {
    [self setTabBarHidden:hidden animated:NO];
}


- (void)setTabBarHidden:(BOOL)hidden animated:(BOOL)animated {
    BOOL isHidden = self.tabBarHidden;
    if (hidden == isHidden)
        return;
    UIView* transitionView = [self.view.subviews objectAtIndex:0];

    if (!transitionView)
    {
#if DEBUG
    NSLog(@"could not get the container view!");
#endif
        return;
    }

    CGRect viewFrame = CGRectApplyAffineTransform(self.view.frame, self.view.transform);
    CGRect tabBarFrame = self.tabBar.frame;
    CGRect containerFrame = transitionView.frame;
    tabBarFrame.origin.y = viewFrame.size.height - (hidden ? 0 : tabBarFrame.size.height);
    containerFrame.size.height = viewFrame.size.height - (hidden ? 0 : tabBarFrame.size.height);
    [UIView animateWithDuration:kAnimationDuration 
                     animations:^{
                         self.tabBar.frame = tabBarFrame;
                         transitionView.frame = containerFrame;
                     }
     ];
}

来自我的 ScrollableDetailImageViewController.m

- (void)setBarsHidden:(BOOL)hidden animated:(BOOL)animated
{
    [self setTabBarHidden:hidden animated:animated];
    [self setStatusBarHidden:hidden animated:animated];

    // must be performed after hiding/showing of statusBar
    [self.navigationController setNavigationBarHidden:hidden animated:animated];
}

- (void)setTabBarHidden:(BOOL)hidden animated:(BOOL)animated
{
    id parent = self.navigationController.parentViewController;
    if ([parent respondsToSelector:@selector(isTabBarHidden)]
        && hidden != [parent isTabBarHidden]
        && [parent respondsToSelector:@selector(setTabBarHidden:animated:)])
        [parent setTabBarHidden:hidden animated:animated];
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用动画同时隐藏导航栏和选项卡栏 的相关文章

随机推荐