iOSでカスタムUIViewをポップアップとして表示する「FFPopup」を試してみた

# はじめに
こんにちは。
今回は、iOSでいい感じのポップアップアニメーションを表示する **「FFPopup」** というライブラリを試してみたので、その紹介をさせていただきます。
至らぬ点など多々あると思いますが、コメントなど頂けたら幸いです。

# [FFPopup](https://github.com/JonyFang/FFPopup)
GitHub: https://github.com/JonyFang/FFPopup
 ![popup-logo](https://github.com/JonyFang/FFPopup/raw/master/Resources/ffpopup-logo.png)
 
e.g.

|上から下へ跳ねる|中心イン&アウト|下から下へスライド|
|:---:|:---:|:---:|
|<img src="https://github.com/JonyFang/FFPopup/raw/master/Resources/001_bounce_from_top&Bounce_to_bottom.gif" width="100px">|<img src="https://github.com/JonyFang/FFPopup/raw/master/Resources/003_bounce_in&bounce_out.gif" width="100px">|<img src="https://github.com/JonyFang/FFPopup/raw/master/Resources/005_bounce_from_bottom&slide_to_bottom.gif" width="100px">|


## 1. 導入

今回は、cocoapodsで導入しました。
Podfileに ```pod 'FFPopup'``` を追加し、 `$ pod install` します。

## 2. 実装
まずは、StoryBoadrdに簡単なボタンを追加し、デフォルトの動作を確認してみます。
ボタンをタップしたらサンプルで作成したUIViewに対してポップアップ表示を適用させます。

```swift
import UIKit
// FFPopupのインポート追加
import FFPopup
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func tapButton(_ sender: Any) {
        
        // サンプルcontentViewの作成
        let contentView = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
        contentView.backgroundColor = UIColor.white
        
        // FFPopupの初期化
        let popup = FFPopup(contentView: contentView)
        let layout = FFPopupLayout(horizontal: .center, vertical: .center)
        
        // popup表示
        popup.show(layout: layout)
    }
}
```

#### 実行結果
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139949/e096d806-e77e-6ac2-984d-02c12d5aa0f8.gif" width="300px">

デフォルトのパラメータを使用すると、
「上からポップアップが出現し、作成したcontentView以外をタップしたら
下にポップアップが消える」挙動を確認できました！

デフォルトのパラメータは以下のようです。

```swift
// FFPopupの初期化
let popup = FFPopup(contentView: contentView)

// ポップアップの表示アニメーションタイプ
popup.showType = .bounceInFromTop
// ポップアップを消すアニメーションタイプ
popup.dismissType = .bounceOutToBottom
// 背景マスク
popup.maskType = .dimmed
// マスクのアルファ値
popup.dimmedMaskAlpha = 0.5
// 表示の遷移時間
popup.showInDuration = 0.15
// 非表示への遷移時間
popup.dismissOutDuration = 0.15
// 背景タッチでポップアップを消す
popup.shouldDismissOnBackgroundTouch = true
// コンテンツビューのタッチでポップアップを消す
popup.shouldDismissOnContentTouch = false

let layout = FFPopupLayout(horizontal: .center, vertical: .center)

// popup表示
popup.show(layout: layout)

```

こちらのパラメータを変更・調整することによって、ポップアップをカスタマイズすることができます。


## 3. カスタムビューを用いた実装例

簡単なカスタムビューを用いて、どのような実装ができるか試してみようと思います。
カスタムビューの作成をし、カスタムビューのボタンをタップして、FFPopupのアニメーションを適用させます。

#### (1) CustomAlertView.xibの追加
戻るボタンと決定ボタンを備えたCustomAlertViewを作成します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139949/622913e2-9efa-2760-6ecd-3758983b5f67.png" width="300px">
( 参考：https://dev.classmethod.jp/smartphone/xib/ )

##### (2) xibファイルとカスタムクラスの紐付けをした、CustomAlertView.swiftを作成する

IBOutletで2つのボタンをストーリーボードから紐付けます。

```swift
//
//  CustomAlertView.swift
// 

import UIKit

class CustomAlertView: UIView {

    // StoryBoardで2つのボタンを追加
    @IBOutlet weak var okButton: UIButton!
    @IBOutlet weak var cancelButton: UIButton!
    
    override init(frame: CGRect){
        super.init(frame: frame)
        loadNib()
    }
    
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
    }
    
    func loadNib(){
        guard let view =  UINib(nibName: "CustomAlertView", bundle: nil).instantiate(withOwner: self, options: nil).first as? CustomAlertView else {
            return
        }
        view.frame = self.bounds
        self.addSubview(view)
    }
}
```

※ `@Outlet` や `@IBAction` を利用するため、
Placeholders → File's Ownerに紐付けを行います。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139949/9f9c2281-53bc-39d8-782e-7377a18b5fb0.png" width="600px">


##### (3) ViewControllerの実装

- ボタンをタップしたら、CustomAlertViewを作成
- CustomAlertViewの2つのボタンのイベントを設定
- 背景タッチしてもポップアップが消えないようにする
- 2つのボタンをタップした際のアニメーションタイプを分ける

```swift

import UIKit
// 追加
import FFPopup
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    var contentView: CustomAlertView?
    var popup:FFPopup?
    
    @IBAction func tapButton(_ sender: Any) {
        
        // カスタムcontentViewの作成
        contentView = CustomAlertView()
        contentView?.frame = CGRect(x: 0, y: 0, width: 300, height: 300)

        // okButtonのイベント設定
        contentView?.okButton.addTarget(self, action: #selector(tappedOk(_:)), for: .touchUpInside)
        
        // cancelButtonのイベント設定
        contentView?.cancelButton.addTarget(self, action: #selector(tappedCancel(_:)), for: .touchUpInside)

        // FFPopupの初期化
        popup = FFPopup(contentView: contentView!)

        // 中心から出現するアニメーション
        popup?.showType = .bounceIn

        // 背景タッチしてもポップアップが消えないようにする
        popup?.shouldDismissOnBackgroundTouch = false

        let layout = FFPopupLayout(horizontal: .center, vertical: .center)

        // popup表示
        popup?.show(layout: layout)
    }


    @objc func tappedOk(_ sender:UIButton) {
        // 拡大して消えるアニメーション
        popup?.dismissType = .growOut
        popup?.dismiss(animated: true)
        print("ok")
    }
    
    // 下に消えるアニメーション
    @objc func tappedCancel(_ sender:UIButton) {
        popup?.dismissType = .bounceOutToBottom
        popup?.dismiss(animated: true)
        print("cancel")
    }
}
```

#### (4) 実行結果
ボタンを押したらアラートのポップアップが表示され、
選択したボタンによって異なるアニメーションを表現することが実現できました！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139949/8d0dc517-9fc4-3b49-9d26-272625ca2611.gif" width="300px">


## おわりに

今回は、FFPopupというライブラリを試してみました。
さまざまな`showType`と`dismissType`を組み合わせることによって、
リッチなポップアップアニメーションを簡易的に実装することができそうです。
  
 
 
最後までご覧いただきありがとうございました。