How to hide tab bar with animation in iOS?

后端 未结 15 1928
夕颜
夕颜 2020-11-30 19:20

So I have a button that is connected to a IBAction. When I press the button I want to hide the tab bar in my iOS app with a animation. This [self setTabBarHidden:hidde

15条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-11-30 20:08

    For Xcode 11.3 and iOS 13 other answers didn't work for me. However, based on those I've came up to the new solution using CGAffineTransform

    I didn't test this code well, but this might actually work.

    extension UITabBarController {
    
        func setTabBarHidden(_ isHidden: Bool) {
    
            if !isHidden { tabBar.isHidden = false }
    
            let height = tabBar.frame.size.height
            let offsetY = view.frame.height - (isHidden ? 0 : height)
            tabBar.transform = CGAffineTransform(translationX: 0, y: offsetY)
    
            UIView.animate(withDuration: 0.25, animations: {
                self.tabBar.transform = .identity
            }) { _ in
                self.tabBar.isHidden = isHidden
            }
        }
    
    }
    

    Hope that helps.

    UPDATE 09.03.2020:

    I've finally found an awesome implementation of hiding tab bar with animation. It's huge advantage it's able to work either in common cases and in custom navigation controller transitions. Since author's blog is quite unstable, I'll leave the code below. Original source: https://www.iamsim.me/hiding-the-uitabbar-of-a-uitabbarcontroller/

    Implementation:

    extension UITabBarController {
    
        /**
         Show or hide the tab bar.
    
         - Parameter hidden: `true` if the bar should be hidden.
         - Parameter animated: `true` if the action should be animated.
         - Parameter transitionCoordinator: An optional `UIViewControllerTransitionCoordinator` to perform the animation
            along side with. For example during a push on a `UINavigationController`.
         */
        func setTabBar(
            hidden: Bool,
            animated: Bool = true,
            along transitionCoordinator: UIViewControllerTransitionCoordinator? = nil
        ) {
            guard isTabBarHidden != hidden else { return }
    
            let offsetY = hidden ? tabBar.frame.height : -tabBar.frame.height
            let endFrame = tabBar.frame.offsetBy(dx: 0, dy: offsetY)
            let vc: UIViewController? = viewControllers?[selectedIndex]
            var newInsets: UIEdgeInsets? = vc?.additionalSafeAreaInsets
            let originalInsets = newInsets
            newInsets?.bottom -= offsetY
    
            /// Helper method for updating child view controller's safe area insets.
            func set(childViewController cvc: UIViewController?, additionalSafeArea: UIEdgeInsets) {
                cvc?.additionalSafeAreaInsets = additionalSafeArea
                cvc?.view.setNeedsLayout()
            }
    
            // Update safe area insets for the current view controller before the animation takes place when hiding the bar.
            if hidden, let insets = newInsets { set(childViewController: vc, additionalSafeArea: insets) }
    
            guard animated else {
                tabBar.frame = endFrame
                return
            }
    
            // Perform animation with coordinato if one is given. Update safe area insets _after_ the animation is complete,
            // if we're showing the tab bar.
            weak var tabBarRef = self.tabBar
            if let tc = transitionCoordinator {
                tc.animateAlongsideTransition(in: self.view, animation: { _ in tabBarRef?.frame = endFrame }) { context in
                    if !hidden, let insets = context.isCancelled ? originalInsets : newInsets {
                        set(childViewController: vc, additionalSafeArea: insets)
                    }
                }
            } else {
                UIView.animate(withDuration: 0.3, animations: { tabBarRef?.frame = endFrame }) { didFinish in
                    if !hidden, didFinish, let insets = newInsets {
                        set(childViewController: vc, additionalSafeArea: insets)
                    }
                }
            }
        }
    
        /// `true` if the tab bar is currently hidden.
        var isTabBarHidden: Bool {
            return !tabBar.frame.intersects(view.frame)
        }
    
    }
    

    If you're dealing with custom navigation transitions just pass a transitionCoordinator property of "from" controller, so animations are in sync:

    from.tabBarController?.setTabBar(hidden: true, along: from.transitionCoordinator)
    

    Note, that in such case the initial solution work very glitchy.

提交回复
热议问题