Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does setting `hidesBottomBarWhenPushed` to YES with a translucent navigationBar break push animation?

I have what I would consider a fairly common setup, but I am seeing a pretty strange animation issue.

Storyboard

There's a navigation controller inside of a tab bar. If I push on that navigation controller, I can still see the previous viewController's red view in the navigation bar during the push animation, but only when I have hidesBottomBarWhenPushed set to yes on the destination viewController (on the very right). This is a reduced example of the issue, and it can all be set up in a storyboard.

Here's an animation of the transition. Watch the navigation bar. You can see the previous red view controller in the background, go partially off screen, then disappear at the end.

Has anyone solved this issue? Am I doing something unsupported? Is this a bug? I definitely want to keep translucent bars and hiding the tab bar on push, but I'm open to ways of reliably hiding the tab bar in some other way that supports translucent tab bars.

Animation

like image 244
Acey Avatar asked Jan 30 '15 21:01

Acey


4 Answers

Here's what I've found so far:

#1 Top right bar is black

The blurred black part on the top right of the top bar is the UIWindow behind the translucent UINavigationbar, with backgroundColor defaulting to blackColor.

The screenshot demonstrates this by setting the pushed view's background to clearColor.

enter image description here

As a workaround, setting the UIWindow's backgroundColor property to your desired background colour fixes this problem as long as you also have the property edgesForExtendedLayout of the view controller to push set to .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.
    }
}

I consider this a workaround since I believe modifying UIWindow's backgroundColor property is not necessarily what we should have to do. Perhaps, future iOS version can address this issue.

#2 View content "moving downwards" after push animation finishes

If you have a subview with a bottom layout guide and the views "move down", I haven't found any ideal fix yet. However, setting the tab bar to hidden helps to some extent. As a caveat and as expected, hiding the tab bar also immediately hides it from parent view controller during the push animation (although it becomes visible again during the animation when popping the view).

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

        // ...

        self.tabBarController?.tabBar.hidden = true
    }
}

Make sure ViewToPushViewController's hidesBottomBarWhenPushed property is set to true before it is pushed (either in the interface builder attributes inspector or in prepareForSegue method in the parent view controller).

enter image description here

Make sure you're also testing the animation behaviour when popping the view with back button.

like image 121
Gurpartap Singh Avatar answered Nov 08 '22 06:11

Gurpartap Singh


You may have UITabBarController class, and its background is empty. and window default background is black.

in Swift 2

without changing an anatomy of app:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point ...
    window?.backgroundColor = UIColor.whiteColor()
    return true
}
like image 22
zippo Avatar answered Nov 08 '22 06:11

zippo


Set UITabBarController's view backgroundColor may work

like image 2
weiminghuaa Avatar answered Nov 08 '22 08:11

weiminghuaa


I setup my storyboard like you showed with the same segues etc and got the same weird animation. After looking around for a resolution and playing with the code I got to this.

Use this in the destination view controller, hope this helps.

- (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;
                     }];
}

P.s. How did you make that very cool gif, will come in very handy.

like image 1
Erion S Avatar answered Nov 08 '22 06:11

Erion S