import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatelessWidget {
final String title;
MyHomePage({Key key, this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(child: CodeField()),
);
}
}
/// zero-width space character
///
/// this character can be added to a string to detect backspace.
/// The value, from its name, has a zero-width so it's not rendered
/// in the screen but it'll be present in the String.
///
/// The main reason this value is used because in Flutter mobile,
/// backspace is not detected when there's nothing to delete.
const zwsp = '\u200b';
// the selection is at offset 1 so any character is inserted after it.
const zwspEditingValue = TextEditingValue(text: zwsp, selection: TextSelection(baseOffset: 1, extentOffset: 1));
class CodeField extends StatefulWidget {
const CodeField({Key key}) : super(key: key);
@override
_CodeFieldState createState() => _CodeFieldState();
}
class _CodeFieldState extends State<CodeField> {
List<String> code = ['', '', '', ''];
List<TextEditingController> controllers;
List<FocusNode> focusNodes;
@override
void initState() {
// TODO: implement initState
super.initState();
focusNodes = List.generate(4, (index) => FocusNode());
controllers = List.generate(4, (index) {
final ctrl = TextEditingController();
ctrl.value = zwspEditingValue;
return ctrl;
});
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
// give the focus to the first node.
focusNodes[0].requestFocus();
});
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
focusNodes.forEach((focusNode) {
focusNode.dispose();
});
controllers.forEach((controller) {
controller.dispose();
});
}
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(
4,
(index) {
return Container(
width: 20,
height: 20,
margin: const EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
),
child: TextField(
controller: controllers[index],
focusNode: focusNodes[index],
maxLength: 2,
keyboardType: TextInputType.number,
decoration: InputDecoration(
counterText: "",
),
onChanged: (value) {
if (value.length > 1) {
// this is a new character event
if (index + 1 == focusNodes.length) {
// do something after the last character was inserted
FocusScope.of(context).unfocus();
} else {
// move to the next field
focusNodes[index + 1].requestFocus();
}
} else {
// this is backspace event
// reset the controller
controllers[index].value = zwspEditingValue;
if (index == 0) {
// do something if backspace was pressed at the first field
} else {
// go back to previous field
controllers[index - 1].value = zwspEditingValue;
focusNodes[index - 1].requestFocus();
}
}
// make sure to remove the zwsp character
code[index] = value.replaceAll(zwsp, '');
print('current code = $code');
},
),
);
},
),
);
}
}
late FocusNode myFocusNode;
@override
void initState() {
super.initState();
myFocusNode = FocusNode();
}
@override
void dispose() {
// Clean up the focus node when the Form is disposed.
myFocusNode.dispose();
super.dispose();
}
on已更改的属性;
TextField(
focusNode: myFocusNode1,
onChanged: (text) {
myFocusNode2.requestFocus();// I could not remember the correct usage please check
},
),
4条答案
按热度按时间qojgxg4l1#
在Flutter中可以通过不同的方式来实现这一点,我将尝试分享其中最简单的一种。在回答之前,值得一提的是以下问题:
在Flutter中,当TextField为空时,退格键不会发送任何事件(例如,
TextField.onChanged
不会被调用)。在您的情况下,如果用户位于第三个字段,并且他们按下backspace键返回到第二个字段,那么如果没有在相关问题中讨论的解决方案,就无法捕获该按键。简而言之,您需要添加一个零宽度空格字符(它不会被呈现,但会出现在String中)来检测退格键事件。我提到这个问题是因为我正在分享一个使用零宽空格字符(简称zwsp)的示例。
在下面的示例中,我只创建了两个列表,其中包含:
FocusNode
TextEditingController
用于每个字段。根据索引,您可以通过调用以下命令将焦点置于特定字段:
FocusNode.requestFocus()
.类似地,您可以通过调用
FocusNode.unfocus
来移除焦点,也可以通过调用以下命令从任何位置移除任何焦点:FocusScope.of(context).unfocus();
(在下面的示例中,在插入最后一个字符后使用它来隐藏键盘)。话虽如此,这里有一个完整的例子,你可以复制粘贴来尝试一下:
juud5qan2#
您可能希望在每个
TextFormField
上使用一个FocusNode
,这样,一旦您的用户在TextFormField
中输入了文本,您就可以在TextFormField
调用myNextTextFieldFocusNode.requestFocus()
的回调onChanged
中使用xytpbqjk3#
你可以使用onChanged和nodefocus属性。当onChanged被调用时,引用下一个文本域。
初始化焦点节点;
on已更改的属性;
8e2ybdfx4#
在flutter中,用户在一个块中输入2和4个字符后,如何自动聚焦下一个文本字段