iOS/Swift - Hide/Show UITabBarController when scrolling down/up

后端 未结 5 482
栀梦
栀梦 2020-12-08 17:36

I\'m quite new to iOS development. Right now i\'m trying to hide my tabbar when I scroll down and when scrolling up the tabbar should appear. I would like to have this anima

相关标签:
5条回答
  • 2020-12-08 18:13

    This answer is a slight modification to Ariel answer which adds animation while user scrolls.

    extension ViewController:UIScrollViewDelegate{
        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            if scrollView.panGestureRecognizer.translation(in: scrollView).y < 0{
                //scrolling down
                changeTabBar(hidden: true, animated: true)
            }
            else{
                //scrolling up
                changeTabBar(hidden: false, animated: true)
            }
        }
    
        func changeTabBar(hidden:Bool, animated: Bool){
            let tabBar = self.tabBarController?.tabBar
            let offset = (hidden ? UIScreen.main.bounds.size.height : UIScreen.main.bounds.size.height - (tabBar?.frame.size.height)! )
            if offset == tabBar?.frame.origin.y {return}
            print("changing origin y position")
            let duration:TimeInterval = (animated ? 0.5 : 0.0)
            UIView.animate(withDuration: duration,
                           animations: {tabBar!.frame.origin.y = offset},
                           completion:nil)
        }
    }
    
    0 讨论(0)
  • 2020-12-08 18:15

    According to @Ariel Hernández Amador answer for black screen after hiding Tabbar just use this line of code in your ViewDidLoad(). Working Superbly...I have posted this here as I am unable to comment over there.

    viewDidLoad()
    {
    if #available(iOS 11.0, *) {
                self.myScroll.contentInsetAdjustmentBehavior = .never
            }
    }
    

    Here myScroll is the Scrollview I am using in my VC. Just replace it with your VC.

    0 讨论(0)
  • 2020-12-08 18:18

    Building on Ariel's answer, I have updated the code for Swift3. This worked great on my collection views.

    override func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
            if scrollView.panGestureRecognizer.translation(in: scrollView).y < 0 {
                changeTabBar(hidden: true, animated: true)
            }else{
                changeTabBar(hidden: false, animated: true)
            }
    
        }
    
    func changeTabBar(hidden:Bool, animated: Bool){
            let tabBar = self.tabBarController?.tabBar
            if tabBar!.isHidden == hidden{ return }
            let frame = tabBar?.frame
            let offset = (hidden ? (frame?.size.height)! : -(frame?.size.height)!)
            let duration:TimeInterval = (animated ? 0.5 : 0.0)
            tabBar?.isHidden = false
            if frame != nil
            {
                UIView.animate(withDuration: duration,
                                           animations: {tabBar!.frame = frame!.offsetBy(dx: 0, dy: offset)},
                                           completion: {
                                            print($0)
                                            if $0 {tabBar?.isHidden = hidden}
                })
            }
        }
    
    0 讨论(0)
  • 2020-12-08 18:19

    This is code that i'm actually using in a production app.

    It's in Swift and it also updates UITabBar.hidden var.

    func scrollViewWillBeginDragging(scrollView: UIScrollView) {
        if scrollView.panGestureRecognizer.translation(in: scrollView).y < 0{
            changeTabBar(hidden: true, animated: true)
        }
        else{
            changeTabBar(hidden: false, animated: true)
        }
    }
    

    You can also use the other callback method:

    func scrollViewDidScroll(scrollView: UIScrollView) {
        ...
    }
    

    but if you choose so, then you must handle multiple calls to the helper method that actually hides the tabBar.

    And then you need to add this method that animates the hide/show of the tabBar.

    func changeTabBar(hidden:Bool, animated: Bool){
        var tabBar = self.tabBarController?.tabBar
        if tabBar!.hidden == hidden{ return }
        let frame = tabBar?.frame
        let offset = (hidden ? (frame?.size.height)! : -(frame?.size.height)!)
        let duration:NSTimeInterval = (animated ? 0.5 : 0.0)
        tabBar?.hidden = false
        if frame != nil
        {
            UIView.animateWithDuration(duration,
                animations: {tabBar!.frame = CGRectOffset(frame!, 0, offset)},
                completion: {
                    println($0)
                    if $0 {tabBar?.hidden = hidden}
            })
        }
    }
    

    Update Swift 4

    func changeTabBar(hidden:Bool, animated: Bool){
        guard let tabBar = self.tabBarController?.tabBar else { return; }
        if tabBar.isHidden == hidden{ return }
        let frame = tabBar.frame
        let offset = hidden ? frame.size.height : -frame.size.height
        let duration:TimeInterval = (animated ? 0.5 : 0.0)
        tabBar.isHidden = false
    
        UIView.animate(withDuration: duration, animations: {
            tabBar.frame = frame.offsetBy(dx: 0, dy: offset)
        }, completion: { (true) in
            tabBar.isHidden = hidden
        })
    }
    
    0 讨论(0)
  • 2020-12-08 18:20

    You can control UITabBar precisly by setting up your class as delegate for scrollView and implementing scrolling in scrollViewDidScroll: method.

    Here is an example how I do it my application. You can probably easily modify that for your needs. Some helper function to get UITabBar included.

    #define LIMIT(__VALUE__, __MIN__, __MAX__) MAX(__MIN__, MIN(__MAX__, __VALUE__))
    
    - (void)scrollViewDidScroll:(UIScrollView *)scrollView
    {
        CGFloat scrollOffset = scrollView.contentOffset.y;
        CGFloat scrollDiff = scrollOffset - self.previousScrollViewYOffset;
        CGFloat scrollHeight = scrollView.frame.size.height;
        CGFloat scrollContentSizeHeight = scrollView.contentSize.height + scrollView.contentInset.bottom;
        CGFloat scrollOffsetGlobal = scrollOffset + scrollView.contentInset.top;
        [self updateUITabBarY:[self UITabBarView].frame.origin.y + scrollDiff];
        self.previousScrollViewYOffset = scrollOffset;
    }
    
    - (UITabBar*) UITabBarView
    {
        for(UIView *view in self.tabBarController.view.subviews)
        {
            if([view isKindOfClass:[UITabBar class]])
            {
                return (UITabBar*) view;
            }
        }
    
        return nil;
    }
    
    - (void) updateUITabBarY:(CGFloat) y
    {
        UITabBar* tabBar = [self UITabBarView];
        if(tabBar)
        {
            CGRect frame = tabBar.frame;
            frame.origin.y  = LIMIT(y, [self UITabBarMiny], [self UITabBarMaxY]);
            tabBar.frame = frame;
        }
    }
    
    - (CGFloat) UITabBarMiny
    {
        return [UIScreen mainScreen].bounds.size.height - [self UITabBarView].frame.size.height - [[UIApplication sharedApplication] statusBarFrame].size.height + 20.0f;
    }
    
    - (CGFloat) UITabBarMaxY
    {
        return [UIScreen mainScreen].bounds.size.height;
    }
    
    0 讨论(0)
提交回复
热议问题