警告のみのダイアログボックス、文字入力ありのダイアログボックスの2種類を扱えるdialogutils.dartを使う。
以下のURLの記事を参考に改良しました。多国語対応と、カレンダー日付入力機能を追加しています。
Flutter逆引き辞典 Chapter 16 ダイアログでもテキスト入力がしたい
https://zenn.dev/pressedkonbu/books/flutter-reverse-lookup-dictionary/viewer/016-input-text-on-dialog
ソースファイル
以下のファイルをlibフォルダに入れておく。HomePage.dart等で、インポートして使う。(カレンダ部分は多国語対応している)。
dialogutil.dart
//dialogutil.dart
// 注意:入力制限は要修正です。
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:intl/intl.dart';
import 'package:flutter_localization/flutter_localization.dart';
class DialogUtils {
DialogUtils._();
final FlutterLocalization localization = FlutterLocalization.instance;
/// タイトルのみを表示するシンプルなダイアログを表示する
static Future<void> showOnlyTitleDialog(
BuildContext context,
String title,
) async {
showDialog(
context: context,
builder: (context) {
return AlertDialog(title: Text(title));
},
);
}
/// 入力した文字列を返すダイアログを表示する
static Future<String?> showEditingDialog(
BuildContext context,
String text,
) async {
return showDialog<String>(
context: context,
builder: (context) {
return TextEditingDialog(text: text);
},
);
}
// カレンダーで日付を選択するダイアログボックス(yyyy-MM-dd文字列を返す)
static Future<String?> showCalender(
BuildContext context,
String sDate,
) async {
final FlutterLocalization localization = FlutterLocalization.instance;
String sLoc = localization.currentLocale.localeIdentifier.substring(
0,
2,
); // 頭2文字
debugPrint(sLoc);
DateTime dt = DateTime.parse(sDate);
DateFormat dateF = DateFormat('yyyy-MM-dd'); // 時刻を消すために使用
DateTime? picked = await showDatePicker(
context: context,
initialDate: dt,
firstDate: DateTime(DateTime.now().year - 120),
lastDate: DateTime(DateTime.now().year + 120),
locale: Locale(sLoc),
keyboardType: TextInputType.text,
);
DateTime d = picked ?? dt;
String sDate2 = dateF.format(d);
return sDate2;
}
}
/// 状態を持ったダイアログ
class TextEditingDialog extends StatefulWidget {
const TextEditingDialog({super.key, this.text});
final String? text;
@override
State<TextEditingDialog> createState() => _TextEditingDialogState();
}
class _TextEditingDialogState extends State<TextEditingDialog> {
final controller = TextEditingController();
final focusNode = FocusNode();
@override
void dispose() {
controller.dispose();
focusNode.dispose();
super.dispose();
}
@override
void initState() {
super.initState();
// TextFormFieldに初期値を代入する
controller.text = widget.text ?? '';
focusNode.addListener(() {
// フォーカスが当たったときに文字列が選択された状態にする
if (focusNode.hasFocus) {
controller.selection = TextSelection(
baseOffset: 0,
extentOffset: controller.text.length,
);
}
});
}
@override
Widget build(BuildContext context) {
return AlertDialog(
content: TextFormField(
autofocus: true, // ダイアログが開いたときに自動でフォーカスを当てる
focusNode: focusNode,
controller: controller,
// ================================================================機能制限(要修正)
// 数字のみ許容
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'[0-9.]'))],
// テキスト入力可能(ただしアルファベットのみ)
//keyboardType: TextInputType.text,
//inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9._-]'))],
onFieldSubmitted: (_) {
// エンターを押したときに実行される
Navigator.of(context).pop(controller.text);
},
),
actions: [
TextButton(
onPressed: () {
debugPrint(controller.text);
Navigator.of(context).pop(controller.text);
},
child: const Text('OK'),
),
],
);
}
}
ダイアログボックスの呼び出し方法
数値を入力する場合について例示する。stateオブジェクトの、build のScaffold()内に、下記を参考に記載する。
ローカル変数textBufで文字列を受取り、初期値を「0」として、nullなら「0」文字列を発生させる。(String?型なのでnullが有り得る)
int.parse(testBuf)でintに変換後、有効な値なら、setState(() {.....}で、共有変数に更新をかける。
async , await が必須。
@override
Widget build(BuildContext context) {
final int age =0;
........
return Scaffold(
appBar: AppBar(....),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
......
ElevatedButton(
onPressed: () async {
String textBuf = await DialogUtils.showEditingDialog(context, '0') ?? '0';
debugPrint(textBuf);
int num = int.parse(textBuf);
if (num > 0) {
setState(() {
selecteddate2 = selecteddate1.add(Duration(days: num),);
});
} // if
},
child: const Text('日数'),
), // ElevatedButton
.......
カレンダー入力ダイアログの呼び出し方法
import 'package:intl/intl.dart'; // DateFormat 関数で必要
// import 'package:flutter_localization/flutter_localization.dart'; // 多国語対応モジュールここでは使わない
// final FlutterLocalization localization = FlutterLocalization.instance; //多国語対応インスタンス
// String sLoc = localization.currentLocale.localeIdentifier.substring(0,2,); // ’ja’となる。
DateTime birthday = DateTime.parse('1900-01-01'); //仮の初期値 意味はない
DateFormat dateF = DateFormat('yyyy-MM-dd'); // 時刻を消すために使用
......
Text(’生年月日’),
Text(DateFormat.yMMMEd('ja').format(birthday);, context),
),
ElevatedButton(
onPressed: () async {
String? sBDay = await DialogUtils.showCalender(
context,
dateF.format(birthday),
);
if (sBDay != null) {
setState(() {
birthday = DateTime.parse(sBDay);
});
}
},
......