Flutter如何实现验证码TextFormField输入自动跳转、删除时回退焦点
需要修改/补充的内容:
- 替换焦点控制变量
原代码中用isFocus1~isFocus6的布尔值控制自动聚焦逻辑不合理,改为使用Flutter官方提供的FocusNode控制每个输入框的焦点状态,同时需要在组件销毁时释放FocusNode避免内存泄漏。 - 为
PhoneCodeTextField扩展参数
增加onChanged回调、FocusNode参数、当前输入框的位置索引,用于监听输入内容变化和控制焦点跳转。 - 实现焦点跳转逻辑
在每个输入框的onChanged回调中做判断:
- 当输入内容长度为1时,当前输入框失焦,自动请求下一个输入框的焦点(最后一个输入框除外)
- 当输入内容被清空时,自动请求上一个输入框的焦点(第一个输入框除外)
- 修正原代码语法问题
原代码中Column直接嵌套Padding缺少children数组包裹,属于语法错误需要修正。
完整修改后代码:
import 'package:flutter/material.dart'; class GetPhoneCode extends StatefulWidget { const GetPhoneCode({Key? key}) : super(key: key); @override _GetPhoneCodeState createState() => _GetPhoneCodeState(); } class _GetPhoneCodeState extends State<GetPhoneCode> { final codeP1 = GlobalKey<FormState>(); final codeP2 = GlobalKey<FormState>(); final codeP3 = GlobalKey<FormState>(); final codeP4 = GlobalKey<FormState>(); final codeP5 = GlobalKey<FormState>(); final codeP6 = GlobalKey<FormState>(); String codeP1S = ""; String codeP2S = ""; String codeP3S = ""; String codeP4S = ""; String codeP5S = ""; String codeP6S = ""; // 新增:每个输入框对应的FocusNode final FocusNode focus1 = FocusNode(); final FocusNode focus2 = FocusNode(); final FocusNode focus3 = FocusNode(); final FocusNode focus4 = FocusNode(); final FocusNode focus5 = FocusNode(); final FocusNode focus6 = FocusNode(); @override void dispose() { // 新增:释放FocusNode focus1.dispose(); focus2.dispose(); focus3.dispose(); focus4.dispose(); focus5.dispose(); focus6.dispose(); super.dispose(); } @override Widget build(BuildContext context) { Size size = MediaQuery.of(context).size; return Scaffold( body: Column( // 修正:补充children数组 children: [ Padding( padding: EdgeInsets.only(top: size.width * .07), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ PhoneCodeTextField(size, codeP1S, focus1, codeP1, index: 1), SizedBox(width: size.width * .040,), PhoneCodeTextField(size, codeP2S, focus2, codeP2, index: 2), SizedBox(width: size.width * .040,), PhoneCodeTextField(size, codeP3S, focus3, codeP3, index: 3), SizedBox(width: size.width * .040,), PhoneCodeTextField(size, codeP4S, focus4, codeP4, index: 4), SizedBox(width: size.width * .040,), PhoneCodeTextField(size, codeP5S, focus5, codeP5, index: 5), SizedBox(width: size.width * .040,), PhoneCodeTextField(size, codeP6S, focus6, codeP6, index: 6), ], ), ), ], ), ); } // 修改:扩展参数,增加FocusNode、index索引、onChanged逻辑 Container PhoneCodeTextField(Size size, String variable, FocusNode focusNode, GlobalKey key, {required int index}) { return Container( width: size.width * .07, child: Form( key: key, child: TextFormField( focusNode: focusNode, decoration: const InputDecoration( counterText: "", focusedBorder: UnderlineInputBorder( borderSide: BorderSide( color: Colors.black, width: 2.0, ), ), border: UnderlineInputBorder( borderSide: BorderSide(color: Colors.black), ), ), maxLength: 1, // 仅第一个输入框默认自动聚焦 autofocus: index == 1, textAlign: TextAlign.center, keyboardType: TextInputType.number, // 新增:输入变化回调处理焦点跳转 onChanged: (value) { setState(() { switch(index) { case 1: codeP1S = value; break; case 2: codeP2S = value; break; case 3: codeP3S = value; break; case 4: codeP4S = value; break; case 5: codeP5S = value; break; case 6: codeP6S = value; break; } }); // 输入了1位数字,跳转到下一个输入框 if (value.length == 1) { focusNode.unfocus(); switch(index) { case 1: FocusScope.of(context).requestFocus(focus2); break; case 2: FocusScope.of(context).requestFocus(focus3); break; case 3: FocusScope.of(context).requestFocus(focus4); break; case 4: FocusScope.of(context).requestFocus(focus5); break; case 5: FocusScope.of(context).requestFocus(focus6); break; // 最后一个输入框输入完成后可以在这里加提交验证码的逻辑 } } // 清空了输入内容,跳转到上一个输入框 if (value.isEmpty) { switch(index) { case 2: FocusScope.of(context).requestFocus(focus1); break; case 3: FocusScope.of(context).requestFocus(focus2); break; case 4: FocusScope.of(context).requestFocus(focus3); break; case 5: FocusScope.of(context).requestFocus(focus4); break; case 6: FocusScope.of(context).requestFocus(focus5); break; } } }, ), ), ); } }
内容的提问来源于stack exchange,提问作者roee attias
相关产品推荐
相关产品推荐

