Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter - Keyboard Show and Hide Causes Build Calls

Tags:

flutter

dart

I've been recently learning Flutter and came across some strange problem, when I click on the TextField the keyboard will be shown and the build will be called for the hosted and all ancestor widgets.

I've read that when TextField clicked, the build method will be called, then the whole widget will be rebuilt, but the case that I encountered is somehow strange, since the build is not called on the first opened widget.

Scenario:

1 - Open app.

2 - First widget loads and printed on screen: "First build called", and when I click on the TextField, the keyboard pops up and nothing printed on console.

3 - Click on "Open Second", the second widget loads and printed on screen: "Second build called", and when I click on the TextField, the keyboard pops up and print: "Second build called" (in step[1] nothing printed!).

4 - Click on "Open First", the first widget loads again and printed on screen: "First build called", and when I click on the TextField, the keyboard pops up and print: "Second build called First build called" (in step[1] for the same widget that didn't print anything!).

Code:

void main() {
  runApp(MaterialApp(home: First()));
}

class First extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print('First build called');
    return Scaffold(
      appBar: AppBar(
        title: Text("HI Ramadan"),
      ),
      body: Column(
        children: <Widget>[
          TextField(),
          RaisedButton(onPressed: () {
            Navigator.push(
                context, MaterialPageRoute(builder: (context) => Second()));
          }, child: Text('Open Second'),),
        ],
      ),
    );
  }
}

class Second extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print('Second build called');
    return Scaffold(
      body: Column(
        children: <Widget>[
          TextField(),
          RaisedButton(onPressed: () {
            Navigator.push(context, MaterialPageRoute(builder: (context) => First()));
          }, child: Text('Open First')),
        ],
      ),
    );
  }
}

Flutter doctor:

[√] Flutter (Channel stable, v1.7.8+hotfix.4, on Microsoft Windows [Version 10.0.17134.885], locale en-US)
    • Flutter version 1.7.8+hotfix.4 at C:\flutter
    • Framework revision 20e59316b8 (3 weeks ago), 2019-07-18 20:04:33 -0700
    • Engine revision fee001c93f
    • Dart version 2.4.0

[√] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
    • Android SDK at C:\Users\ASUS\AppData\Local\Android\sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-28, build-tools 28.0.3
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1248-b01)
    • All Android licenses accepted.

[√] Android Studio (version 3.3)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin version 34.0.1
    • Dart plugin version 182.5215
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1248-b01)

[√] VS Code (version 1.36.1)
    • VS Code at C:\Users\ASUS\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.2.0

[√] Connected device (1 available)
    • FLA LX1 • 75U7N18410006702 • android-arm64 • Android 9 (API 28)

• No issues found!


Questions:

1 - Why this is happening (Called build on every widget that is not the root of the tree)?

2 - Is there a way to force flutter not calling build when the keyboard shows or hides? since I have a form, when I click over TextField and typing something, then clicking over DropDown the DropDown will be shown then hide directly (because build called) and I need to click on the DropDown one more time to select!

like image 315
Mohammad Shahhoud Avatar asked Aug 09 '19 09:08

Mohammad Shahhoud


People also ask

How do you hide soft input keyboard on Flutter after clicking outside TextField anywhere on screen?

To make the keyboard go away itself, we need to remove “focus” from all of our text fields (if your app has more than one text field) by calling the unfocus() method: FocusManager.

When build function is called in Flutter?

The build method is called any time you call setState , your widget's dependencies update, or any of the parent widgets are rebuilt (when setState is called inside of those).


3 Answers

Keep in mind you should always write your build methods as if they're being called 60 times a second. So they should be (a) fast and (b) idempotent.

like image 123
Randal Schwartz Avatar answered Oct 29 '22 00:10

Randal Schwartz


First is rebuilt because its position in the navigation stack changed.

As for your keyboard issue, this post tackled it, you just have to make a slight change to your code:

Change this :

  RaisedButton(
      onPressed: () {
         Navigator.push(context, MaterialPageRoute(builder: (context) => Second()));
      },
      child: Text('Open Second'),
  ),

  RaisedButton(
      onPressed: () {
         Navigator.push(context, MaterialPageRoute(builder: (context) => First()));
      },
      child: Text('Open First'),
  ),

To:

  RaisedButton(
      onPressed: () {
          final page = Second();
          Navigator.push(context,MaterialPageRoute(builder: (context) => page ));
      }, 
      child: Text('Open Second'),
  ),

  RaisedButton(
      onPressed: () {
          final page = First();
          Navigator.push(context,MaterialPageRoute(builder: (context) => page ));
      }, 
      child: Text('Open First'),
  ),
like image 2
Mazin Ibrahim Avatar answered Oct 29 '22 00:10

Mazin Ibrahim


Based on Mazin Ibrahim answer, I managed to solve the keyboard build problem:

Define all your navigator widgets as final in case using routes.

In case of using routes, I managed to define all my navigation widgets as final fields inside the routes class.

That's stops of recreating the same widget more than once, especially that my widgets are all Stateless.

like image 2
Mohammad Shahhoud Avatar answered Oct 29 '22 01:10

Mohammad Shahhoud