🔑
【Flutter】ログイン画面のUXを爆上げする OS標準パスワード自動入力の実装術
はじめに
メールアドレスとパスワードを毎回手入力させるログイン画面は、離脱率を確実に引き上げます。iOSの iCloudキーチェーン や Android の Google パスワード マネージャー を正しく使ってもらうには、Flutter側で「これは認証フォームですよ」と OS に伝えるコードが必要です。本稿では、現時点での デファクトスタンダード な実装パターンを整理します。
🔑 結論:最低限そろえる 3 要素
| 要素 | 役割 |
|---|---|
AutofillGroup |
OS に「このフィールド群はログインフォームだよ」と伝える |
autofillHints |
各フィールドが ID なのかパスワードなのかを明示するメタデータ |
keyboardType / textInputAction
|
入力体験を最適化し、誤入力と離脱を防ぐ |
この 3 点を正しく設定してはじめて、OS 標準の自動入力候補が確実に表示され、保存ダイアログまで到達します。
実装サンプル
import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; // finishAutofillContext を使う場合に必要
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
void dispose() {
_emailController.dispose();
_passwordController.dispose();
super.dispose();
}
void _login() {
// TODO: ログイン処理を実装
// ✅ ログイン成功後に呼ぶと OS が保存ダイアログを出せる
TextInput.finishAutofillContext();
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('ログイン')),
body: Padding(
padding: const EdgeInsets.all(24),
child: AutofillGroup(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: _emailController,
decoration: const InputDecoration(
labelText: 'ログインID (メールアドレス)',
),
autofillHints: const [
AutofillHints.username,
AutofillHints.email,
],
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.next,
enableSuggestions: false,
autocorrect: false,
),
const SizedBox(height: 16),
TextField(
controller: _passwordController,
decoration: const InputDecoration(
labelText: 'パスワード',
),
obscureText: true,
autofillHints: const [AutofillHints.password],
keyboardType: TextInputType.visiblePassword,
textInputAction: TextInputAction.done,
enableSuggestions: false,
autocorrect: false,
onEditingComplete: _login,
),
const SizedBox(height: 32),
ElevatedButton(
onPressed: _login,
style: ElevatedButton.styleFrom(
minimumSize: const Size.fromHeight(50),
),
child: const Text('ログイン', style: TextStyle(fontSize: 18)),
),
],
),
),
),
);
}
}
各要素の深掘り
1. AutofillGroup
- OS はグループ単位で「これは認証フォームのセットだ」と理解する
-
Scaffold直下ではなく、関連フィールドだけを囲むと誤認識を防げる - 同一画面に別フォームがある場合はグループを分ける
2. autofillHints
| Hint | 使いどころ |
|---|---|
AutofillHints.username |
メールアドレス以外の ID も含む汎用ログイン ID |
AutofillHints.email |
メールアドレスと明示したい場合に併用 |
AutofillHints.password |
パスワードフィールド。obscureText とセットで使う |
コツ: Username と Email は 両方 指定することで認識率が上がります。
3. キーボード・アクション設定
-
keyboardTypeで OS の専用キーボード (@キー、記号など) を出す -
textInputActionをnext/doneにすると、ソフトキーボードのラベルが変わり遷移がスムーズ -
enableSuggestions=false,autocorrect=falseで意図しない候補を消せる(特にパスワード)
✅ ログイン成功時は finishAutofillContext
- ユーザーが Autofill で入力 → ログイン処理成功
-
TextInput.finishAutofillContext()を呼ぶ - OS が「この資格情報を保存しますか?」ダイアログを表示
呼び忘れると保存ダイアログが出ず、次回以降の自動入力も期待できません。ログイン API 成功 → トークン保存 → 画面遷移の直前が定位置です。
追加で押さえておきたい UX チューニング
-
フォーカス移動:
FocusScope.of(context).nextFocus()をonEditingCompleteで呼ぶと、ユーザー操作を 1 アクション減らせる - バリデーション表示: まずは自動入力で通して、失敗したらエラーメッセージを出す(先にバリデーションすると保存済み情報が弾かれることがある)
-
MFA 連携: パスワード入力後に 2FA があるプロダクトは、
finishAutofillContextを二段階で呼ぶとエコシステムと相性が良い -
テスト端末: iOS は
設定 > パスワードでテストアカウントを登録、Android は Chrome で先に資格情報を保存しておくと検証が速い
チェックリスト
-
フォームが
AutofillGroupで囲われている -
メール欄に
usernameとemailの両ヒントを付与 -
パスワード欄に
AutofillHints.passwordとobscureText -
TextInput.finishAutofillContext()を成功時に呼ぶ - 自動入力後のバリデーションで弾かない
- テスト端末で保存ダイアログが出るところまで確認済み
よくある落とし穴
| 症状 | 原因と対策 |
|---|---|
| 自動入力候補が出ない |
AutofillGroup を忘れている / フォームが複数グループにまたがっている |
| パスワード保存ダイアログが出ない |
finishAutofillContext の呼び忘れ or 例外で未到達 |
| メール欄に電話番号候補が出る |
keyboardType が text のまま、ヒントが未指定 |
| バリデーションで即エラー | 自動入力後に TextField の onChanged で無効化している。バリデーションタイミングを見直す |
まとめ
AutofillGroupでフォームを囲むautofillHintsでフィールドの役割を宣言keyboardTypeとtextInputActionで UX を磨く- ログイン成功時に
TextInput.finishAutofillContext()を必ず呼ぶ
たったこれだけで、ユーザーは保存済みパスワードをワンタップで呼び出せるようになり、ログイン成功率と滞在時間が大幅に改善します。まだ未対応であれば、今すぐ取り込んで「入力が面倒なアプリ」から卒業しましょう!
Discussion