skip to Main Content

I’m encountering an issue in my Flutter app where the keyboard dismisses automatically after typing or removing just one character in a TextFormField. I have a ListView.builder with Dismissible widgets containing TextFormFields. However, whenever I type or remove a character in the TextFormField, the keyboard dismisses unexpectedly.

My code:

import 'package:flutter/material.dart';
import 'package:r6stats/scanner_result.dart';

class PlayerEditor extends StatefulWidget {
  const PlayerEditor({super.key, required this.playerNames});

  final List<String> playerNames;

  @override
  State<PlayerEditor> createState() => _PlayerEditorState();
}

class _PlayerEditorState extends State<PlayerEditor> {

  @override
  Widget build(BuildContext context) {
    List<String> players = widget.playerNames;

    return Scaffold(
      appBar: AppBar(
        title: const Text("Edit Players"),
        actions: [
          IconButton(
              onPressed: () {
                Navigator.of(context).push(
                  MaterialPageRoute(
                    builder: (context) => ScannerResult(playerNames: players),
                  ),
                );
              },
              icon: const Icon(Icons.check))
        ],
      ),
      body: ListView.builder(
        itemCount: players.length,
        itemBuilder: (context, index) => Padding(
          padding: const EdgeInsets.all(8),
          child: Dismissible(
            key: UniqueKey(),
            direction: DismissDirection.startToEnd,
            onDismissed: (direction) {
              final playerName = players[index];
              ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                content: Text("${players[index]} dismissed"),
                action: SnackBarAction(
                  label: 'UNDO',
                  onPressed: () {
                    setState(() {
                      players.insert(index, playerName);
                    });
                  },
                ),
              ));
              setState(() {
                players.removeAt(index);
              });
            },
            background: Container(
              color: Colors.red,
              alignment: Alignment.centerLeft,
              padding: const EdgeInsets.only(left: 20.0),
              child: const Icon(Icons.delete, color: Colors.white),
            ),
            child: ListTile(
              tileColor: const Color.fromRGBO(194, 194, 194, 100),
              shape: const RoundedRectangleBorder(
                  side: BorderSide(color: Colors.black, width: 1)),
              title: TextFormField(
                initialValue: players[index],
                onChanged: (newValue) {
                  setState(() {
                    players[index] = newValue;
                  });
                },
                style: Theme.of(context)
                    .textTheme
                    .titleMedium!
                    .copyWith(color: Colors.black),
                decoration: const InputDecoration(
                  border: InputBorder.none,
                  focusedBorder: InputBorder.none,
                  hintText: 'Enter player name',
                ),
              ),
              titleTextStyle: Theme.of(context)
                  .textTheme
                  .titleMedium!
                  .copyWith(color: Colors.black),
            ),
          ),
        ),
      ),
    );
  }
}

I’ve tried using GlobalKey for the ListView.builder and UniqueKey for each Dismissible widget, but the issue persists. How can I prevent the keyboard from dismissing automatically after typing or removing a character?

Any insights or suggestions would be greatly appreciated. Thank you!

2

Answers


  1. I think there might be two problems with your code.

    1. Since you are changing the list of players, and you can not change the value of widget.playerNames, you must copy the List items. So, do this:
    List<String> players = [...widget.playerNames];
    
    1. You don’t need to use setState in your onChanged method.
    Login or Signup to reply.
  2. I try to fix the two issues here, 1. Your playerNames list is a final list which is not okay to modify. 2. I removed the setState from your textFormField that I may cause the problem of keyboard dismisses.automatically.

    import 'package:flutter/material.dart';
    import 'package:r6stats/scanner_result.dart';
    
    class PlayerEditor extends StatefulWidget {
      const PlayerEditor({super.key, required this.playerNames});
    
      final List<String> playerNames;
    
      @override
      State<PlayerEditor> createState() => _PlayerEditorState();
    }
    
    class _PlayerEditorState extends State<PlayerEditor> {
      
      List<String> players = [];
      
        @override
      void initState() {
        super.initState();
        players = List<String>.from(widget.playerNames);
      }
    
    
      @override
      Widget build(BuildContext context) {
        
        return Scaffold(
          appBar: AppBar(
            title: const Text("Edit Players"),
            actions: [
              IconButton(
                  onPressed: () {
                    Navigator.of(context).push(
                      MaterialPageRoute(
                        builder: (context) => ScannerResult(playerNames: players),
                      ),
                    );
                  },
                  icon: const Icon(Icons.check))
            ],
          ),
          body: ListView.builder(
            itemCount: players.length,
            itemBuilder: (context, index) => Padding(
              padding: const EdgeInsets.all(8),
              child: Dismissible(
                key: UniqueKey(),
                direction: DismissDirection.startToEnd,
                onDismissed: (direction) {
                  final playerName = players[index];
                  ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                    content: Text("${players[index]} dismissed"),
                    action: SnackBarAction(
                      label: 'UNDO',
                      onPressed: () {
                        setState(() {
                          players.insert(index, playerName);
                        });
                      },
                    ),
                  ));
                  setState(() {
                    players.removeAt(index);
                  });
                },
                background: Container(
                  color: Colors.red,
                  alignment: Alignment.centerLeft,
                  padding: const EdgeInsets.only(left: 20.0),
                  child: const Icon(Icons.delete, color: Colors.white),
                ),
                child: ListTile(
                  tileColor: const Color.fromRGBO(194, 194, 194, 100),
                  shape: const RoundedRectangleBorder(
                      side: BorderSide(color: Colors.black, width: 1)),
                  title: TextFormField(
                    initialValue: players[index],
                    onChanged: (newValue) {
                      players[index] = newValue;
                    },
                    style: Theme.of(context)
                        .textTheme
                        .titleMedium!
                        .copyWith(color: Colors.black),
                    decoration: const InputDecoration(
                      border: InputBorder.none,
                      focusedBorder: InputBorder.none,
                      hintText: 'Enter player name',
                    ),
                  ),
                  titleTextStyle: Theme.of(context)
                      .textTheme
                      .titleMedium!
                      .copyWith(color: Colors.black),
                ),
              ),
            ),
          ),
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search