So I am trying to build an Instagram like image editor with all the functionality. I wanted to switch between a text field and a simple Text Widget on tapping on either of them. I found an example online but it does not work in my case.
class _StateTextFieldState extends State<StateTextField> {
FocusNode focusNode;
GlobalKey key = GlobalKey();
TextEditingController controller;
Offset offset = Offset(1, 1);
Color textColor;
double fontSize;
bool highlighted;
final ValueNotifier<Matrix4> notifier = ValueNotifier(Matrix4.identity());
Color pickerColor = Color(0xffffffff);
Color currentColor = Color(0xffffffff);
void changeColor(Color color) {
setState(() => pickerColor = color);
}
@override
void initState() {
highlighted = widget.highlighted;
focusNode = widget.focusNode;
focusNode.addListener(() {
setState(() {
highlighted = true;
});
});
controller = TextEditingController();
super.initState();
}
@override
void dispose() {
controller.dispose();
focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
double fontSize = 24;
String text = "Enter Text!";
bool isEditing = false;
double textWidth = MediaQuery.of(context).size.width * 0.6;
return Container(
key: key,
height: MediaQuery.of(context).size.height * 0.6,
child: MatrixGestureDetector(
onMatrixUpdate: (Matrix4 m, Matrix4 tm, Matrix4 sm, Matrix4 rm) {
setState(() {
notifier.value = m;
});
},
child: Transform(
transform: notifier.value,
child: Row(
children: <Widget>[
Container(
decoration: BoxDecoration(
color: Colors.transparent,
border: highlighted
? Border.all(color: Colors.black, width: 2)
: Border.all(color: Colors.transparent),
),
// color: Colors.redAccent,
width: textWidth,
child:
//_editTitleTextField(controller)
isEditing
? TextField(
textAlign: TextAlign.center,
autofocus: true,
onEditingComplete: () {
setState(() {
text = controller.text;
isEditing = false;
focusNode.unfocus();
print(isEditing);
highlighted = false;
});
},
style: TextStyle(
color: currentColor, fontSize: fontSize),
decoration: InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide:
BorderSide(color: Colors.transparent),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
),
fillColor: Colors.red,
hintText: "Enter text",
hintStyle: TextStyle(color: Colors.red)),
maxLines: 1,
focusNode: focusNode,
// maxLength: 100,
)
: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
text,
style: TextStyle(fontSize: 18),
),
IconButton(
icon: Icon(Icons.edit, color: Colors.white),
onPressed: () {
setState(() {
print(widget);
isEditing = true;
print(isEditing);
});
})
],
),
),
],
),
)
// ),
),
);
}
My problem is that even though isEditing changes on clicking the Iconbutton, the widget does not rebuild and remains the same. Where am I going wrong?
you have to move your variables from build method to class method. Currently each time you rebuild your widget ( for example by taping on a button ) your variables will be get default values
class _StateTextFieldState extends State<StateTextField> {
... your code...
double fontSize = 24;
String text = "Enter Text!";
bool isEditing = false;
@override
Widget build(BuildContext context) {
... your code ...
}
}
The problem here is that , you are using setState and functionality of setState is to rebuild the UI again by calling the build function.
@override
Widget build(BuildContext context) {
double fontSize = 24;
String text = "Enter Text!";
bool isEditing = false;
return Container(
.. . ..
. . .
}
So whenever you call setState ,each time this function is called and your variables are getting re-initialized , hence ,you need to make these variables as class members, instead of making them local variable of build function.
class _StateTextFieldState extends State<StateTextField> {
bool isEditing =false;
. . .
. . .
@override
Widget build(BuildContext context) {
return Container( . . );
}
Hope this helps!
User contributions licensed under CC BY-SA 3.0