Android Studio Flutter下TextFormField输入值无法更新变量问题求助
问题解决方案
核心问题点
TextFormField的onSaved回调不会自动执行,必须将输入控件包裹在Form组件内,主动调用Form状态的save()方法才会触发该回调- 你当前的代码没有使用
Form组件包裹输入框,也没有主动触发保存逻辑,所以_valueAlarm变量始终不会更新 onSaved回调拿到的输入值是String类型,直接强转为int会抛出类型异常,需要显式做类型转换
实现步骤
- 为Form组件创建全局唯一的Key,用于后续操作Form状态
- 将输入框包裹在
Form组件中,绑定刚才创建的Key - 点击启动按钮时,先校验输入合法性,校验通过后执行保存操作,再触发闹钟逻辑
- 修正
onSaved中的类型转换逻辑
修正后完整代码
import 'package:android_alarm_manager/android_alarm_manager.dart'; import 'package:flutter/material.dart'; import 'package:flutter_ringtone_player/flutter_ringtone_player.dart'; class HomePage extends StatefulWidget { const HomePage({Key? key}) : super(key: key); @override _HomePageState createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { bool isOn = false; int alarmId = 1; final _controller = TextEditingController(); // 新增Form的全局Key final _formKey = GlobalKey<FormState>(); int _valueAlarm = 0; var now = DateTime.now(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text( 'Alarm', style: TextStyle(fontSize: 30.0,), ), centerTitle: true, ), body: Column( children: <Widget>[ Padding( padding: const EdgeInsets.all(50.0), // 输入框包裹在Form组件内 child: Form( key: _formKey, child: minAlarmFormField(context), ), ), startButton() ], ), ); } TextFormField minAlarmFormField(BuildContext context) { return TextFormField( controller: _controller, keyboardType: TextInputType.number, textInputAction: TextInputAction.next, validator: (value){ if(value == null || value.isEmpty){ return '请输入分钟数'; } int? inputNum = int.tryParse(value); if(inputNum == null || inputNum < 0 || inputNum >59){ return '请输入0-59之间的整数'; } return null; }, onSaved: (value) { // 修正类型转换逻辑 _valueAlarm = int.parse(value!); }, decoration: const InputDecoration( hintText: 'e.g.) 55', labelText: 'Minute', ), ); } ElevatedButton startButton(){ return ElevatedButton( onPressed: () async { // 先校验输入,再执行保存 if(_formKey.currentState!.validate()){ _formKey.currentState!.save(); print("alarm start at ${DateTime.now()}"); print("minAlarm value is $_valueAlarm"); await AndroidAlarmManager.oneShot( Duration(minutes: _valueAlarm), alarmId, fireAlarm, exact: true, wakeup: true, ); } }, child:const Text( 'Start', style: TextStyle(fontSize: 17.0), ), ); } } void fireAlarm() { print('Alarm Fired at ${DateTime.now()}'); FlutterRingtonePlayer.play( android: AndroidSounds.notification, ios: IosSounds.glass, looping: false, volume: 0.5, asAlarm: true, ); }
可选简化方案
如果你不需要用到Form的校验能力,也可以直接在点击按钮时读取输入框控制器的值,不用依赖onSaved回调:
// 按钮点击逻辑直接修改为 onPressed: () async { int? inputNum = int.tryParse(_controller.text); if(inputNum != null && inputNum >=0 && inputNum <=59){ _valueAlarm = inputNum; // 后续闹钟逻辑 } }
内容的提问来源于stack exchange,提问作者Tyler E
相关产品推荐
相关产品推荐

