Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When popping a route, controls should reacquire focus without opening the keyboard or scrolling to make visible. #48464

Open
vijayaragavangkf opened this issue Jan 9, 2020 · 22 comments
Labels
a: text input f: focus f: routes found in release: 1.22 framework has reproducible steps P4

Comments

@vijayaragavangkf
Copy link

@vijayaragavangkf vijayaragavangkf commented Jan 9, 2020

I have number of pages and all of them are kind of forms with some TextFields.

In each page, I am entering some data in TextField and then moving to the next page either by clicking next button directly (Key Board is Visible) or by clicking back button to dismiss keyboard then clicking next button. After the next page, When I trying to go to previous page by back button or Navigator.pop that TextField getting auto focused. This behaviour is really annoying lot.

I verified that in my older version app (Which uses older Flutter SDK) works fine.

Sample code to reproduce:

import 'package:flutter/material.dart';

void main() => runApp(MainPage());

class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: FirstPage(),
    );
  }
}

class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    double height = MediaQuery.of(context).size.height;
    return Scaffold(
      appBar: AppBar(
        title: Text("First Page"),
      ),
      body: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            TextField(),
            Text("Use back button to dismiss keyboar"),
            Text("Scroll down to see next button"),
            SizedBox(
              height: height + 100,
              child: Center(child: Text("Some widgets")),
            ),
            RaisedButton(
              child: Text("Click Here"),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => SecondPage(),
                  ),
                );
              },
            )
          ],
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Page"),
      ),
      body: Column(
        children: <Widget>[
          TextField(),
          RaisedButton(
            child: Text("Go Back"),
            onPressed: () {
              Navigator.pop(context);
            },
          )
        ],
      ),
    );
  }
}

Flutter Doctor:

[√] Flutter (Channel stable, v1.12.13+hotfix.5, on Microsoft Windows [Version 10.0.18362.535], locale en-IN)
    • Flutter version 1.12.13+hotfix.5 at D:\Installed\FlutterSDK
    • Framework revision 27321ebbad (4 weeks ago), 2019-12-10 18:15:01 -0800
    • Engine revision 2994f7e1e6
    • Dart version 2.7.0


[√] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
    • Android SDK at C:\Users\Flower\AppData\Local\Android\sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-29, 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_202-release-1483-b03)
    • All Android licenses accepted.

[√] Android Studio (version 3.5)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin version 42.1.1
    • Dart plugin version 191.8593
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b03)

[√] Connected device (1 available)
    • KOB L09 • VAF4T18531000189 • android-arm64 • Android 7.0 (API 24)

• No issues found!
@VladyslavBondarenko VladyslavBondarenko added a: text input f: focus framework severe: regression labels Jan 9, 2020
@HansMuller HansMuller added the f: material design label Jan 9, 2020
@HansMuller
Copy link
Contributor

@HansMuller HansMuller commented Jan 9, 2020

@gspencergoog
Copy link
Contributor

@gspencergoog gspencergoog commented Jan 9, 2020

This is "as designed", since otherwise we would be losing the previously focused widget when we return to a route.

If you want it to lose the focus so that this doesn't happen, then just unfocus the currently focused widget before you push the route:

class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    double height = MediaQuery.of(context).size.height;
    return Scaffold(
      appBar: AppBar(
        title: Text("First Page"),
      ),
      body: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            TextField(),
            Text("Use back button to dismiss keyboard"),
            Text("Scroll down to see next button"),
            SizedBox(
              height: height + 100,
              child: Center(child: Text("Some widgets")),
            ),
            RaisedButton(
              child: Text("Click Here"),
              onPressed: () {

                // Tells any currently focused widget to unfocus, so that it won't scroll when
                // returning to this page.
                FocusManager.instance.primaryFocus.unfocus();

                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => SecondPage(),
                  ),
                );
              },
            )
          ],
        ),
      ),
    );
  }
}

@vijayaragavangkf
Copy link
Author

@vijayaragavangkf vijayaragavangkf commented Jan 10, 2020

@gspencergoog Please run the code on device or emulator where the in-build keyboard(virtual keyboard) is enabled. By default keyboard is disable in IOS Simulator.. I am getting this issue in Android Device and Emulator. I am not sure about IOS.

And yes we need to get previously focused widget when we return to a route. Showing cursor in the previously focused TextField is good. But the main problem is keyboard is popping up.

On going to next page, I am dismissing keyboard by pressing back button(the cursor is still blinking on TextField). So why when we return to a route the keyboard state is not persisted. And in my example I am scrolling down to get to the next button. Why the scroll state is not persisted.

If it is still "as designed",
In Native Android this is not the case(not sure about swift). Then why flutter is different.

@gspencergoog
Copy link
Contributor

@gspencergoog gspencergoog commented Jan 11, 2020

The scroll state is persisted, but when you go back, it restores the focus to the text field, which causes it to scroll into view. Notice that if you unfocus the text field before pushing (as in my example), then when you go back, the scroll state is unchanged.

If I understand you correctly, what you want is (only when popping a route) focus the text field without bringing up a keyboard, and without scrolling it into view.

Can you give a concrete example of an Android app doing this? I mean, it's probably possible to find, but I've tried a few apps now, and none of the do what you describe: they all either bring up the keyboard again when I go back to the page that had a text field focused, even if I manually put away the keyboard, or the control is unfocused when I go back to them. See the gif below:

text_fields

@gspencergoog gspencergoog reopened this Jan 11, 2020
@vijayaragavangkf
Copy link
Author

@vijayaragavangkf vijayaragavangkf commented Jan 11, 2020

@gspencergoog Thank you.

  1. Gmail - Compose (you can try it on Subject or Compose email Fields too)
  2. Calendar - New Event
  3. WhatApp - Change Number

I am unable to screen record in Netflix android app. You can go to sign in page, then enter username and then password and then navigate to Help page and then navigate back. you can see password field still has focus, but the keyboard not popping.

I am not requesting new feature. It worked fine on older app that build with older Flutter SDK but in latest Flutter SDK(Flutter version 1.12.13+hotfix.5) looks kind of buggy.

@vijayaragavangkf
Copy link
Author

@vijayaragavangkf vijayaragavangkf commented Jan 12, 2020

Demo Native Project. This is a simple native android project with two page with EditText.

@gspencergoog
Copy link
Contributor

@gspencergoog gspencergoog commented Jan 13, 2020

OK, we'll see what we can do to figure out a way to do this.

This may be architecturally difficult with Flutter, so it may take a while, but we'll get to it. Thanks for your examples.

@gspencergoog gspencergoog changed the title "TextField" keep auto focusing when coming back from a page. When popping a route, controls should reacquire focus without opening the keyboard or scrolling to make visible. Jan 13, 2020
@gspencergoog gspencergoog added platform-android and removed f: material design labels Jan 13, 2020
@gspencergoog
Copy link
Contributor

@gspencergoog gspencergoog commented Jan 13, 2020

FYI the cause of the regression is enabling focus upon popping a route. Before that change, popping a route didn't automatically cause controls to re-acquire the focus at all.

@Piinks Piinks added the f: routes label Feb 10, 2020
@goderbauer goderbauer added a: desktop and removed platform-android labels Feb 12, 2020
@davidmartos96
Copy link
Contributor

@davidmartos96 davidmartos96 commented Feb 15, 2020

I have also started experiencing this issue after using v1.9.1 for a long time and now update to 1.12.
I have found a workaround that works fine for my use case, I don't know if there could be unwanted behaviors with this though: @vijayaragavangkf

MaterialApp(
    ...
    navigatorObservers: [ClearFocusOnPush()],
    ...
)


class ClearFocusOnPush extends NavigatorObserver {
  @override
  void didPush(Route route, Route previousRoute) {
    super.didPush(route, previousRoute);
    final focus = FocusManager.instance.primaryFocus;
    focus?.unfocus();
  }
}

I would also like to see a fix for this issue implemented at some point

@vijayaragavangkf
Copy link
Author

@vijayaragavangkf vijayaragavangkf commented Feb 16, 2020

@davidmartos96 Your solution is good to solve the annoying keyboard popup when popping a route. But the previous focus will be lost. This is also an unexpected behavior. I only don't want the keyboard popup, while still persisting previous focus.

@vijayaragavangkf
Copy link
Author

@vijayaragavangkf vijayaragavangkf commented Feb 16, 2020

MaterialApp(
    ...
    navigatorObservers: [ClearFocusOnPop ()],
    ...
)

class ClearFocusOnPop extends NavigatorObserver {
  @override
  void didPop(Route route, Route previousRoute) {
    super.didPop(route, previousRoute);
    WidgetsBinding.instance.addPostFrameCallback((_) async{
      await Future.delayed(Duration.zero);
      SystemChannels.textInput.invokeMethod('TextInput.hide');
    });
  }
}

This will solve the problem. But not sure this an efficient way to do so.

@goderbauer goderbauer added this to the Goals milestone Mar 18, 2020
@gspencergoog gspencergoog removed the severe: regression label May 6, 2020
@kf6gpe kf6gpe added the P4 label May 29, 2020
@sanekyy
Copy link

@sanekyy sanekyy commented Jun 15, 2020

faced with the same problem. waiting for fix

@galves93
Copy link

@galves93 galves93 commented Jun 17, 2020

I facing a problem with the screen that scroll when focus node change to another input, anyone here already face the problem or something similar?
Screenshot_1592405397
when the first input is submitted, the focus goes to the field named "Quantidade", and the screen scrolls down ... thank guys

@Hixie Hixie removed this from the None. milestone Aug 17, 2020
@TahaTesser TahaTesser removed the a: desktop label Sep 25, 2020
@TahaTesser
Copy link
Member

@TahaTesser TahaTesser commented Sep 25, 2020

This doesn't to bedesktop related
Looks like this is debatable if this is working as intended or a bug, nevertheless I can reproduce

code sample
import 'package:flutter/material.dart';

void main() => runApp(MainPage());

class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: FirstPage(),
    );
  }
}

class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    double height = MediaQuery.of(context).size.height;
    return Scaffold(
      appBar: AppBar(
        title: Text("First Page"),
      ),
      body: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            TextField(),
            Text("Use back button to dismiss keyboar"),
            Text("Scroll down to see next button"),
            SizedBox(
              height: height + 100,
              child: Center(child: Text("Some widgets")),
            ),
            RaisedButton(
              child: Text("Click Here"),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => SecondPage(),
                  ),
                );
              },
            )
          ],
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Page"),
      ),
      body: Column(
        children: <Widget>[
          TextField(),
          RaisedButton(
            child: Text("Go Back"),
            onPressed: () {
              Navigator.pop(context);
            },
          )
        ],
      ),
    );
  }
}
flutter doctor -v
[✓] Flutter (Channel master, 1.22.0-10.0.pre.358, on Mac OS X 10.15.6 19G2021
    x86_64, locale en-GB)
    • Flutter version 1.22.0-10.0.pre.358 at
      /Users/tahatesser/Code/flutter_master
    • Framework revision 4898a42b0a (2 hours ago), 2020-09-25 05:42:04 -0400
    • Engine revision 62b5a53b10
    • Dart version 2.11.0 (build 2.11.0-161.0.dev)

 
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
    • Android SDK at /Users/tahatesser/Code/sdk
    • Platform android-30, build-tools 30.0.2
    • ANDROID_HOME = /Users/tahatesser/Code/sdk
    • Java binary at: /Applications/Android
      Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build
      1.8.0_242-release-1644-b3-6222593)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 12.0.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 12.0.1, Build version 12A7300
    • CocoaPods version 1.9.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.0)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 49.0.2
    • Dart plugin version 193.7547
    • Java version OpenJDK Runtime Environment (build
      1.8.0_242-release-1644-b3-6222593)

[✓] VS Code (version 1.49.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.14.1

[✓] Connected device (4 available)
    • RMX2001 (mobile) • EUYTFEUSQSRGDA6D • android-arm64  • Android 10 (API 29)
    • macOS (desktop)  • macos            • darwin-x64     • Mac OS X 10.15.6
      19G2021 x86_64
    • Web Server (web) • web-server       • web-javascript • Flutter Tools
    • Chrome (web)     • chrome           • web-javascript • Google Chrome
      85.0.4183.121

• No issues found!

@TahaTesser TahaTesser added found in release: 1.22 has reproducible steps labels Sep 25, 2020
@rh-id
Copy link

@rh-id rh-id commented Dec 23, 2020

Hi, same issue on version 1.22.5. also waiting for fix

@febg11
Copy link

@febg11 febg11 commented Dec 29, 2020

navigatorObservers: [ClearFocusOnPush()],

Thanks @davidmartos96, worked perfectly.

@Asquare17
Copy link

@Asquare17 Asquare17 commented Feb 26, 2021

Hi
Please is there any solution to this problem yet

@3crazyspecial
Copy link

@3crazyspecial 3crazyspecial commented May 20, 2021

My page has a lot of operations to use pushPage to the next page, and I expect that if the input field is focused when the pushPage to a new page comes back when the keyboard won't be focused

if i use the code

FocusManager.instance.primaryFocus?.unfocus();

when I back page, the keyboard can not be used

How to deal with it better

@3crazyspecial
Copy link

@3crazyspecial 3crazyspecial commented May 20, 2021

@gspencergoog Thank you.

  1. Gmail - Compose (you can try it on Subject or Compose email Fields too)
  2. Calendar - New Event
  3. WhatApp - Change Number


I am unable to screen record in Netflix android app. You can go to sign in page, then enter username and then password and then navigate to Help page and then navigate back. you can see password field still has focus, but the keyboard not popping.

I am not requesting new feature. It worked fine on older app that build with older Flutter SDK but in latest Flutter SDK(Flutter version 1.12.13+hotfix.5) looks kind of buggy.

Same question

@rockingdice
Copy link

@rockingdice rockingdice commented Aug 4, 2021

+1 on this issue.

@jgat2012
Copy link

@jgat2012 jgat2012 commented Aug 23, 2021

I am also facing the same issue.

@phankietit
Copy link

@phankietit phankietit commented Jan 10, 2022

Same issue, auto focus cannot working for this case :(((

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a: text input f: focus f: routes found in release: 1.22 framework has reproducible steps P4
Projects
None yet
Development

No branches or pull requests