How can I work around hidesBottomBarWhenPushed act

2019-02-11 12:56发布

I ran into the same problem described in this OpenRadar issue. As stated there:

Summary: The hidesBottomBarWhenPushed property of UIViewController doesn't work as expected for apps built with iOS 6 SDK (not beta SDKs for iOS 7). The animation is weird when hiding the bottom bar (e.g. a tab bar).

Steps to Reproduce:

  1. Create a new project with the TabBar template in Xcode 4. Add a UINavigationController to the FirstViewController. Add a button on the FirstViewController and set its action to push a new view controller. (please see the sample code attached)

  2. Run the demo on an iOS 7 beta 5 device.

  3. Press the button, back from the UINavigationController, pay attention to the animated view transitions.

Expected Results: The animation works exactly the same as on an iOS 6 device.

Actual Results: The animation looks weird. The FirstViewController is sliding down from the bottom.

Sample code: http://cl.ly/QgZZ

Is there any way to fix or work around this when building with the iOS 6 SDK?

2条回答
狗以群分
2楼-- · 2019-02-11 13:40

This issue definitely exists. I did some investigation and found out what's causing it. When pushing a view controller with UINavigationController, you view controller's view is contained in a UIViewControllerWrapperView, which a private Apple's view managed by the UINavigationController. When the transition animation is about to occur and the hidesBottomBarWhenPushed is set to YES, this UIViewControllerWrapperView is being animated with wrong position for the Y axis, so the solution is just to overwrite this behaviour and give correct values for the animation. Here's the code:

//Declare a property
@property (nonatomic, assign) BOOL shouldFixAnimation;

...

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

#ifndef __IPHONE_7_0 //If this constant is not defined then we probably build against lower SDK and we should do the fix
    if (self.hidesBottomBarWhenPushed && [[[UIDevice currentDevice] systemVersion] floatValue] >= 7 && animated && self.navigationController) {
        self.shouldFixAnimation = YES;
    }
#endif

}

-(void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];

#ifndef __IPHONE_7_0
    if(self.shouldFixAnimation) {
        self.shouldFixAnimation = NO;
        CABasicAnimation *basic = (CABasicAnimation *)[self.view.superview.layer animationForKey:@"position"]; //The superview is this UIViewControllerWrapperView

        //Just in case for future changes from Apple
        if(!basic || ![basic isKindOfClass:[CABasicAnimation class]]) 
            return;

        if(![basic.fromValue isKindOfClass:[NSValue class]])
            return;

        CABasicAnimation *animation = [basic mutableCopy];

        CGPoint point = [basic.fromValue CGPointValue];

        point.y = self.view.superview.layer.position.y;

        animation.fromValue = [NSValue valueWithCGPoint:point];

        [self.view.superview.layer removeAnimationForKey:@"position"];
        [self.view.superview.layer addAnimation:animation forKey:@"position"];
    }
#endif

}
查看更多
SAY GOODBYE
3楼-- · 2019-02-11 13:46

In My Case, I had TabBarViewController with UINavigationController in each tabs & faced similar issue. I used,

nextScreen.hidesBottomBarWhenPushed = true
pushViewToCentralNavigationController(nextScreen)

It works fine when nextScreen is UITableViewController subclass & applied auto layout. But, It does not work fine when nextScreen is UIViewController. I found it depends on nextScreen auto layout constraints.

So I just updated my currentScreen with this code -

override func viewWillDisappear(animated: Bool) {

        super.viewWillDisappear(animated)

        self.tabBarController?.tabBar.hidden = true

    }

In this way you can achieve desired outcome but its not good way to achieve it.

Hope it helps.

查看更多
登录 后发表回答