くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

Firebase UI for Flutterでログイン画面とかを楽に作る

FirebaseUI for WebのFlutter版があったので、
いろいろ試してみたときの備忘録(*´ω`*)

ちなみに、FlutterFire UIもあったが、今はdeprecated。
firebase_ui_authへのマイグレーションが書かれている。

Firebase UI Authとは

Firebase UI Auth is a set of Flutter widgets and utilities designed to help you build and integrate your user interface with Firebase Authentication.
Firebase UI Auth は、ユーザー インターフェースを構築して Firebase Authentication と統合するのに役立つように設計された Flutter ウィジェットとユーティリティのセットです。

各プラットフォームで対応状況は異なるけど、
ログインなどの画面やWidget,処理などを提供してくれている。

ただ、ドキュメント関連はGitHubだけっぽい。。
一方、ソース中のコメントは丁寧に書かれてる印象。

なかなか見ずらく、ドキュメントも足りない部分があるので、
サンプルやソース自体をよく参照する。。
github.devと合わせて見るのがいいかも。

シンプルな例

firebase_ui_auth/README.mdのシンプルな例。
これだけでログイン画面がつくれる。

import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: FirebaseAuth.instance.currentUser == null ? '/sign-in' : '/profile',
      routes: {
        '/sign-in': (context) {
          // ログイン画面 = SignInScreen
          return SignInScreen(
            // 利用するProvider = Email/Passwordのみ
            providers: [EmailAuthProvider()],
            actions: [
              // 利用するAction = AuthStateの変更検知のみ
              AuthStateChangeAction<SignedIn>((context, state) {
                // authStateが変わったら、プロフィール画面に遷移
                Navigator.pushReplacementNamed(context, '/profile');
              }),
            ],
          );
        },
      },
    );
  }
}

提供されているもの

ざっくりした全体像はこんな感じ。

基本はscreensとactionsを使っておけばOK。
カスタマイズしたいときはviewsやwidgetsを使って、画面を作る感じ。

SignInScreenにも、
headerBuildersubtitleBuilderfooterBuilderなども用意されていて、
部分的なカスタマイズもできる。

必要なパッケージ

使いたいプロバイダーなどによって、
必要なパッケージはちょっと変わる。

# 必須: コアのUI。EmailなどならこれだけでOK
$ flutter pub add firebase_ui_auth

# OAuthの場合は、OAuthのコア+対象のプロバイダが必要
$ flutter pub add firebase_ui_oauth
$ flutter pub add firebase_ui_oauth_google

# 日本語化など多言語対応するときにこれも必要
$ flutter pub add firebase_ui_localizations

GoogleSignInButtonなどのWidgetfirebase_ui_oauth_googleに入ってる。

言語化(firebase_ui_localizations)

firebase_ui_localizationsのREADMEだとこんな感じ。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: [
        // Flutter提供の標準Widget用
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,

        // FirebaseUI用
        FirebaseUILocalizations.delegate,
      ],
      // ...
    );
  }
}

FirebaseUIにある一部のラベルを変更したいときは、
DefaultLocalizationsを使えばよいっぽい。

import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:firebase_ui_localizations/firebase_ui_localizations.dart';

class LabelOverrides extends DefaultLocalizations {
  const LabelOverrides();

  @override
  String get emailInputLabel => 'Enter your email';

  @override
  String get passwordInputLabel => 'Enter your password';
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: [
        // FirebaseUI用: カスタマイズ部分
        FirebaseUILocalizations.withDefaultOverrides(const LabelOverrides()),
        
        // Flutter提供の標準Widget用
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,

        // FirebaseUI用: カスタマイズ以外
        FirebaseUILocalizations.delegate,
      ],
      // ...
    );
  }
}

flutter_localizationsを利用時

公式ドキュメントでも解説されてるflutter_localizationsを使ってるときはこんな感じ。

import '/app_l10n.dart' show L10n;

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: [
          // flutter_localizationsのdelegates
          ...L10n.localizationsDelegates,
          // FirebaseUI用
          FirebaseUILocalizations.delegate,
      ],
      supportedLocales: L10n.supportedLocales,
      // ...
    );
  }
}

L10n.localizationsDelegatesの中身がこんな感じなので、
GlobalMaterialLocalizations.delegateとかは不要。

abstract class L10n {
  static const List<LocalizationsDelegate<dynamic>> localizationsDelegates = <LocalizationsDelegate<dynamic>>[
    delegate,
    GlobalMaterialLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
  ];
  // ...
}

以上!! 各種OAuthのボタンをブランドイメージに合わせて作るのはめんどくさいので、
こういうのあってありがたい。。(*´ω`*)

参考にしたサイトさま