🐥

FirebaseUIのAuthPickerViewをxibでカスタマイズ

2022/06/19に公開

前回FirebaseUIを使って簡単にGoogle/Apple/Twitterを使って認証ができたので、今度はフェデレーション ID プロバイダ選択画面のカスタマイズを本家のサンプルを参考にやってみた。

カスタマイズ内容は以下の3つ

  • ナビゲーションバーを消す
  • キャンセルボタンを置く
  • フェデレーション ID プロバイダのリストの上にラベルを置く

コード

https://github.com/paraches/FirebaseUI_Auth_sample

カスタマイズの仕組み

本家のページにあるようにカスタマイズはFUIAuthPickerViewControllerのサブクラスを作ってそれをカスタマイズすることになる。

カスタマイズされた画面が表示されるプロセスは、

  1. AuthUIauthViewController()を呼ぶ
  2. プロトコルFUIAuthDelegateauthPickerViewController(forAuthUI:)が呼ばれるので、作成したサブクラスのインスタンスを返す
  3. ライブラリがフェデレーション ID プロバイダのボタンをviewに貼り付けてauthViewController()の戻り値として返す。

ちなみにこのボタンのサイズや位置をカスタマイズする機能は用意されていない。どうしてもやりたい場合は直接ライブラリの中をいぢるしかない。が、そこまでするなら最初から自分でUIを作った方が楽な気がする。

FUIAuthPickerViewControllerのサブクラス

FUIAuthPickerViewControllerのサブクラスCustomAuthPickerViewControllerを作成する。

CustomAuthPickerViewController.swift
class CustomAuthPickerViewController: FUIAuthPickerViewController {
}

とりあえずはこれだけ。

CustomAuthPickerViewControllerのxibファイルを作成

コードで画面を作っても良いが今回は本家のサンプルのようにxibファイルを使ってみる。

  1. Xcodeの[File]-[New]-[File...]でUser Interfaceのviewを選択してxibファイルを作成する。ファイル名はCustomAuthPickerViewController.xibにした。
  2. 作成されたxibファイルを選択して左のリストからFile's Ownerを選択、Custom ClassのClassでCustomAuthPickerViewControllerを選択。
  3. そのままShow the connection inspectorを表示してviewを画面のviewに接続する。
  4. 左のリストからviewを選択してライブラリからGray Buttonを選択し、TitleをCancelにして貼り付ける。位置はSafe Areaより少し下にしてConstrainを設定する。
  5. [Editor]-[Assistant]でコード(CustomAuthPickerViewController.swift)を表示してCancelボタンからドラッグ&ドロップでIBActiononClickCancelを作成。中身はprint("click Cancel")だけ。
  6. 最後にviewのBackgroundをSystem Gray 4 Colorに設定。これはViewControllerCustomAuthPickerViewControllerがそれぞれわかりやすくなるように。

これでCustomAuthPickerViewController.swiftはこうなる。

CustomAuthPickerViewController.swift
class CustomAuthPickerViewController: FUIAuthPickerViewController {
    @IBAction func onClickCancel(_ sender: Any) {
        print("click Cencel")
    }
}

authPickerViewController(forAuthUI:)を実装

ViewController.swiftにプロトコルFUIAuthDelegateauthPickerViewController(forAuthUI:)を実装する。

ViewController.swift
    func authPickerViewController(forAuthUI authUI: FUIAuth) -> FUIAuthPickerViewController {
        return CustomAuthPickerViewController.init(nibName: "CustomAuthPickerViewController", bundle: nil, authUI: authUI)
    }

本家のサンプルとは違ってCustomAuthPickerViewControllerinit(nibName:bundle:authUI:)を使ってインスタンス化している。

ここまでの変更で前回の画面にCancelボタンが加わった状態で動作するようになる。

色々とカスタマイズする

以下、先に挙げたカスタマイズをしていく。

Cancelボタンでキャンセルする

キャンセルボタンをタップしたらキャンセルできるようにする。
FUIAuthPickerViewControllercancelAuthorization()があるのでこれを呼ぶだけ。

CustomAuthPickerViewController.swift
    @IBAction func onClickCancel(_ sender: Any) {
        print("click Cencel")
        self.cancelAuthorization()
    }

これでCancelボタンをタップすると画面がアニメーションしながら消える。

ナビゲーションバーを消す

Cancelボタンでキャンセルできるのでナビゲーションバーは必要ない。

CustomAuthPickerViewController.swift
    override func viewWillAppear(_ animated: Bool) {
        self.navigationController?.navigationBar.isHidden = true
    }

    override func viewDidDisappear(_ animated: Bool) {
        self.navigationController?.navigationBar.isHidden = false
    }

表示される直前に消して、消えた直後に元に戻している。

認証プロバイダのリストの上にタイトルを表示する

ナビゲーションバーを消してタイトル(Welcomeだけど)が消えたので代わりに認証プロバイダのリストの上にタイトル「Providers:」を表示する。

まずはCustomAuthPickerViewController.xibを選択してLabelをCancelボタンの下に貼り付けCustomAuthPickerViewController.swiftにIBOutletを作成。

CustomAuthPickerViewController.swift
    @IBOutlet weak var label: UILabel!

次にこのラベルをフェデレーション ID プロバイダリストの上のいい感じの位置に移動したいが、プロバイダの数で位置が変わるので計算する必要がある。

こんな感じ。

CustomAuthPickerViewController.swift
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        for childView in self.view.subviews {
            let childViewClassName = String(describing: type(of: childView))
            if childViewClassName == "UIView" {
                //  in FUIAuthPickerViewController, kSignInButtonVerticalMargin = 24.0f
                let labelCenter = CGPoint(x: self.view.center.x,
                                          y: childView.frame.minY - 24 - self.label.frame.height / 2)
                self.label.center = labelCenter
                self.label.text = "Providers:"
                self.label.textAlignment = .center
            }
        }
    }

怪しいやり方だけど現状は取り敢えず動いている。

フェデレーション ID プロバイダのリストは_buttonContainerViewとしてFUIAuthPickerViewControllerviewDidLoad()で貼り付けられ、viewDidLayoutSubviews()が呼ばれた時に位置調整をされている。

なのでCustomAuthPickerViewControllerviewDidLayoutSubviews()superviewDidLayoutSubviews()を呼びプロバイダのリストの位置を決定。
その後でself.view.subviewsから_buttonContainerViewであろうUIViewを探して位置を取得。
それを元にlabelをマージン(kSignInButtonVerticalMarginとして定義されている)分だけずらして配置した。

表示されるシートを小さくする

フェデレーション ID プロバイダの数が少ないのに表示されるシートが画面いっぱいだとスカスカでなんかおかしい。というわけで、表示されるシートを小さくしてみた。

ViewController.swift
    override func viewDidAppear(_ animated: Bool) {
        if let authViewController = authUI?.authViewController() {
            if let sheet = authViewController.sheetPresentationController {
                sheet.detents = [.medium()]
                sheet.largestUndimmedDetentIdentifier = .medium
                sheet.prefersScrollingExpandsWhenScrolledToEdge = false
                sheet.prefersEdgeAttachedInCompactHeight = true
                sheet.widthFollowsPreferredContentSizeWhenEdgeAttached = true
            }
            self.present(authViewController, animated: true)
        }
    }

UISheetPresentationControllerに全てお任せで微調整はしていない。リストの数からサイズを確認してシートの大きさを変えたりした方が良いかもしれない。

最終的に表示される画面はこんな感じ。

しかし、この程度のカスタマイズならxibファイル使わずにコードでやった方が早いし簡単だと思う…。

最後に

正直ちょっとしたカスタマイズならやっても良いが、リストの位置を得るのに酷いやり方するくらいならFirebaseUIを使わずに最初から自分でUIを作った方が楽だと思う。

が、FirebaseUI面白いのでもう少し触ってみるつもり。

Discussion