我正在创建一个带有用于输入服务器URL的字段的登录表单。网址的TextFormField
已将keyboardType
设置为TextInputType.url
。
当我开始在字段中输入网址时,在输入https://
NoSuchMethodError(NoSuchMethodError:方法“调用”在null上被调用。 接收者:null 尝试调用:call(“ Normal_Mode”,_LinkedHashMap len:0))
此字段引发错误
TextFormField(
controller: _urlController,
onChanged: (value) {},
decoration: const InputDecoration(
icon: const Icon(Icons.http),
hintText: 'http://yourdomain.com/',
labelText: 'Url (no trailing slash /)*',
),
keyboardType: TextInputType.url,
onSaved: (val) {},
validator: (value) {
if (value.isEmpty) {
return 'Address cannot be empty';
}
return null;
},
)
下面是表单的代码
import 'package:flutter/material.dart';
class LoginForm extends StatefulWidget {
LoginForm({Key key}) : super(key: key);
@override
State<StatefulWidget> createState() {
return new LoginFormState();
}
}
class LoginFormState extends State<LoginForm> {
final _formKey = new GlobalKey<FormState>();
final _scaffoldKey = new GlobalKey<ScaffoldState>();
final _scrollViewKey = new GlobalKey<ScaffoldState>();
static final TextEditingController _nameController =
new TextEditingController();
static final TextEditingController _urlController =
new TextEditingController();
static final TextEditingController _userNameController =
new TextEditingController();
static final TextEditingController _passwordController =
new TextEditingController();
String fcmToken = "";
bool _checkBoxUrlHasIndex = true;
@override
initState() {
super.initState();
}
// Instantiate the Formfields. Note we provide persisters for each.
//
@override
Widget build(BuildContext context) {
var loginBtn = Container(
padding: const EdgeInsets.only(top: 8.0),
child: new RaisedButton(
onPressed: () {
_submit(context);
},
child: new Text(
"LOGIN",
style: new TextStyle(color: Colors.white),
),
color: Theme.of(context).primaryColor,
));
var loginForm = new Column(
children: <Widget>[
Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
controller: _nameController,
// onSaved: (val) => _server_name = val,
decoration: const InputDecoration(
icon: const Icon(Icons.web),
hintText: 'Name of site',
labelText: 'Server Name *'),
// onSaved: (String value) { person.name = value; },
validator: (value) {
if (value.isEmpty) {
return 'A name is required for this server';
}
return null;
}),
TextFormField(
controller: _urlController,
onChanged: (value) {},
decoration: const InputDecoration(
icon: const Icon(Icons.http),
hintText: 'http://yourdomain.com/',
labelText: 'Url (no trailing slash /)*',
),
keyboardType: TextInputType.url,
onSaved: (val) {},
validator: (value) {
if (value.isEmpty) {
return 'Address cannot be empty';
}
return null;
},
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Checkbox(
value: _checkBoxUrlHasIndex,
onChanged: (bool value) {
onCheckBoxUrlHasIndexChanged(value);
}),
Text('Append index.php to address'),
]),
TextFormField(
controller: _userNameController,
decoration: const InputDecoration(
icon: const Icon(Icons.person),
hintText: 'Username',
labelText: 'Username *',
),
validator: (value) {
if (value.isEmpty) {
return 'Username cannot be empty';
}
return null;
},
// onSaved: (val) => _username = val,
),
TextFormField(
controller: _passwordController,
decoration: const InputDecoration(
icon: const Icon(Icons.lock),
hintText: 'Password',
labelText: 'Password *',
),
obscureText: true,
validator: (value) {
if (value.isEmpty) {
return 'Password cannot be empty';
}
return null;
},
// onSaved: (val) => _password = val,
),
loginBtn,
Container(
padding: const EdgeInsets.only(top: 8.0),
child: Text('* indicates required field',
style: Theme.of(context).textTheme.caption),
),
],
),
),
],
crossAxisAlignment: CrossAxisAlignment.center,
);
return Scaffold(
appBar: AppBar(
title: Text("Login"),
centerTitle: true,
),
key: _scaffoldKey,
backgroundColor: Colors.white,
body: Center(
child: SingleChildScrollView(
padding: const EdgeInsets.all(8.0),
key: _scrollViewKey,
scrollDirection: Axis.vertical,
child: Container(
decoration: BoxDecoration(color: Colors.white),
child: Container(
child: loginForm,
height: 450.0,
width: 300.0,
),
)),
),
);
}
void _submit(BuildContext context) async {
try {
final form = _formKey.currentState;
if (form.validate()) {
form.save();
}
} catch (ex) {}
}
void onCheckBoxUrlHasIndexChanged(bool value) {
setState(() {
_checkBoxUrlHasIndex = value;
});
}
}