最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

flutter - Textfield loses focus insed BlocBuilder - Stack Overflow

programmeradmin0浏览0评论

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
  • 1 tried to replace Container with ColoredBox? – pskink Commented Feb 3 at 9:34
  • In fact Container should work too (but I didn't test it) if you replace null color with Colors.transparent - check it out – pskink Commented Feb 3 at 11:20
Add a comment  | 

3 Answers 3

Reset to default 0

try 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!

发布评论

评论列表(0)

  1. 暂无评论