web-dev-qa-db-ja.com

iOS / Swift-上下にスクロールするときにUITabBarControllerを非表示/表示する

私はiOS開発にまったく慣れていません。現在、下にスクロールするとタブバーを非表示にしようとしていますが、上にスクロールするとタブバーが表示されます。ナビゲーションバーと同じようにアニメーション化してもらいたいです。ナビゲーションバーの場合は、属性インスペクターのオプションをクリックするだけです。ツールバーの例をいくつか見ましたが、タブバーを採用することはできません。

self.tabBarController?.tabBar.hidden = trueタブバーを非表示にするだけですが、ナビゲーションコントローラーのようにアニメーション化されていません。

9
Philipp B.

これは、私が実際に本番アプリで使用しているコードです。

Swiftにあり、UITabBar.hiddenvarも更新します。

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

他のコールバックメソッドを使用することもできます。

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

ただし、そうすることを選択した場合は、実際にtabBarを非表示にするヘルパーメソッドへの複数の呼び出しを処理する必要があります。

次に、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}
        })
    }
}

更新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
    })
}

Arielの回答に基づいて、Swiftのコードを更新しました。これは私のコレクションビューでうまく機能しました。

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}
            })
        }
    }
5
Aidan.C

この回答は、ユーザーがスクロールしている間にアニメーションを追加するArielの回答を少し変更したものです。

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)
    }
}
4
LC 웃

クラスをscrollViewのデリゲートとして設定し、scrollViewDidScroll:メソッドでスクロールを実装することにより、UITabBarを正確に制御できます。

これが私のアプリケーションの例です。おそらく、必要に応じて簡単に変更できます。 UITabBarを含めるためのいくつかのヘルパー関数。

#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;
}
1

@ArielHernándezAmadorによると、Tabbarを非表示にした後の黒い画面に対する回答は、ViewDidLoad()でこのコード行を使用するだけです。見事に働いています...あそこにコメントすることができないので、私はここにこれを投稿しました。

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

ここでmyScrollは、VCで使用しているScrollviewです。 VCと交換するだけです。

0
srsstyle