请参考以下代码
使用 ScrollController,您可以通过添加这段代码在 Description TextField 为 onTapped 和 onFocus 时滚动到底部
_controller.animateTo(
_controller.position.maxScrollExtent,
duration: Duration(seconds: 1),
curve: Curves.fastOutSlowIn,
);
final _controller = ScrollController();
ListView(
controller: _controller,
children: [
Column(
children: [
Text('Title'),
TitleField(
controller: titleEditingController,
),
Text(
'Description',
),
DescriptionField(
focusNode: _focusNode,
controller: descriptionEditingController),
DCDatePicker(),
],
),
SizedBox(
height: 15.0,
),
AddButton(),
SizedBox(
height: 250.0,
), // Add space at end of list view so it allows to scroll
],
),
请参考下面的示例代码
class MainScreen extends StatefulWidget {
MainScreen({Key key}) : super(key: key);
@override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
final TextEditingController emailController = TextEditingController();
final FocusNode emailFocus = FocusNode();
final TextEditingController pswdController = TextEditingController();
final FocusNode pswdFocus = FocusNode();
final _validationKey = GlobalKey<FormState>();
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
int validateEmail(String emailAddress) {
String patttern = r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$';
RegExp regExp = new RegExp(patttern);
if (emailAddress.isEmpty || emailAddress.length == 0) {
return 1;
} else if (!regExp.hasMatch(emailAddress)) {
return 2;
} else {
return 0;
}
}
int validatePassword(String pswd) {
if (pswd.isEmpty || pswd.length == 0) {
return 1;
} else if (pswd != null && pswd.isNotEmpty && pswd.length <= 8) {
return 2;
} else {
return 0;
}
}
final _controller = ScrollController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.lightBlue,
automaticallyImplyLeading: true,
leading: Icon(
Icons.arrow_back,
),
title: Text("Example"),
centerTitle: true,
),
body: Container(
padding: EdgeInsets.all(15.0),
child: ListView(
controller: _controller,
children: [
Form(
key: _validationKey,
child: Column(
children: [
/* Email */
TextFormField(
autovalidateMode: AutovalidateMode.onUserInteraction,
/* autovalidate is disabled */
controller: emailController,
keyboardType: TextInputType.emailAddress,
onChanged: (val) {},
maxLines: 1,
validator: (value) {
int res = validateEmail(value);
if (res == 1) {
return "Please fill email address";
} else if (res == 2) {
return "Please enter valid email address";
} else {
return null;
}
},
focusNode: emailFocus,
autofocus: false,
decoration: InputDecoration(
errorMaxLines: 3,
counterText: "",
filled: true,
fillColor: Colors.white,
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Color(0xffE5E5E5),
),
),
disabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Color(0xffE5E5E5),
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Color(0xffE5E5E5),
),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Colors.red,
)),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Colors.red,
),
),
hintText: "Enter email address" ?? "",
),
),
SizedBox(
height: 15.0,
),
/* Password */
TextFormField(
autovalidateMode: AutovalidateMode.onUserInteraction,
/* autovalidate is disabled */
controller: pswdController,
inputFormatters: [
FilteringTextInputFormatter.deny(RegExp(r"\s\s")),
FilteringTextInputFormatter.deny(RegExp(
r'(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])')),
],
keyboardType: TextInputType.text,
onChanged: (val) {},
maxLines: 15,
validator: (value) {
int res = validatePassword(value);
if (res == 1) {
return "Please enter password";
} else if (res == 2) {
return "Please enter minimum 9 characters";
} else {
return null;
}
},
focusNode: pswdFocus,
autofocus: false,
onTap: () {
_controller.animateTo(
_controller.position.maxScrollExtent,
duration: Duration(seconds: 1),
curve: Curves.fastOutSlowIn,
);
},
decoration: InputDecoration(
errorMaxLines: 3,
counterText: "",
filled: true,
fillColor: Colors.white,
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Color(0xffE5E5E5),
),
),
disabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Color(0xffE5E5E5),
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Color(0xffE5E5E5),
),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Colors.red,
)),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Colors.red,
),
),
hintText: "Enter password" ?? "",
),
),
],
),
),
SizedBox(
height: 15.0,
),
OutlinedButton(
onPressed: () {
_validationKey.currentState.validate();
if (emailController.text.isEmpty) {
emailFocus.requestFocus();
} else if (pswdController.text.isEmpty ||
pswdController.text.length <= 8) {
pswdFocus.requestFocus();
_controller.animateTo(
_controller.position.maxScrollExtent,
duration: Duration(seconds: 1),
curve: Curves.fastOutSlowIn,
);
}
},
child: Text("Validate"),
),
SizedBox(
height: 250.0,
),
],
),
),
);
}
}