我的应用程序中有一个奇怪的问题,我有一个注册页面,其中包含多个文本表单字段在 ListView 中,而 ListView 是表单的子项。
当我到达 ListView 中的最后一个表单域时,我需要向上滚动屏幕才能真正看到我在该域中输入的内容。当我向上滚动时,失去焦点的 textformfields 会丢失输入的文本并初始化为 null。我不确定我错过了什么,或者我是否必须使用其他方式来确保我保留 TextFormField 值。我试图在每个 TextFormField 中使用 Controller ,然后即使我向上滚动它也会保留该值。但是,对象的属性,例如 hostelData.hostelName 仅在第一次更新,并且从第二次开始,更改不会反射(reflect)在对象属性中。我不太确定我错过了什么?请有人帮我解决这个问题。 请原谅我发帖时的错误,因为我是编程新手,任何帮助将不胜感激。
我已经发布了下面的代码,以便您可以重现相同的问题。
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:myhostel/theme.dart' as Theme;
import 'package:myhostel/globals.dart' as gl;
class SignUp extends StatefulWidget {
const SignUp({ Key key }) : super(key: key);
@override
_SignUpState createState() => new _SignUpState();
}
class HostelData{
String hostelName = '';
String ownersName = '';
String mobileNumber = '';
String emailId = '';
String password = '';
String city = '';
String hostelType= 'mens';
String confirmPassword ='';
}
class _SignUpState extends State<SignUp> {
HostelData hostelData = new HostelData();
void showInSnackBar(String value) {
_scaffoldKey.currentState.showSnackBar(new SnackBar(
content: new Text(value),
duration: const Duration(milliseconds: 3000),
));
}
final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
final GlobalKey<FormFieldState<String>> _passwordFieldKey = new
GlobalKey<FormFieldState<String>>();
bool _autovalidate = false;
bool _formWasEdited = false;
void _handleSubmitted() {
final FormState form = _formKey.currentState;
if (!form.validate()) {
_autovalidate = true; // Start validating on every change.
showInSnackBar('Please fix the errors in red before submitting.');
} else {
form.save();
showInSnackBar('${hostelData.ownersName}\'s hostel name is
${hostelData.hostelName}');
_createuserwithemailandpassword();
}
}
String _validateName(String value) {
_formWasEdited = true;
if (value.isEmpty)
return 'Name is required.';
final RegExp nameExp = new RegExp(r'^[A-Za-z ]+$');
if (!nameExp.hasMatch(value))
return 'Please enter only alphabetical characters and spaces.';
return null;
}
String _validatePassword(String value) {
_formWasEdited = true;
final FormFieldState<String> passwordField =
_passwordFieldKey.currentState;
if (passwordField.value == null || passwordField.value.isEmpty)
return 'Please choose a password.';
if (passwordField.value != value)
return 'Passwords don\'t match';
return null;
}
@override
Widget build(BuildContext context){
return new MaterialApp(
theme: Theme.MyHostelThemeData,
home: new Scaffold(
key: _scaffoldKey,
body: new Container(
child: new Container(
decoration: new BoxDecoration(
image: new DecorationImage(
image: new AssetImage('assets/bg.png'),
fit: BoxFit.fill,
),
),
child: new Form(
key: _formKey,
autovalidate: _autovalidate,
child: new ListView(
children: <Widget>[
new Container(
margin: const EdgeInsets.only(top:32.0),
child: new Center(
child: new Text('SIGN UP',
style: new TextStyle(
color: const Color(0xFFF5FEFD),fontSize:24.0,fontWeight:
FontWeight.bold),
),
),
),
new Row(
children:[
new Expanded(
child: new Container(
margin: const EdgeInsets.only(left: 24.0,right: 12.0,),
child:new TextFormField(decoration: new InputDecoration(
/*hintStyle: new TextStyle(
fontSize: 20.0,color: const Color(0xFFF5FEFD),),*/
labelText: 'Hostel Name',
),
/*style: new TextStyle(
fontSize: 20.0,
color: Colors.white,
),*/
onSaved:(String value){ hostelData.hostelName = value; },
validator: _validateName,
),
),
),
],
),
new Row(
children:[
/*new Container(
margin: const EdgeInsets.all(8.0),
width: 24.0,
child: new Image.asset(
'assets/person_avatar.png',
fit: BoxFit.contain,
//alignment: FractionalOffset.center,
),
),*/
new Expanded(
child: new Container(
margin: const EdgeInsets.only(left: 24.0,right: 12.0,),
child:new TextFormField(
//controller: _ownersNameController,
decoration: new InputDecoration(//hintText: 'Mobile
Number',
/* hintStyle: new TextStyle(fontSize: 20.0,color: const
Color(0xFFF5FEFD),),*/
labelText: 'Owners Name',
),
/*style: new TextStyle(
fontSize: 20.0,
color: Colors.white,
),*/
onSaved: (String value) { hostelData.ownersName = value;
},
validator: _validateName,
),
),
),
],
),
new Row(
children:[
new Expanded(
child: new Container(
margin: const EdgeInsets.only(left: 24.0,right: 12.0,),
child:new TextFormField(
//controller: _mobileNumberController,
keyboardType: TextInputType.phone,
decoration: new InputDecoration(//hintText: 'Mobile
Number',
/* hintStyle: new TextStyle(fontSize: 20.0,color:
const Color(0xFFF5FEFD),),*/
labelText: 'Mobile Number',
//prefixText: '+91',
),
/*style: new TextStyle(
fontSize: 20.0,
color: Colors.white,
),*/
onSaved: (String value) { hostelData.mobileNumber = value; },
//validator: _validatePhoneNumber,
),
),
),
],
),
//implements EmailID Row
new Row(
children:[
new Expanded(
child: new Container(
margin: const EdgeInsets.only(left: 24.0,right: 12.0,),
child:new TextFormField(
//controller: _emailIdController,
decoration: new InputDecoration(
//hintText: 'Mobile Number',
/*hintStyle: new TextStyle(fontSize: 20.0,color: const
Color(0xFFF5FEFD),),*/
labelText: 'EMail Id',
helperText: 'Required',
),
/*style: new TextStyle(
fontSize: 20.0,
color: Colors.white,
),*/
onSaved: (String value){hostelData.emailId = value;},
),
),
),
],
),
//implements the password row
new Container(
padding: const EdgeInsets.only(left: 8.0,),
child: new Row(
children: <Widget>[
new Container(
margin: const EdgeInsets.only(top: 16.0),
//padding: const EdgeInsets.all(8.0),
child: new Icon(Icons.lock_outline,
color: const Color(0xFFF5FEFD)
),
),
new Expanded(
child: new Container(
margin: const EdgeInsets.only(
left: 28.0, right: 12.0,),
child: new TextFormField(
key: _passwordFieldKey,
//controller: _passwordController,
decoration: const InputDecoration(
hintText: 'min 8 characters',
labelText: 'Password',
helperText: 'Required',
),
autocorrect: false,
//obscureText: true,
//validator: 'Required',
/*style: DefaultTextStyle.of(context).style.merge(new
TextStyle(
fontSize: 16.0,
color: CustomColors.fontColor,
),
),*/
onSaved: (String value){hostelData.password = value;},
),
),
),
],
),
),
new Container(
padding: const EdgeInsets.only(left: 8.0,),
child: new Row(
children: <Widget>[
new Container(
margin: const EdgeInsets.only(top: 16.0),
//padding: const EdgeInsets.all(8.0),
child: new Icon(Icons.lock_outline,
color: const Color(0xFFF5FEFD)
),
),
new Expanded(
child: new Container(
margin: const EdgeInsets.only(
left: 28.0, right: 12.0,),
child: new TextFormField(
//controller: _confirmpasswordcontroller,
decoration: const InputDecoration(
labelText: 'Confirm Password',
helperText: 'Required'
),
autocorrect: false,
// obscureText: true,
//validator: 'Required',
/*style: DefaultTextStyle.of(context).style.merge(new
TextStyle(
fontSize: 16.0,
color: CustomColors.fontColor,
),
),*/
//onSaved: (String value){hostelData.confirmPassword =
value;},
validator: _validatePassword,
),
),
),
],
),
),
new Row(
children:[
new Expanded(
child: new Container(
margin: const EdgeInsets.only(left: 24.0,right: 12.0,),
child:new TextFormField(
controller: _cityController,
decoration: new InputDecoration(labelText: 'City*'),
onSaved: (String value){hostelData.city = value;},
validator: _validateName,
),
),
),
],
),
new Container(
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.only(left:24.0,right: 24.0),
decoration: new BoxDecoration(
border: new Border.all(
color: Colors.white,
width: 2.0,
),
borderRadius: new BorderRadius.all(const
Radius.circular(32.0),)
),
child: new FlatButton(
onPressed: ((){
print('SignUp Button Clicked');
_handleSubmitted();
}),
child: new Text (
'SIGN UP',
style: new TextStyle(fontSize: 24.0,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
),
new Row(
children:[
new Container(
margin: const EdgeInsets.only(left: 24.0,bottom: 12.0),
child:new Text(
'Already have an account?',
style: new TextStyle(
fontSize: 20.0,
color: Colors.white,
),
),
),
new Container(
padding: const EdgeInsets.only(right: 8.0,top:
4.0,bottom:16.0),
margin: const EdgeInsets.only(right: 12.0,left: 4.0),
child:
new MaterialButton(
onPressed: ((){
//Sign In Button pressed declaration here
print('sign in button clicked');
}),
child: new Text('SignIn',
style: new TextStyle(
fontSize: 16.0,
color: Colors.teal[200],
),
),
minWidth: 16.0,
),
),
],
),
new Container(
padding: const EdgeInsets.only(left: 16.0),
child: new Text('* indicates required field',
style: new TextStyle(
fontSize: 14.0,
color: Colors.white,
),),
),
]
),
),
),
),
),
);
} // widget ends here
globals.dart
library my_hostel.globals;
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_database/firebase_database.dart';
final FirebaseAuth auth = FirebaseAuth.instance;
final DatabaseReference messagesRef =FirebaseDatabase.instance.reference();
最佳答案
这是一个工作代码示例:
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String s1 = "";
String s2 = "";
String s3 = "";
String s4 = "";
String s5 = "";
final TextEditingController c1 = new TextEditingController();
final TextEditingController c2 = new TextEditingController();
final TextEditingController c3 = new TextEditingController();
final TextEditingController c4 = new TextEditingController();
final TextEditingController c5 = new TextEditingController();
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text("Example"),),
body: new ListView(
children: <Widget>[
new Padding(padding: new EdgeInsets.all(70.0),),
new TextField(
controller: c1,
onChanged: (String text) {
s1 = text;
},
),
new Padding(padding: new EdgeInsets.all(70.0),),
new TextField(
controller: c2,
onChanged: (String text) {
s2 = text;
},
),
new Padding(padding: new EdgeInsets.all(70.0),),
new TextField(
controller: c3,
onChanged: (String text) {
s3 = text;
},
),
new Padding(padding: new EdgeInsets.all(70.0),),
new TextField(
controller: c4,
onChanged: (String text) {
s4 = text;
},
),
new Padding(padding: new EdgeInsets.all(70.0),),
new TextField(
controller: c5,
onChanged: (String text) {
s5 = text;
},
),
],
)
);
}
}
您需要在 TextField 中添加一个 TextEditingController。 Listview 删除不可见的小部件,因为渲染大量未显示的小部件会使其性能变差!
关于dart - TextFormField 值未按预期更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46362734/
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数
为什么以下不同?Time.now.end_of_day==Time.now.end_of_day-0.days#falseTime.now.end_of_day.to_s==Time.now.end_of_day-0.days.to_s#true 最佳答案 因为纳秒数不同:ruby-1.9.2-p180:014>(Time.now.end_of_day-0.days).nsec=>999999000ruby-1.9.2-p180:015>Time.now.end_of_day.nsec=>999999998
我正在尝试为我的iOS应用程序设置cocoapods但是当我执行命令时:sudogemupdate--system我收到错误消息:当前已安装最新版本。中止。当我进入cocoapods的下一步时:sudogeminstallcocoapods我在MacOS10.8.5上遇到错误:ERROR:Errorinstallingcocoapods:cocoapods-trunkrequiresRubyversion>=2.0.0.我在MacOS10.9.4上尝试了同样的操作,但出现错误:ERROR:Couldnotfindavalidgem'cocoapods'(>=0),hereiswhy:U
这太简单了,太荒谬了,我在任何地方都找不到关于它的任何信息,包括API文档和Rails源代码:我有一个:belongs_to关联,我开始理解当您没有关联时您在Controller中调用的正常模型方法与您有关联时调用的方法略有不同。例如,我的关联在创建Controller操作时运行良好:@user=current_user@building=Building.new(params[:building])respond_todo|format|if@user.buildings.create(params[:building])#etcetera但我找不到关于更新如何工作的文档:@user
升级到OSXYosemite后,我现有的pow.cx安装不起作用。升级到最新的pow.cx无效。通过事件监视器重新启动它也没有成功。 最佳答案 卸载(!)并重新安装解决了这个问题。curlget.pow.cx/uninstall.sh|shcurlget.pow.cx|sh 关于ruby-on-rails-OSXYosemite更新破坏了pow.cx,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/q
我们在Ubuntu14.04和Gitlab9.3.7上运行,运行良好。我们正在尝试更新到Gitlabv9.3.8的最新安全补丁,但它给我们这个错误:Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension.currentdirectory:/home/git/gitlab/vendor/bundle/ruby/2.3.0/gems/re2-1.0.0/ext/re2/usr/local/bin/ruby-r./siteconf20170720-19622-15i0edf.rbextconf.rbcheckingformain(
我正在尝试使用Sinatra中的重定向和session在网站周围传递一些数据。这是一个简化的示例,使用PrettyPrint进行调试:require'pp'require'rubygems'require'sinatra'enable:sessionsget'/'dosession[:foo]='12345'puts'session1'ppsessionredirectto('/redir')endget'/redir'doputs'session2'ppsession'helloworld'end查看Thin的输出,我看到:>>Listeningon0.0.0.0:4567,CTRL
我遇到了以下问题。我有一个名为user的模型,它有一个名为activated的列。我试图通过激活的方法更新该值?但它给我错误:验证失败:密码不能为空,密码太短(最少6个字符)这对我来说没有意义,因为我没有接触密码字段!我只想更新激活的列。我把我认为相关的代码放在这里,但如果你认为你需要更多,请问:)非常感谢您!型号:attr_accessor:passwordattr_accessible:name,:email,:password,:password_confirmation,:activatedhas_many:sucu_votesemail_regex=/\A[\w+\-.]+@
当且仅当模型存在时,我才尝试更新模型的值。如果没有,我什么都不做。搜索似乎只返回更新或创建问题/答案,但我不想创建。我知道我可以用一个简单的方法来做到这一点:found=Model.find_by_id(id)iffoundupdatestuffend但是,我觉得有一种方法可以在一次调用中完成此操作,而无需分配任何临时本地值或执行if。如果记录不存在,我该如何编写一个Rails调用来更新记录而不出现嘈杂错误?最新的Rails3.x 最佳答案 您可以使用try在对find_by_id或where的结果调用update_attribut