Flutterでプラットフォームによって違うUIのダイアログを表示してみた。
大阪オフィスの山田です。家の中でよくねこを紛失しますが、大体布団の中にいます。今回は、プラットフォーム毎に、異なるUIのダイアログを表示してみます。
今回やること
前回作ったチャットアプリにサインイン機能を追加しましたので、今回はサインアウト機能をつけます。その際に表示する確認ダイアログをiOS、Androidで表示を変えてみたいと思います。
完成イメージ
iOS
Android
※画像はタブレット端末のスクリーンショットです
開発環境
flutter doctor
Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel beta, v0.5.1, on Mac OS X 10.13.5 17F77, locale ja-JP) [✓] Android toolchain - develop for Android devices (Android SDK 28.0.1) [✓] iOS toolchain - develop for iOS devices (Xcode 9.4) [✓] Android Studio (version 3.1) ✗ Flutter plugin not installed; this adds Flutter specific functionality. ✗ Dart plugin not installed; this adds Dart specific functionality. [!] VS Code (version 1.26.1) [✓] Connected devices (1 available)
flutter --version
Flutter 0.5.1 • channel beta • https://github.com/flutter/flutter.git Framework • revision c7ea3ca377 (3 months ago) • 2018-05-29 21:07:33 +0200 Engine • revision 1ed25ca7b7 Tools • Dart 2.0.0-dev.58.0.flutter-f981f09760
実装
前準備
前回作ったチャットアプリの続きから始めます。プラットフォーム毎に処理を切り替える実装自体は、前回からの続きからでなくても参考にできるかと思います。
実装
まずは、ナビゲーションバーの右上にSignOut
ボタンを表示する部分です。ログインしている時にのみボタンを表示するようにしています。実装は以下の通りです。
import 'dart:io'; import 'package:flutter/cupertino.dart'; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: new Text("Firebase Chat"), actions: _buildAppBarActionButton() ), body: Container( child: _user == null ? _buildGoogleSignInButton() : _buildChatArea()), ); } List<Widget> _buildAppBarActionButton() { return _user == null ? null : <Widget>[ MaterialButton( onPressed: () { StatelessWidget dialog; dialog = Platform.isIOS ? _buildSignOutDialogiOS() : _buildSignOutDialogAndroid(); showDialog( context: context, builder: (context) { return dialog; } ); }, child: Text( "SignOut", style: TextStyle( fontSize: 14.0, color: Colors.white ), ), ) ]; }
dart:io
をimportして、Platform.isXXX
メソッドでプラットフォームを判定します。_buildSignOutDialogXXX
メソッドで各プラットフォームに対応したダイアログを生成します。ダイアログを生成するメソッドは以下の通りです。
Widget _buildSignOutDialogAndroid() { return AlertDialog( title: Text("Confirm"), content: Text("Are you sure you want to Sign out?"), actions: <Widget>[ FlatButton( child: const Text("Cancel"), onPressed: () { Navigator.pop(context); }, ), FlatButton( child: const Text("SignOut"), onPressed: () { Navigator.pop(context); _signOut(); }, ) ] ); } Widget _buildSignOutDialogiOS() { return CupertinoAlertDialog( title: Text("Confirm"), content: Text("Are you sure you want to Sign out?"), actions: <Widget>[ CupertinoDialogAction( child: const Text("Cancel"), isDefaultAction: true, onPressed: () { Navigator.pop(context); }, ), CupertinoDialogAction( child: const Text("SignOut"), isDestructiveAction: true, onPressed: () { Navigator.pop(context); _signOut(); }, ) ] ); } void _signOut() { _auth.signOut() .then((_) { setState(() { _user = null; }); }) .catchError((error) { print(error); }); }
AndroidはAlertDialog
, FlatButton
、iOSはCupertinoAlertDialog
, CuprtinoDialogAction
クラスを使用しています。どちらも処理はほぼ同じでSignOut
ボタンがタップされたらサインアウトする処理を実行します。うーん、ここはほとんど処理が同じだし、なんとか共通化したいなぁ。。。今回、実装したソースはこちらに載せておきます。
最後に
いかがだったでしょうか。Flutterで完結する内容であれば、Flutterでプラットフォーム毎に処理を分けることができました。あんまり分けすぎるとFlutterを使うメリットも小さくなってしまうので、可能な限り統一して進めたい、というのが所感です。