もくじ
こんにちは。スマホアプリをメインに開発しているロッキーカナイです。
記事が大分ご無沙汰になってしまいましたが、今回はFlutterでカスタムダイアログの実装について紹介したい思います。
まずFlutterでダイアログを実装する場合は、SimpleDialogやAlertDialogを使うと思うのですが、クライアントの要望にあったオシャンティなダイアログを作るとなると、これらでは実現出来ません。そこでカスタムダイアログを用いて実装します。
ではカスタムダイアログの実装を見てみましょう。
実装説明
ModalRouteを継承したページを用意し、モーダル画面遷移させて現在のページの上にかさねる感じになります。
よって、現在のページ上にボタンがあったとしてもタッチは届かず、ダイアログとしての機能を満たします。
ModalRouteを継承したルートクラスを実装
ModalRouteを継承したModalOverlayクラスを追加します。
import 'package:flutter/material.dart';
/*
* モーダルオーバーレイ
*/
class ModalOverlay extends ModalRoute<void> {
// ダイアログ内のWidget
final Widget contents;
// Androidのバックボタンを有効にするか
final bool isAndroidBackEnable;
ModalOverlay(this.contents, {this.isAndroidBackEnable = true}) : super();
@override
Duration get transitionDuration => Duration(milliseconds: 100);
@override
bool get opaque => false;
@override
bool get barrierDismissible => false;
@override
Color get barrierColor => Colors.black.withOpacity(0.5);
@override
String get barrierLabel => null;
@override
bool get maintainState => true;
@override
Widget buildPage(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) {
return Material(
type: MaterialType.transparency,
child: SafeArea(
child: _buildOverlayContent(context),
),
);
}
@override
Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
return FadeTransition(
opacity: animation,
child: ScaleTransition(
scale: animation,
child: child,
),
);
}
Widget _buildOverlayContent(BuildContext context) {
return Center(
child: dialogContent(context),
);
}
Widget dialogContent(BuildContext context) {
return WillPopScope(
child: this.contents,
onWillPop: () {
return Future(() => isAndroidBackEnable);
},
);
}
}
Androidで実機のバックボタンを押すとダイアログが閉じてしまうので、有効無効の切り替えができるようにしました。dialogContentメソッドのWillPopScopeクラスのonWillPopでポップする際にコールバックが呼ばれて、bool値を返すことで切り替えしてます。
また、ModalOverlayではcontentsというWidgetをもらってそれを表示させるようにしました。
ダイアログのコンテンツクラスを実装
CustomDialogというクラスを作り、ここでModalOverlayのコンテンツを作って渡すのと、push遷移させます。
import 'package:flutter/material.dart';
import 'package:test_project/ModalOverlay.dart';
class CustomDialog {
BuildContext context;
CustomDialog(this.context) : super();
/*
* 表示
*/
void showCustomDialog() {
Navigator.push(
context,
ModalOverlay(
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Stack(
children: <Widget>[
Image.asset(
"images/fukidashi.png",
fit: BoxFit.fitWidth,
),
Container(
height: 200.0,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
/*
* タイトル
*/
Text(
"カスタムダイアログ",
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.bold,
locale: Locale("ja", "JP"),
),
),
/*
* メッセージ
*/
Text(
"こんな感じでダイアログが出せるよ",
style: TextStyle(
fontSize: 16.0,
locale: Locale("ja", "JP"),
),
),
],
),
)
)
],
),
/*
* OKボタン
*/
Row(
children: <Widget>[
Expanded(
child: Container(),
),
FlatButton(
color: Colors.blue,
child: Text(
"OK",
style: TextStyle(
color: Colors.white,
fontSize: 18.0,
fontWeight: FontWeight.bold,
locale: Locale("ja", "JP"),
),
),
onPressed: () {
hideCustomDialog();
},
),
SizedBox(
width: 80.0,
)
],
),
],
)
),
isAndroidBackEnable: false,
),
);
}
/*
* 非表示
*/
void hideCustomDialog() {
Navigator.of(context).pop();
}
}
呼び出しは以下のようにします。
onPressed: () {
CustomDialog(
context,
).showCustomDialog();
},
フキダシはここのを使用しました。
まとめ
いかがでしたでしょうか?
ModalRouteを使ってカスタムダイアログの実装を紹介をしました。
今回作ったModalOverlayを用いて、通信中などで使うインジケータビューとしても使うことができますので、次回はその紹介をしたいと思います。
いつかマイブームのキックボクシングの記事書けたらいいなぁ。