[TOC]
表單輸入
1. Flutter 中表單怎么工作?我怎么拿到用戶的輸入?
我們已經(jīng)提到 Flutter 使用不可變的 widget,并且狀態(tài)是分離的,你可能會好奇在這種情境下怎么處理用戶的輸入。在 iOS 中,你經(jīng)常在需要提交數(shù)據(jù)時查詢組件當前的狀態(tài)或動作,但這在 Flutter 中是怎么工作的呢?
在表單處理的實踐中,就像在 Flutter 中任何其他的地方一樣,要通過特定的 widgets。如果你有一個 TextField 或是 TextFormField,你可以通過 TextEditingController 來獲得用戶輸入:
class _MyFormState extends State<MyForm> {
// Create a text controller and use it to retrieve the current value.
// of the TextField!
final myController = TextEditingController();
@override
void dispose() {
// Clean up the controller when disposing of the Widget.
myController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Retrieve Text Input'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: TextField(
controller: myController,
),
),
floatingActionButton: FloatingActionButton(
// When the user presses the button, show an alert dialog with the
// text the user has typed into our text field.
onPressed: () {
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
// Retrieve the text the user has typed in using our
// TextEditingController
content: Text(myController.text),
);
},
);
},
tooltip: 'Show me the value!',
child: Icon(Icons.text_fields),
),
);
}
}
你可以在這里獲得更多信息,或是完整的代碼列表: Retrieve the value of a text field,來自 Flutter Cookbook 。
2. Text field 中的 placeholder 相當于什么?
在 Flutter 中,你可以輕易地通過向 Text widget 的裝飾構(gòu)造器參數(shù)重傳遞 InputDecoration 來展示“小提示”,或是占位符文字:
body: Center(
child: TextField(
decoration: InputDecoration(hintText: "This is a hint"),
),
)
3. 我怎么展示驗證錯誤信息?
就像展示“小提示”一樣,向 Text widget 的裝飾器構(gòu)造器參數(shù)中傳遞一個 InputDecoration。
然而,你并不想在一開始就顯示錯誤信息。相反,當用戶輸入了驗證信息,更新狀態(tài),并傳入一個新的 InputDecoration 對象:
class SampleApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Sample App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SampleAppPage(),
);
}
}
class SampleAppPage extends StatefulWidget {
SampleAppPage({Key key}) : super(key: key);
@override
_SampleAppPageState createState() => _SampleAppPageState();
}
class _SampleAppPageState extends State<SampleAppPage> {
String _errorText;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Sample App"),
),
body: Center(
child: TextField(
onSubmitted: (String text) {
setState(() {
if (!isEmail(text)) {
_errorText = 'Error: This is not an email';
} else {
_errorText = null;
}
});
},
decoration: InputDecoration(hintText: "This is a hint", errorText: _getErrorText()),
),
),
);
}
_getErrorText() {
return _errorText;
}
bool isEmail(String em) {
String emailRegexp =
r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
RegExp regExp = RegExp(p);
return regExp.hasMatch(em);
}
}