【Swift4】タブバーの表示・非表示をアニメーション付きで【iOS】

タブバーの表示・非表示をアニメーション付きで。

デモ　(iPhone8 plus)
![tabbardemo.gif](https://qiita-image-store.s3.amazonaws.com/0/151314/af1f8750-91a1-92e7-a998-ce9f6513928c.gif)

## デモプロジェクトの作成

画面をタップするとタブバーが出たり隠れたりする単純なアプリです。

「Single View Application」をテンプレに新規プロジェクトを作成します。
ストーリーボードにて、ViewControllerに**`Tab Bar Controller`**を挿入します。挿入方法は、ViewController上部の一番左のアイコンをクリックしてから、Xcodeメニュー：Editor -> Embed In -> Tab Bar Controllerと辿ります。

## 実装

```Swift:ViewController.swift
import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var tapGes:UITapGestureRecognizer!
    
    var tabBarFrame:CGRect!      // タブバー位置情報
    var tabbarVisible = true   // 見えてる・見えてないフラグ

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        // デフォルトのタブバー位置情報を保存
        tabBarFrame = (tabBarController?.tabBar.frame)!

        tapGes.addTarget(self, action: #selector(ViewController.tapped(_ :)))
        view.addGestureRecognizer(tapGes)
        
    }

    @objc func tapped(_ s:UITapGestureRecognizer) {
        
        UIView.animate(withDuration: 0.5, animations: {() -> Void in
            
            var frame = self.tabBarFrame
            
            if self.tabbarVisible {
                // 隠す（不可視領域に追いやる）
                frame?.origin.y = (self.tabBarFrame?.origin.y)! + (self.tabBarFrame?.size.height)!
                self.tabBarController?.tabBar.frame = frame!
            } else {
                // 出す（不可視領域から復帰させる）
                self.tabBarController?.tabBar.frame = self.tabBarFrame
            }
            
            // 見えてる・見えてないフラグの更新
            self.tabbarVisible = (self.tabbarVisible) ? false : true
        })
        
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

```
## ストーリーボード／アウトレット変数関連付け

今回はTapGestureRecognizerをストーリーボードにて設定しています。
<img width="2306" alt="tab1.png" src="https://qiita-image-store.s3.amazonaws.com/0/151314/96c1dd56-6393-20d8-90e7-0d5f0bada29d.png">
## 解説
UIViewのクラスメソッド、animate()のanimationブロックに位置情報(frame)の更新処理を記述します。隠すときはｙ座標にタブバー自身の高さを追加することによって可視エリアから下へ追いやっています。出現させるときは本来の位置情報をセットすることで実現しています。
**`withDuration`**にてどのくらいの時間をかけて指定値の状態にするかを指定します。

```Swift
        UIView.animate(withDuration: 0.5, animations: {() -> Void in
            
            var frame = self.tabBarFrame
            
            if self.tabbarVisivbe {
                // 隠す（不可視領域に追いやる）
                frame?.origin.y = (self.tabBarFrame?.origin.y)! + (self.tabBarFrame?.size.height)!
                self.tabBarController?.tabBar.frame = frame!
            } else {
                // 出す（不可視領域から復帰させる）
                frame?.origin.y = (self.tabBarFrame?.origin.y)!
                self.tabBarController?.tabBar.frame = frame!
            }
            
            // 見えてる・見えてないフラグの更新
            self.tabbarVisible = (self.tabbarVisible) ? false : true
        })
```

##ナビゲーションバーにも同様の挙動をさせる

タブバーとは逆に隠すときは画面上へ追いやることになりますので、描画ポジションのｙ座標から自身の高さとステータスバーの高さ（２０）を引きます。
<img width="853" alt="ViewController_swift.png" src="https://qiita-image-store.s3.amazonaws.com/0/151314/59834779-6bf9-c3fe-da65-2cd0d41e6d6f.png">


##### ★が追加コード
```Swift:ViewController.swift
import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var tapGes:UITapGestureRecognizer!
    
    var tabBarFrame:CGRect! // タブバー位置情報
    var navBarFrame:CGRect! // ★追加　ナビゲーションバー位置情報

    var isTabbarVisivle = true   // 見えてる・見えてないフラグ
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        // デフォルトのタブバー位置情報を保存
        tabBarFrame = (tabBarController?.tabBar.frame)!
        // ★追加　デフォルトのナビゲーションバー位置情報を保存
        navBarFrame = (navigationController?.navigationBar.frame)!
        
        tapGes.addTarget(self, action: #selector(ViewController.tapped(_ :)))
        view.addGestureRecognizer(tapGes)
        
    }

    @objc func tapped(_ s:UITapGestureRecognizer) {
        
        UIView.animate(withDuration: 0.5, animations: {() -> Void in
            
            var frame = self.tabBarFrame
            var navFrame = self.navBarFrame
            
            if self.isTabbarVisivle {
                // 隠す（不可視領域に追いやる）
                frame?.origin.y = (self.tabBarFrame?.origin.y)! + (self.tabBarFrame?.size.height)!
                self.tabBarController?.tabBar.frame = frame!
                
                // ★追加　20はステータスバーの高さ
                navFrame?.origin.y = (self.navBarFrame?.origin.y)! - (self.navBarFrame?.size.height)! - 20
                self.navigationController?.navigationBar.frame = navFrame!
                
            } else {
                // 出す（不可視領域から復帰させる）
                self.tabBarController?.tabBar.frame = self.tabBarFrame
                // ★追加
                self.navigationController?.navigationBar.frame = self.navBarFrame
            }
            
            // 見えてる・見えてないフラグの更新
            self.isTabbarVisivle = (self.isTabbarVisivle) ? false : true
        })
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}
```

### おまけ：徐々に薄くなってゆくエフェクトを追加する

フェードのエフェクトを加える場合は**`alpha`**プロパティに値を指定することでそれらしい効果が出せます。

```Swift
    @objc func tapped(_ s:UITapGestureRecognizer) {
        
        UIView.animate(withDuration: 0.5, animations: {() -> Void in
            
            var frame = self.tabBarFrame
            var navFrame = self.navBarFrame
            
            if self.isTabbarVisivle {

                // 隠す（不可視領域に追いやる）
                frame?.origin.y = (self.tabBarFrame?.origin.y)! + (self.tabBarFrame?.size.height)!
                self.tabBarController?.tabBar.frame = frame!
                self.tabBarController?.tabBar.alpha = 0.0
                // ★追加　20はステータスバーの高さ
                navFrame?.origin.y = (self.navBarFrame?.origin.y)! - (self.navBarFrame?.size.height)! - 20
                self.navigationController?.navigationBar.frame = navFrame!
                self.navigationController?.navigationBar.alpha = 0.0

            } else {
                // 出す（不可視領域から復帰させる）
                self.tabBarController?.tabBar.frame = self.tabBarFrame
                self.tabBarController?.tabBar.alpha = 1.0

                // ★追加
                self.navigationController?.navigationBar.frame = self.navBarFrame
                self.navigationController?.navigationBar.alpha = 1.0

            }
            
            // 見えてる・見えてないフラグの更新
            self.isTabbarVisivle = (self.isTabbarVisivle) ? false : true
        })
        
    }
```

![222.gif](https://qiita-image-store.s3.amazonaws.com/0/151314/838feab0-3526-10ec-4fbf-19a91753cbfb.gif)


　

　

#####ちなみにアニメーションが不要なら、**`isHidden`**プロパティを操作するだけでOKです。

```Swift:sample
// タブバーの表示・非表示のトグル
tabBarController?.tabBar.isHidden = (tabBarController?.tabBar.isHidden) ? false : true
```

###### 関連記事
[UITabBarController基礎【Swift3.0】](https://qiita.com/fromage-blanc/items/552e47353ae21259e046)