Reputation: 1683
I want create a lot of TextFormField with int value.If user changed TextFormField value i was set FAB to visible.So user can save new value if he hit the FAB.But there is a problem with Setstate.When user changed TextFormField value its trigger OnChanged and i was set FAB visible inside setstate.When i was use setState its reset TextFormFields to initial value.How to avoid this problem?
Thanks
Here my sample code
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
bool FabVisible = false;
final List<TextEditingController> controllers = List.generate(6, (index) {
return TextEditingController();
});
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: SafeArea(
child: Scaffold(
floatingActionButton: FAB(),
body: Center(
child: MyWidget(),
),
),
),
);
}
FloatingActionButton FAB() {
return FabVisible
? FloatingActionButton(onPressed: () {}, child: Icon(Icons.save))
: null;
}
}
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
// final TextEditingController controller = TextEditingController();
// final TextEditingController controller2 = TextEditingController();
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
SingleChildScrollView(
child: Column(
children: textFields(),
),
),
],
);
}
List<TextFormField> textFields() {
List<TextFormField> trash = List();
for (int i = 0; i <= 5; i++) {
TextEditingController controller = controllers[i];
controller.value = TextEditingValue(
text: 10.toString(),
selection: TextSelection.fromPosition(
TextPosition(offset: (10.toString()).length)));
trash.add(
TextFormField(
onChanged: (txt) {
controller.value = TextEditingValue(
text: txt,
selection: TextSelection.fromPosition(
TextPosition(offset: txt.length),
));
setState(() {
FabVisible = true;
});
},
keyboardType: TextInputType.number,
inputFormatters: [WhitelistingTextInputFormatter.digitsOnly],
controller: controller,
style: TextStyle(color: Colors.white),
textAlign: TextAlign.center,
decoration: InputDecoration.collapsed(
hintText: "",
fillColor: Colors.teal,
focusColor: Colors.yellow,
),
),
);
}
return trash;
}
}
Upvotes: 1
Views: 5576
Reputation: 888
In constructor function of class example name class EditPage
EditPage(){
controller.text = 'waad mawlood';
}
this way to reject change value of TextFormField
Upvotes: 0
Reputation: 6161
When you call setState()
, it rebuilds the widget, therefore calling the textFields()
function again. To avoid this, I recommend taking advantage of initState()
. initState()
only gets called when the screen loads for the first time.
Let's see how we can use this:
class _MyWidgetState extends State<MyWidget> {
// final TextEditingController controller = TextEditingController();
// final TextEditingController controller2 = TextEditingController();
final List<Widget> children = [];
@override
void initState() {
textFields();
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
SingleChildScrollView(
child: Column(
children: children,
),
),
],
);
}
void textFields() {
for (int i = 0; i <= 5; i++) {
TextEditingController controller = controllers[i];
controller.value = TextEditingValue(
text: "10", // same thing as 10.toString()
selection: TextSelection.fromPosition(
TextPosition(offset: ("10").length)));
children.add(
TextFormField(
onChanged: (txt) {
controller.value = TextEditingValue(
text: txt,
selection: TextSelection.fromPosition(
TextPosition(offset: txt.length),
));
setState(() {
FabVisible = true;
});
},
keyboardType: TextInputType.number,
inputFormatters: [WhitelistingTextInputFormatter.digitsOnly],
controller: controller,
style: TextStyle(color: Colors.white),
textAlign: TextAlign.center,
decoration: InputDecoration.collapsed(
hintText: "",
fillColor: Colors.teal,
focusColor: Colors.yellow,
),
),
);
}
}
}
Upvotes: 2