screen flickering with every keyboard stroke in Flutter

Issue

I have 2 issues:

  1. the screen is getting rebuilt every time I type something, it was working fine, and not sure what happened!

  1. when I click send, a message will be sent even if the TextField is empty. It basically sends the last message. The text is being cleared but still getting sent.

here is my code

class ChatGroupLayout extends StatefulWidget {
  const ChatGroupLayout({Key? key}) : super(key: key);

  @override
  State<ChatGroupLayout> createState() => _ChatGroupLayoutState();
}

class _ChatGroupLayoutState extends State<ChatGroupLayout> {
  final fieldText = TextEditingController();

  void clearText() {
    fieldText.clear();
  }

  var _enterdMessage;

  void _sendMessage() async {
    final user = await FirebaseAuth.instance.currentUser;
    final userData = await FirebaseFirestore.instance
        .collection('users')
        .doc(user?.uid)
        .get();

    FirebaseFirestore.instance
        .collection('groupsChat')
        .doc('groupsChat')
        .collection('P1HSu0cjsQSyIKZ7ZiX6a74rwzU2')
        .add({
      'text': _enterdMessage.trim(),
      'time': Timestamp.now(),
      'userid': user?.uid,
      'displayname': userData['displayname']
    });
    clearText();
  }

  static final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        backgroundColor: Colors.grey.shade700,
        appBar: AppBar(
          backgroundColor: Colors.black,
          title: ListTile(
            onTap: () => showBarModalBottomSheet(
                context: context,
                builder: (context) => const GroupDetailsScreen()),
            tileColor: Colors.black,
            title: const Center(child: Text('Group Chat')),
            subtitle: const Center(child: Text('323 in this Group')),
          ),
          actions: [
            IconButton(
                onPressed: () {}, icon: const Icon(Icons.favorite_border)),
            IconButton(
              onPressed: () {},
              icon: const Icon(Icons.exit_to_app),
            ),
          ],
        ),
        body: Column(
          children: [
            Expanded(
              child: ChatGroupScreen(),
            ),
            Row(
              children: [
                Expanded(
                  child: Padding(
                    padding: const EdgeInsets.only(
                        left: 6, bottom: 6, right: 0, top: 5),
                    child: TextField(
                      key: _formKey,
                      controller: fieldText,
                      onChanged: (value) {
                        setState(() {
                          _enterdMessage = value;
                        });
                      },
                      decoration: InputDecoration(
                        prefixIcon: IconButton(
                          icon: const Icon(
                            Icons.emoji_emotions_outlined,
                            color: Colors.white,
                          ),
                          onPressed: () {},
                        ),
                        suffixIcon: IconButton(
                          icon: const Icon(
                            Icons.attach_file,
                            color: Colors.white,
                          ),
                          onPressed: () {},
                        ),
                        filled: true,
                        fillColor: Colors.black,
                        hintText: 'type a message',
                        border: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(6),
                          borderSide: const BorderSide(
                            width: 0,
                            style: BorderStyle.none,
                          ),
                        ),
                        contentPadding: EdgeInsets.all(20),
                      ),
                    ),
                  ),
                ),
                IconButton(
                    icon: Icon(Icons.send),
                    onPressed: () {
                      if (_enterdMessage.trim().isEmpty) {
                        return null;
                      } else {
                        _sendMessage();
                        clearText();
                      }
                    }),
              ],
            ),
          ],
          //TextInput
        ),
      ),
    );
  }
}

Solution

So what you need to do: Completely remove the onChanged property of the textField. It is not needed. You can get the current text in the textField from its controller. And in the onPressed function of the icon button check if controller.text is not equal to "" and if yes call the _sendMessage function.
updatedCode:

class ChatGroupLayout extends StatefulWidget {
  const ChatGroupLayout({Key? key}) : super(key: key);

  @override
  State<ChatGroupLayout> createState() => _ChatGroupLayoutState();
}

    class _ChatGroupLayoutState extends State<ChatGroupLayout> {
      final fieldText = TextEditingController();

      void clearText() {
        fieldText.clear();
      }

      void _sendMessage() async {
        final user = await FirebaseAuth.instance.currentUser;
        final userData = await FirebaseFirestore.instance
            .collection('users')
            .doc(user?.uid)
            .get();

        FirebaseFirestore.instance
            .collection('groupsChat')
            .doc('groupsChat')
            .collection('P1HSu0cjsQSyIKZ7ZiX6a74rwzU2')
            .add({
          'text': fieldText.text.trim(),
          'time': Timestamp.now(),
          'userid': user?.uid,
          'displayname': userData['displayname']
        });
      }

      static final _formKey = GlobalKey<FormState>();

      @override
      Widget build(BuildContext context) {
        return SafeArea(
          child: Scaffold(
            backgroundColor: Colors.grey.shade700,
            appBar: AppBar(
              backgroundColor: Colors.black,
              title: ListTile(
                onTap: () => showBarModalBottomSheet(
                    context: context,
                    builder: (context) => const GroupDetailsScreen()),
                tileColor: Colors.black,
                title: const Center(child: Text('Group Chat')),
                subtitle: const Center(child: Text('323 in this Group')),
              ),
              actions: [
                IconButton(
                    onPressed: () {}, icon: const Icon(Icons.favorite_border)),
                IconButton(
                  onPressed: () {},
                  icon: const Icon(Icons.exit_to_app),
                ),
              ],
            ),
            body: Column(
              children: [
                Expanded(
                  child: ChatGroupScreen(),
                ),
                Row(
                  children: [
                    Expanded(
                      child: Padding(
                        padding: const EdgeInsets.only(
                            left: 6, bottom: 6, right: 0, top: 5),
                        child: TextField(
                          key: _formKey,
                          controller: fieldText,
                          decoration: InputDecoration(
                            prefixIcon: IconButton(
                              icon: const Icon(
                                Icons.emoji_emotions_outlined,
                                color: Colors.white,
                              ),
                              onPressed: () {},
                            ),
                            suffixIcon: IconButton(
                              icon: const Icon(
                                Icons.attach_file,
                                color: Colors.white,
                              ),
                              onPressed: () {},
                            ),
                            filled: true,
                            fillColor: Colors.black,
                            hintText: 'type a message',
                            border: OutlineInputBorder(
                              borderRadius: BorderRadius.circular(6),
                              borderSide: const BorderSide(
                                width: 0,
                                style: BorderStyle.none,
                              ),
                            ),
                            contentPadding: EdgeInsets.all(20),
                          ),
                        ),
                      ),
                    ),
                    IconButton(
                        icon: Icon(Icons.send),
                        onPressed: () {
                          if (fieldText.text != "") {
                            _sendMessage();
                            clearText();
                          }
                        }),
                  ],
                ),
              ],
              //TextInput
            ),
          ),
        );
      }
    }

Answered By – TheUltimateOptimist

Answer Checked By – Katrina (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *