Search code examples
iosswiftframeuitabbar

Weird frame calculation for UITabBar


Sometimes the app shrinks the width of the UITabBar, the 4 icons in the screenshot are usually distributed across the whole width.

weird uitabbar frame

Is anyone experiencing this and knows why it happens or even better how to fix/avoid it? I think it started happening with Swift, so maybe another of their awesome optimizations?

Also not sure how to reproduce it, happens around twice a week, maybe rotation, segue or app switch.

This screenshot is from an iPhone6 in portrait mode, but happens on other devices too.


Solution

  • I found the same behavior on iOS9 in two cases:

    1) while immediate rotation during the pop-navigation in UINavigationController;

    2) on rotation from landscape to portrait while watching full-screen video player and closing player after that.

    To solve the problem on iOS8+ you should subclass UITabBarController and implement method from UIContentContainer protocol as follows:

    - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
    {
        [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
    
        if (!self.tabBar.window) return;
    
        [coordinator animateAlongsideTransition: ^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
             CGRect newBounds = self.tabBar.bounds;
             newBounds.size.width = size.width;
             self.tabBar.bounds = newBounds;
    
             [self.view.superview setNeedsLayout];
         }
                                 completion: nil];
    }
    

    If you don't write return string you won't fix the 2nd issue.

    Adding same in Swift:

    extension UITabBarController {
        public override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
            super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
            if let _ = self.tabBar.window {
                coordinator.animateAlongsideTransition( { (context) in
                    self.tabBar.bounds.size.width = size.width
                    self.view.superview?.setNeedsLayout()
                    }, completion: nil)
            }
        }
    }