How to hide tab bar with animation in iOS? How to hide tab bar with animation in iOS? ios ios

How to hide tab bar with animation in iOS?


When working with storyboard its easy to setup the View Controller to hide the tabbar on push, on the destination View Controller just select this checkbox:
enter image description here


I try to keep view animations available to me using the following formula:

// pass a param to describe the state change, an animated flag and a completion block matching UIView animations completion - (void)setTabBarVisible:(BOOL)visible animated:(BOOL)animated completion:(void (^)(BOOL))completion {    // bail if the current state matches the desired state    if ([self tabBarIsVisible] == visible) return (completion)? completion(YES) : nil;    // get a frame calculation ready    CGRect frame = self.tabBarController.tabBar.frame;    CGFloat height = frame.size.height;    CGFloat offsetY = (visible)? -height : height;    // zero duration means no animation    CGFloat duration = (animated)? 0.3 : 0.0;    [UIView animateWithDuration:duration animations:^{        self.tabBarController.tabBar.frame = CGRectOffset(frame, 0, offsetY);    } completion:completion];}//Getter to know the current state- (BOOL)tabBarIsVisible {    return self.tabBarController.tabBar.frame.origin.y < CGRectGetMaxY(self.view.frame);}//An illustration of a call to toggle current state- (IBAction)pressedButton:(id)sender {    [self setTabBarVisible:![self tabBarIsVisible] animated:YES completion:^(BOOL finished) {        NSLog(@"finished");    }];}


does not longer work on iOS14, see updated 2nde answer below

Swift 3.0 version, using an extension:

extension UITabBarController {        private struct AssociatedKeys {        // Declare a global var to produce a unique address as the assoc object handle        static var orgFrameView:     UInt8 = 0        static var movedFrameView:   UInt8 = 1    }        var orgFrameView:CGRect? {        get { return objc_getAssociatedObject(self, &AssociatedKeys.orgFrameView) as? CGRect }        set { objc_setAssociatedObject(self, &AssociatedKeys.orgFrameView, newValue, .OBJC_ASSOCIATION_COPY) }    }        var movedFrameView:CGRect? {        get { return objc_getAssociatedObject(self, &AssociatedKeys.movedFrameView) as? CGRect }        set { objc_setAssociatedObject(self, &AssociatedKeys.movedFrameView, newValue, .OBJC_ASSOCIATION_COPY) }    }        override open func viewWillLayoutSubviews() {        super.viewWillLayoutSubviews()        if let movedFrameView = movedFrameView {            view.frame = movedFrameView        }    }        func setTabBarVisible(visible:Bool, animated:Bool) {        //since iOS11 we have to set the background colour to the bar color it seams the navbar seams to get smaller during animation; this visually hides the top empty space...        view.backgroundColor =  self.tabBar.barTintColor         // bail if the current state matches the desired state        if (tabBarIsVisible() == visible) { return }                //we should show it        if visible {            tabBar.isHidden = false            UIView.animate(withDuration: animated ? 0.3 : 0.0) {                //restore form or frames                self.view.frame = self.orgFrameView!                //errase the stored locations so that...                self.orgFrameView = nil                self.movedFrameView = nil                //...the layoutIfNeeded() does not move them again!                self.view.layoutIfNeeded()            }        }            //we should hide it        else {            //safe org positions            orgFrameView   = view.frame            // get a frame calculation ready            let offsetY = self.tabBar.frame.size.height            movedFrameView = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height + offsetY)            //animate            UIView.animate(withDuration: animated ? 0.3 : 0.0, animations: {                self.view.frame = self.movedFrameView!                self.view.layoutIfNeeded()            }) {                (_) in                self.tabBar.isHidden = true            }        }    }        func tabBarIsVisible() ->Bool {        return orgFrameView == nil    }}
  • This is based on the input from Sherwin Zadeh after a few hours of playing around.
  • Instead of moving the tabbar itself it moves the frame of the view, this effectively slides the tabbar nicely out of the bottom of the screen but...
  • ... has the advantage that the content displayed inside the UITabbarcontroller is then also taking the full screen!
  • note its also using the AssociatedObject functionality to attached data to the UIView without subclassing and thus an extension is possible (extensions do not allow stored properties)

enter image description here