为啥使用半透明导航栏刹车推动动画将“hidesBottomBarWhenPushed”设置为 YES?

Posted

技术标签:

【中文标题】为啥使用半透明导航栏刹车推动动画将“hidesBottomBarWhenPushed”设置为 YES?【英文标题】:Why does setting `hidesBottomBarWhenPushed` to YES with a translucent navigationBar break push animation?为什么使用半透明导航栏刹车推动动画将“hidesBottomBarWhenPushed”设置为 YES? 【发布时间】:2015-01-30 21:39:46 【问题描述】:

我有一个我认为相当常见的设置,但我看到一个非常奇怪的动画问题。

标签栏内有一个导航控制器。如果我推动该导航控制器,我仍然可以在推动动画期间在导航栏中看到前一个 viewController 的红色视图,但只有当我将目标 viewController 上的hidesBottomBarWhenPushed 设置为yes 时(在最右边)。这是该问题的一个简化示例,它都可以在情节提要中进行设置。

这是过渡的动画。观看导航栏。你可以在后台看到之前的红色视图控制器,部分离开屏幕,然后在最后消失。

有人解决了这个问题吗?我在做一些不受支持的事情吗?这是一个错误吗?我绝对想保留半透明栏并在推送时隐藏标签栏,但我愿意以其他支持半透明标签栏的方式可靠地隐藏标签栏。

【问题讨论】:

您找到发生这种情况的原因了吗? 作为线索,我发现最右侧视图控制器中的视图在完成推送后“移动”以适应屏幕。与自动布局有关? 不,我没有。现在我推迟实施半透明导航栏,直到找到一个好的解决方案。 您是否尝试过我的解决方案...它对我有用...让我知道它是否对您有帮助... 这有点hacky,但你可以尝试设置TabBarController 的视图的背景颜色。它应该会有所帮助。 【参考方案1】:

这是我目前发现的:

#1 右上角是黑色的

顶栏右上方模糊的黑色部分是半透明UINavigationbar后面的UIWindowbackgroundColor默认为blackColor

屏幕截图通过将推送视图的背景设置为 clearColor 来演示这一点。

作为一种解决方法,将UIWindowbackgroundColor 属性设置为所需的背景颜色可以解决此问题,只要您还拥有要推送的视图控制器的属性edgesForExtendedLayout 设置为.Top

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool 
    window?.backgroundColor = UIColor.whiteColor()
    return true


class ViewToPushViewController: UIViewController 
    override func viewDidLoad() 
        super.viewDidLoad()
        self.edgesForExtendedLayout = UIRectEdge.Top
        // Or set it from the Attributes Inspector in IB.
        // See screenshot below.
    

我认为这是一种解决方法,因为我认为修改 UIWindow 的 backgroundColor 属性不一定是我们应该做的。或许,未来的 ios 版本可以解决这个问题。

#2 推送动画结束后查看内容“向下移动”

如果您有一个带有底部布局指南的子视图并且视图“向下移动”,我还没有找到任何理想的修复方法。但是,将标签栏设置为隐藏在一定程度上有所帮助。需要注意的是,正如预期的那样,隐藏标签栏也会在推送动画期间立即从父视图控制器中隐藏它(尽管在弹出视图时它会在动画期间再次可见)。

class ViewToPushViewController: UIViewController 
    override func viewDidLoad() 
        super.viewDidLoad()

        // ...

        self.tabBarController?.tabBar.hidden = true
    

确保 ViewToPushViewController 的 hidesBottomBarWhenPushed 属性在被推送之前设置为 true(在界面构建器属性检查器中或在父视图控制器中的 prepareForSegue 方法中)。

确保在使用后退按钮弹出视图时还测试动画行为。

【讨论】:

#1 对我不起作用。将窗口的背景颜色设置为蓝色后(参见此处imgur.com/AaL4avY),您可以看到颜色出现在栏下方,但它只是延伸了一部分。即使我选择使用绿色而不是蓝色,它也不会对齐。 而#2 并不令人满意。立即隐藏标签栏太突然,看起来可能比半透明问题更糟糕。不过感谢您的建议! 是的,我同意 #2 不是一个令人满意的解决方案。对于#1,您是否设置了self.edgesForExtendedLayout = UIRectEdge.Top?如果这样设置,您可能只需要设置窗口 bgColor 即可让弹出动画生效。 对于#1,我将edgesForExtendedLayout 保留为第一个 viewController 的默认 UIRectEdgeAll(需要在半透明标签栏下有内容),并且我已经尝试了 UIRectEdgeTop 和 All目标viewController,两者都不起作用。您为#1 包含的图像似乎没有标签栏。也许这就是它看起来适合你的原因? 它有一个标签栏,它在父视图中可见(在图片中带有那些表格分隔符),但在视图被推送时被隐藏。【参考方案2】:

你可能有 UITabBarController 类,它的背景是空的。 并且窗口默认背景为黑色。

在 Swift 2 中

在不改变应用结构的情况下:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool 
    // Override point ...
    window?.backgroundColor = UIColor.whiteColor()
    return true

【讨论】:

【参考方案3】:

设置 UITabBarController 的视图 backgroundColor 可能会起作用

【讨论】:

【参考方案4】:

我设置了我的故事板,就像你用相同的 segues 等展示的一样,得到了同样奇怪的动画。在四处寻找解决方案并使用代码后,我得到了这个。

在目标视图控制器中使用它,希望这会有所帮助。

- (void)viewDidLoad

    [super viewDidLoad];

    [self hideTabBar];


- (void)viewWillDisappear:(BOOL)animated

    [super viewWillDisappear:animated];

    [self showTabBar];


- (void)hideTabBar

    UITabBar *tabBar = self.tabBarController.tabBar;
    UIView *parent = tabBar.superview;
    UIView *content = [parent.subviews objectAtIndex:0];
    UIView *window = parent.superview;

    [UIView animateWithDuration:0.5
                     animations:^
                         CGRect tabFrame = tabBar.frame;
                         tabFrame.origin.y = CGRectGetMaxY(window.bounds);
                         tabBar.frame = tabFrame;
                         content.frame = window.bounds;
                     ];


- (void)showTabBar

    UITabBar *tabBar = self.tabBarController.tabBar;
    UIView *parent = tabBar.superview;
    UIView *content = [parent.subviews objectAtIndex:0];
    UIView *window = parent.superview;

    [UIView animateWithDuration:0.5
                     animations:^
                         CGRect tabFrame = tabBar.frame;
                         tabFrame.origin.y = CGRectGetMaxY(window.bounds) - CGRectGetHeight(tabBar.frame);
                         tabBar.frame = tabFrame;

                         CGRect contentFrame = content.frame;
                         contentFrame.size.height -= tabFrame.size.height;
                     ];

附:你是怎么做出这么酷的 gif 的,会派上用场的。

【讨论】:

我使用 Quicktime 创建了一个屏幕录制,使用 ffmpeg 将其转换为一系列 PNG,sips 将它们交换为“gif”图像(主要用于压缩),然后使用 gifsicle 进行合并他们在一起。这是一个很好的指南 (chrismessina.me/b/13913393/mov-to-gif)。我认为 App Store 上有一步应用程序,但这是免费的 =) 谢谢,以后会用到。 @Acey 你试过我的代码了吗?或者你有没有想出另一种方法。如果是这样,请在此处展示,以便我了解您是如何做到的。 我真的不想手动定位标签栏。这似乎是 UITabBarController 的工作。从标签栏容器视图中获取第一个子视图也不安全,并且不能保证在不同版本的 iOS 上工作,具体取决于 UITabBarController 的实现。从这里推送到另一个视图控制器时,也存在显示标签栏的问题。当我们希望它保持隐藏时,标签栏会返回,这是 hidesBottomBarWhenPush 提供的。另外,如何将导航控制器推送和弹出到根目录?需要维护的状态太多。 你想清楚了,请上传到这里让我看看。【参考方案5】:

只需在应用程序中设置窗口的背景颜色和导航栏的外观:didFinishLaunchingWithOptions:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
    self.window.backgroundColor = [UIColor whiteColor];
    [UINavigationBar appearance].translucent = NO;
    return YES;

【讨论】:

【参考方案6】:

我找到了 Objective-C 的答案!即使它适合您的情况!

AnotherViewController *av = [[AnotherViewController alloc] init];

// 设置控制器视图的颜色

self.navigationController.view.backgroundColor = [UIColor whiteColor];

[self setHidesBottomBarWhenPushed:YES];

[self.navigationController pushViewController:av animated:YES];

如果你将视图的颜色更改为特定颜色(Red, Blue...),你就会知道这段代码是如何工作的~

【讨论】:

以上是关于为啥使用半透明导航栏刹车推动动画将“hidesBottomBarWhenPushed”设置为 YES?的主要内容,如果未能解决你的问题,请参考以下文章

可靠获取状态栏高度解决KitKat半透明导航问题

可靠获取状态栏高度解决KitKat半透明导航问题

无法使 UITableView 出现在半透明导航栏下

iPhone:UITabBarController 内的半透明导航栏

导航栏背景颜色 - 半透明是没有

iOS Autolayout - 在半透明导航栏下方正确定位视图