Flutter 数値表示・入力ダイアログのサンプル
はじめに
Flutterで数値を入力するためのダイアログパターンを3つ作ってみました(iPad向けです)。
https://github.com/sshiraki/FlutterNumberDisplay
メインで表示されるページのラジオボタンで表示させるダイアログを選択し、数字の部分をタップするとダイアログが表示されます。
どれも、シンプルに数値を入力するだけで、他に機能はありません。
白枠:白い枠にテンキーを配置
透過:グレイの透過背景にテンキーを配置
ボトムシート:ボトムシートにテンキーを配置
最初に表示される数値をタップするとダイアログが表示され、ダイアログで入力された数値がEnterキーをタップすることで確定され、ダイアログが閉じます。
は後ろの画面に表示されている数値が変更される想定ですが、現状は見た目では数値が変更されません。
ダイアログについて
「白枠」、と「透過」は showDialogメソッドでDialogウィジェット を表示しします。
main.dart : Scaffold:body
result = await showDialog(
barrierDismissible: false,
context: context,
builder: (_) {
if (_dialogType == DialogType.greyFrame) {
return NumberDisplayDialogGrey(
numberData: "$numberData");
} else {
//_dialogType == DialogType.whiteFrame
return NumberDisplayDialog(
numberData: "$numberData");
}
});
setState(() {
numberData = result;
});
白枠
透過
「ボトムシート」はshowModalBottomSheet でモーダルボトムシートを表示します。
モーダルボトムシートは厳密にはダイアログではありませんが、本稿ではダイアログとして扱っています。
main.dart : Scaffold:body
if (_dialogType == DialogType.bottomSheet) {
result = await showModalBottomSheet<String>(
context: context,
isDismissible: false,
builder: (BuildContext context) {
return NumberDisplayBottomSheet(
numberData: "$numberData");
},
);
setState(() {
if (result != null) {
numberData = result;
}
});
ModalBottomSheetでは、後ろに表示されているグレイアウトされた部分をタップした場合、何もしなければ、戻り値なしでダイアログが終了してしまいます。setStateに以下の処理があることで、グレイ部分をタップしても終了しなくなります。
setState(() {
if (result != null) {
numberData = result;
}
});
一見、戻り値がnullの場合、ダイアログが終了してしまいそうですが、ダイアログに処理が戻ります。戻り値がnullでない場合はnumberDataに値が設定され、ダイアログが終了します。
ボトムシート
ステート保持について
ボタンのUIはAdobe XD to Flutter Generate Plugin を使用してベースを作りましたが、ボタンの処理を実装したり、ステート保持をするため、大幅に修正しています。
Adobe XD でフロントエンド設計(Adobe XD Flutter Code Generate プラグイン)
https://note.com/sshiraki/n/n8270cec70534
ステートは、providerを使用しダイアログの数値表示部分を外出ししています。メイン画面のステート保持は分離する実装としたため、「ボトムシート」では見た目で数値が変更されませんが、内部的にはproviderでステート保持されています。
providerを使えるようにします。
main.dart
import 'package:provider/provider.dart';
数値表示部分のステートを外出ししています。
NumberDataModel.dart
import 'package:flutter/material.dart';
class NumberDataModel extends ChangeNotifier {
final String _numberData_default = "000000";
String numberData;
NumberDataModel({Key key, this.numberData});
String getNumberData() {
return numberData;
//print("debug $numberData");
}
void setNumberData(String s) {
if (numberData.substring(0, 1) == "0") {
numberData = "${numberData.substring(1, 6)}$s";
notifyListeners();
//print("debug $numberData");
}
}
void delNumberData() {
numberData = "0${numberData.substring(0, 5)}";
notifyListeners();
//print("debug $numberData");
}
void resetNumberData() {
numberData = _numberData_default;
notifyListeners();
//print("debug $numberData");
}
}
ボタンの処理。数値を設定する前にモデル(NumberDataModel)を指定します。
main.dart : _NumberDisplayDialogState
NumberDisplayBottomSheet.dart : _NumberDisplayBottomSheetState
NumberDisplayDialogGrey.dart : _NumberDisplayDialogGreyState
ChangeNotifierProvider<NumberDataModel>(
create: (_) => NumberDataModel(numberData: _numberData)
数値(文字列ですが)を画面表示します(1文字ずつ表示するため、substringで切り出し)。
main.dart : NumberDisplayText
Text(
Provider.of<NumberDataModel>(context)
.numberData
.substring(inx, inx + 1)
テンキーボタンの表示と押された時の処理。Consumerでモデル(NumberDataModel)を指定します。
main.dart : KeyButton, KeyButtonBS, KeyButtonClear, KeyButtonEnter
Consumer<NumberDataModel>(builder: (_, model, __) {
数値のボタンを押された時の処理。NumberDataModelのsetNumberDataを呼びます。引数keychは"1”〜"9"。
main.dart : KeyButton
onPressed: () {
model.setNumberData(keych);
},
バックスペースキーが押された時の処理。NumberDataModelのdelNumberDataを呼びます。
main.dart : KeyButtonBS
onPressed: () {
model.delNumberData();
}
Cキーが押された時の処理。NumberDataModelのresetNumberDataを呼びます。
main.dart : KeyButtonClear
onPressed: () {
model.resetNumberData();
},
Enterキーが押された時の処理。NumberDataModelのgetNumberDataで取得した値を親画面に戻します。
main.dart : KeyButtonEnter
onPressed: () {
//print("debug ${model.getNumberData()}");
Navigator.of(context).pop("${model.getNumberData()}");
}
以上です。
この記事が気に入ったらサポートをしてみませんか?