Flutter: how to maintain TextField value after dismissing the soft Keyboard

Viewed 1158

There is a simple structure with a Bottom Modal Sheet that contains an input TextField to add a Text into a List and a button to submit the value.

When the text field is focused, it automatically opens the soft keyboard that covers the submit button. When I dismiss the keyboard in order to press the button, the value in the text field is still visible but the sent value is null. If I press the button without dismissing the keyboard, the value is correctly sent.

The question is: how can I dismiss the keyboard and still be able to send the typed value after pressing the submit button?

Here is the code:

1) On the main screen, the floating action button shows the modal bottom sheet.

return Scaffold(
    floatingActionButton: FloatingActionButton(
      onPressed: () {
        showModalBottomSheet(
            context: context,
            builder: (context) => AddTaskScreen(),               
      },

2) On the AddTaskScreen class, there is a Column with the content of the modal bottom sheet inside a container.

Container(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          Text(
            'Add your next Task',
            textAlign: TextAlign.center,
            style: TextStyle(
              color: Colors.lightBlueAccent,
              fontSize: 20,
              fontWeight: FontWeight.w400,
            ),
          ),
          TextField(
            textAlign: TextAlign.center,
            autofocus: true,
            onChanged: (value) {
              newTaskTitle = value;
            },
          ),
          FlatButton(
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.all(
                Radius.circular(10),
              ),
            ),
            child: Padding(
              padding: const EdgeInsets.all(8.0),
              child: Text(
                'ADD',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 25,
                ),
              ),
            ),
            color: Colors.lightBlueAccent,
            onPressed: () {
              print(newTaskTitle);
            },
          ),
        ],
      ),
    ),

In this simplified version, the value from the TextField is printed in the console when pressing the button. If I press the button without hiding the keyboard it works fine; If I hide the keyboard it passes a null value.

Thanks in advance for your help.

2 Answers

I had the same issue, I resolved it by simply converting called class to extend StatefullWidget instead of StatelessWidget.

In your case converting class AddTaskScreen() to extend StatefullWidget.

Okay, the easiest way to do this is by supplying a TextEditingController to the child class.

So for your case, you can first create a TextEditingController in the Parent Class, then pass it to the child class. And in the TextField inside child class set the controller: The controller you have passed

Parent Class.....
//// other codes ////
TextEditingController textEditingController = TextEditingController();
return Scafold{
  FloatingActionButton(
  onPressed: () {
    showModalBottomSheet(
        context: context,
        builder: (context) => AddTaskScreen(textEditingController),               
  },
};

And in the child class

class ChildClass extends StatelessWidget(
final TextEditingController textEditingController;
ChildClass({this.textEditingController});
///then inside build method///
Container(
  child: Column(
    crossAxisAlignment: CrossAxisAlignment.center,
    children: <Widget>[
      Text(
        'Add your next Task',
        textAlign: TextAlign.center,
        style: TextStyle(
          color: Colors.lightBlueAccent,
          fontSize: 20,
          fontWeight: FontWeight.w400,
        ),
      ),
      TextField(
        textAlign: TextAlign.center,
        autofocus: true,
        controller: textEditingController, /// here add the controller
        onChanged: (value) {
          newTaskTitle = value;
        },
      ),
      FlatButton(
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.all(
            Radius.circular(10),
          ),
        ),
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Text(
            'ADD',
            style: TextStyle(
              color: Colors.white,
              fontSize: 25,
            ),
          ),
        ),
        color: Colors.lightBlueAccent,
        onPressed: () {
          print(newTaskTitle);
        },
      ),
    ],
  ),
),

Now you can access what was written in the TextField by simply calling textEditingController.value.text from anywhere between these two classes.

Related