How do I hide/show tabBar when tapped using Swift in iOS8
After much hunting and trying out various methods to gracefully hide/show the UITabBar using Swift I was able to take this great solution by danh and convert it to Swift:
func setTabBarVisible(visible: Bool, animated: Bool) { //* This cannot be called before viewDidLayoutSubviews(), because the frame is not set before this time // bail if the current state matches the desired state if (tabBarIsVisible() == visible) { return } // get a frame calculation ready let frame = self.tabBarController?.tabBar.frame let height = frame?.size.height let offsetY = (visible ? -height! : height) // zero duration means no animation let duration: TimeInterval = (animated ? 0.3 : 0.0) // animate the tabBar if frame != nil { UIView.animate(withDuration: duration) { self.tabBarController?.tabBar.frame = frame!.offsetBy(dx: 0, dy: offsetY!) return } }}func tabBarIsVisible() -> Bool { return (self.tabBarController?.tabBar.frame.origin.y)! < self.view.frame.maxY}// Call the function from tap gesture recognizer added to your view (or button)@IBAction func tapped(_ sender: Any?) { setTabBarVisible(visible: !tabBarIsVisible(), animated: true)}
Loved Michael Campsall's answer. Here's the same code as extension, if somebody is interested:
Swift 2.3
extension UITabBarController { func setTabBarVisible(visible:Bool, animated:Bool) { // bail if the current state matches the desired state if (tabBarIsVisible() == visible) { return } // get a frame calculation ready let frame = self.tabBar.frame let height = frame.size.height let offsetY = (visible ? -height : height) // animate the tabBar UIView.animateWithDuration(animated ? 0.3 : 0.0) { self.tabBar.frame = CGRectOffset(frame, 0, offsetY) self.view.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height + offsetY) self.view.setNeedsDisplay() self.view.layoutIfNeeded() } } func tabBarIsVisible() ->Bool { return self.tabBar.frame.origin.y < CGRectGetMaxY(self.view.frame) }}
Swift 3
extension UIViewController { func setTabBarVisible(visible: Bool, animated: Bool) { //* This cannot be called before viewDidLayoutSubviews(), because the frame is not set before this time // bail if the current state matches the desired state if (isTabBarVisible == visible) { return } // get a frame calculation ready let frame = self.tabBarController?.tabBar.frame let height = frame?.size.height let offsetY = (visible ? -height! : height) // zero duration means no animation let duration: TimeInterval = (animated ? 0.3 : 0.0) // animate the tabBar if frame != nil { UIView.animate(withDuration: duration) { self.tabBarController?.tabBar.frame = frame!.offsetBy(dx: 0, dy: offsetY!) return } } } var isTabBarVisible: Bool { return (self.tabBarController?.tabBar.frame.origin.y ?? 0) < self.view.frame.maxY }}
I had to adapt the accepted answer to this question a bit. It was hiding the bar but my view wasn't sizing itself appropriately so I was left with a space at the bottom.
The following code successfully animates the hiding of the tab bar while resizing the view to avoid that issue.
Updated for Swift 3 (now with less ugly code)
func setTabBarVisible(visible: Bool, animated: Bool) { guard let frame = self.tabBarController?.tabBar.frame else { return } let height = frame.size.height let offsetY = (visible ? -height : height) let duration: TimeInterval = (animated ? 0.3 : 0.0) UIView.animate(withDuration: duration, delay: 0.0, options: UIViewAnimationOptions.curveEaseIn, animations: { [weak self] () -> Void in guard let weakSelf = self else { return } weakSelf.tabBarController?.tabBar.frame = frame.offsetBy(dx: 0, dy: offsetY) weakSelf.view.frame = CGRect(x: 0, y: 0, width: weakSelf.view.frame.width, height: weakSelf.view.frame.height + offsetY) weakSelf.view.setNeedsDisplay() weakSelf.view.layoutIfNeeded() })}func handleTap(recognizer: UITapGestureRecognizer) { setTabBarVisible(visible: !tabBarIsVisible(), animated: true)}func tabBarIsVisible() -> Bool { guard let tabBar = tabBarController?.tabBar else { return false } return tabBar.frame.origin.y < UIScreen.main.bounds.height}
Older Swift 2 Version
func setTabBarVisible(visible: Bool, animated: Bool) { // hide tab bar let frame = self.tabBarController?.tabBar.frame let height = frame?.size.height var offsetY = (visible ? -height! : height) println ("offsetY = \(offsetY)") // zero duration means no animation let duration:NSTimeInterval = (animated ? 0.3 : 0.0) // animate tabBar if frame != nil { UIView.animateWithDuration(duration) { self.tabBarController?.tabBar.frame = CGRectOffset(frame!, 0, offsetY!) self.view.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height + offsetY!) self.view.setNeedsDisplay() self.view.layoutIfNeeded() return } }}@IBAction func handleTap(recognizer: UITapGestureRecognizer) { setTabBarVisible(!tabBarIsVisible(), animated: true)}func tabBarIsVisible() -> Bool { return self.tabBarController?.tabBar.frame.origin.y < UIScreen.mainScreen().bounds.height}