FirebaseUIのAuthPickerViewをxibでカスタマイズ
前回FirebaseUIを使って簡単にGoogle/Apple/Twitterを使って認証ができたので、今度はフェデレーション ID プロバイダ選択画面のカスタマイズを本家のサンプルを参考にやってみた。
カスタマイズ内容は以下の3つ
- ナビゲーションバーを消す
- キャンセルボタンを置く
- フェデレーション ID プロバイダのリストの上にラベルを置く
コード
カスタマイズの仕組み
本家のページにあるようにカスタマイズはFUIAuthPickerViewController
のサブクラスを作ってそれをカスタマイズすることになる。
カスタマイズされた画面が表示されるプロセスは、
-
AuthUI
のauthViewController()
を呼ぶ - プロトコル
FUIAuthDelegate
のauthPickerViewController(forAuthUI:)
が呼ばれるので、作成したサブクラスのインスタンスを返す - ライブラリがフェデレーション ID プロバイダのボタンを
view
に貼り付けてauthViewController()
の戻り値として返す。
ちなみにこのボタンのサイズや位置をカスタマイズする機能は用意されていない。どうしてもやりたい場合は直接ライブラリの中をいぢるしかない。が、そこまでするなら最初から自分でUIを作った方が楽な気がする。
FUIAuthPickerViewControllerのサブクラス
FUIAuthPickerViewController
のサブクラスCustomAuthPickerViewController
を作成する。
class CustomAuthPickerViewController: FUIAuthPickerViewController {
}
とりあえずはこれだけ。
CustomAuthPickerViewControllerのxibファイルを作成
コードで画面を作っても良いが今回は本家のサンプルのようにxibファイルを使ってみる。
- Xcodeの[File]-[New]-[File...]でUser Interfaceのviewを選択してxibファイルを作成する。ファイル名はCustomAuthPickerViewController.xibにした。
- 作成されたxibファイルを選択して左のリストからFile's Ownerを選択、Custom ClassのClassでCustomAuthPickerViewControllerを選択。
- そのままShow the connection inspectorを表示してviewを画面のviewに接続する。
- 左のリストからviewを選択してライブラリから
Gray Button
を選択し、TitleをCancelにして貼り付ける。位置はSafe Areaより少し下にしてConstrainを設定する。
- [Editor]-[Assistant]でコード(CustomAuthPickerViewController.swift)を表示してCancelボタンからドラッグ&ドロップでIBAction
onClickCancel
を作成。中身はprint("click Cancel")
だけ。 - 最後にviewのBackgroundをSystem Gray 4 Colorに設定。これは
ViewController
とCustomAuthPickerViewController
がそれぞれわかりやすくなるように。
これでCustomAuthPickerViewController.swiftはこうなる。
class CustomAuthPickerViewController: FUIAuthPickerViewController {
@IBAction func onClickCancel(_ sender: Any) {
print("click Cencel")
}
}
authPickerViewController(forAuthUI:)を実装
ViewController.swiftにプロトコルFUIAuthDelegate
のauthPickerViewController(forAuthUI:)
を実装する。
func authPickerViewController(forAuthUI authUI: FUIAuth) -> FUIAuthPickerViewController {
return CustomAuthPickerViewController.init(nibName: "CustomAuthPickerViewController", bundle: nil, authUI: authUI)
}
本家のサンプルとは違ってCustomAuthPickerViewController
はinit(nibName:bundle:authUI:)
を使ってインスタンス化している。
ここまでの変更で前回の画面にCancelボタンが加わった状態で動作するようになる。
色々とカスタマイズする
以下、先に挙げたカスタマイズをしていく。
Cancelボタンでキャンセルする
キャンセルボタンをタップしたらキャンセルできるようにする。
FUIAuthPickerViewController
にcancelAuthorization()
があるのでこれを呼ぶだけ。
@IBAction func onClickCancel(_ sender: Any) {
print("click Cencel")
self.cancelAuthorization()
}
これでCancelボタンをタップすると画面がアニメーションしながら消える。
ナビゲーションバーを消す
Cancelボタンでキャンセルできるのでナビゲーションバーは必要ない。
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を作成。
@IBOutlet weak var label: UILabel!
次にこのラベルをフェデレーション ID プロバイダリストの上のいい感じの位置に移動したいが、プロバイダの数で位置が変わるので計算する必要がある。
こんな感じ。
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
としてFUIAuthPickerViewController
のviewDidLoad()
で貼り付けられ、viewDidLayoutSubviews()
が呼ばれた時に位置調整をされている。
なのでCustomAuthPickerViewController
のviewDidLayoutSubviews()
でsuper
のviewDidLayoutSubviews()
を呼びプロバイダのリストの位置を決定。
その後でself.view.subviews
から_buttonContainerView
であろうUIView
を探して位置を取得。
それを元にlabelをマージン(kSignInButtonVerticalMargin
として定義されている)分だけずらして配置した。
表示されるシートを小さくする
フェデレーション ID プロバイダの数が少ないのに表示されるシートが画面いっぱいだとスカスカでなんかおかしい。というわけで、表示されるシートを小さくしてみた。
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