I have a textfield that is inside a BlocBuilder, so that the background color of the textfield changes depending on a parameter of the bloc (if the text entered in the textfield is empty or not). However everytime the background color changes due to the blocBuilder, the textfield loses focus, and keyboard disappear. If the textfield is initially empty, when i type 1 letter, the background color changes and textfield lose focus.
I tried to add a focusNode but it did'nt change anything.
return BlocBuilder<MyCubit, MyState>(
builder: (context, state) {
return Container(
color: (state.description == null ||
state.description!.isEmpty)
? Colors.red
: null,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("title"),
const Divider(color: constants.grey),
TextField(
maxLines: null,
controller: _controller,
),
],
),
),
);
},
);
I have a textfield that is inside a BlocBuilder, so that the background color of the textfield changes depending on a parameter of the bloc (if the text entered in the textfield is empty or not). However everytime the background color changes due to the blocBuilder, the textfield loses focus, and keyboard disappear. If the textfield is initially empty, when i type 1 letter, the background color changes and textfield lose focus.
I tried to add a focusNode but it did'nt change anything.
return BlocBuilder<MyCubit, MyState>(
builder: (context, state) {
return Container(
color: (state.description == null ||
state.description!.isEmpty)
? Colors.red
: null,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("title"),
const Divider(color: constants.grey),
TextField(
maxLines: null,
controller: _controller,
),
],
),
),
);
},
);
Share
Improve this question
edited Feb 3 at 8:41
DarkBee
15.6k8 gold badges72 silver badges117 bronze badges
asked Feb 3 at 8:36
fanfanfanfan
371 silver badge2 bronze badges
2
|
3 Answers
Reset to default 0try using autofocus: true
in the textfield:
Text("title"),
const Divider(color: constants.grey),
TextField(
maxLines: null,
controller: _controller,
autofocus: true,
),
The suggestion from @pkskink in this comment worked for me. The solution was to replace Container
by ColoredBox
.
Solution: Move Controller and FocusNode Outside BlocBuilder
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
late TextEditingController _controller;
late FocusNode _focusNode;
@override
void initState() {
super.initState();
_controller = TextEditingController();
_focusNode = FocusNode();
}
@override
void dispose() {
_controller.dispose();
_focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocBuilder<MyCubit, MyState>(
buildWhen: (previous, current) => previous.description != current.description, // Avoid unnecessary rebuilds
builder: (context, state) {
return Container(
color: (state.description == null || state.description!.isEmpty)
? Colors.red
: null,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("title"),
const Divider(color: Colors.grey),
TextField(
maxLines: null,
controller: _controller,
focusNode: _focusNode,
onChanged: (text) {
context.read<MyCubit>().updateDescription(text);
},
),
],
),
),
);
},
);
}
}
Key Fixes: Preserve TextEditingController and FocusNode
Moved them outside BlocBuilder in StatefulWidget to prevent recreation on every rebuild. Use buildWhen in BlocBuilder
Ensures that the widget rebuilds only when description changes. Use onChanged to Update State
Instead of rebuilding on every keystroke, update the state from onChanged. This will keep the focus on the TextField even when the background color changes!
Container
withColoredBox
? – pskink Commented Feb 3 at 9:34Container
should work too (but I didn't test it) if you replacenull
color withColors.transparent
- check it out – pskink Commented Feb 3 at 11:20