flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
165.62k stars 27.34k forks source link

Flutter web textfield on iOS: cursor goes to completely wrong place after tap on text #124483

Open hhkk opened 1 year ago

hhkk commented 1 year ago

Keep in mind - one can't edit text if you can't place the cursor at least very nearby an intended location on tap.

As run in chrome and safari browsers on android and ios cell phones, after many experiments including a simple flutter dev cookbook case we ask...

seen in flutter version 3.2.2 stable and 3.7.10 stable on 3 people's environments.

issue is also seen using http-server against release flutter build web (build/web) content.

To demonstrate:

Open this url on a cell phone https://docs.flutter.dev/cookbook/forms/focus

1 in the cookbook dev code editor add: maxLines: 5

2 click run

3 in the textfield, paste the ~1500 char's "lorem ipsum" text below.

4 tap various places within the text (once the on screen keyboard settles) and

5 !!!!!! issue: you will see cursor does not end up where the tap occurred. bounces to other places, with underlines and confused attempts at hi-lighting I guess

6 this is just one environment to demo this issue in. I've tried many different tests. (I'd be happy to see even one TextField example where this does not occur, on a cell phone.)

sample text to paste:

Lorem ipsum dolor sit amet, dictas habemus nominati ex sed, possit prodesset concludaturque sed ei, usu ut falli constituam. Mea ad ipsum graeci aliquip, iisque volumus theophrastus sit id. Nec ei sumo democritum, qui dicant inimicus repudiare no. Duo no hinc partem ornatus, ei voluptua moderatius eloquentiam cum, pri modus viderer vituperatoribus ad. Ea sea dicunt vidisse sadipscing.

Ut aliquid bonorum definitiones sit, at delenit utroque adversarium ius. At vocent imperdiet definitiones eum. Vulputate dissentiet eu eos, vis virtute urbanitas reprimique et, adhuc errem reprimique eos eu. Duo utinam doctus concludaturque an, ne alienum constituam per.

Rebum impedit volumus ad qui, mei epicurei reprehendunt ad. Mel magna deleniti appetere ex, ex lobortis inciderint quo, saepe vidisse impedit an vim. Legendos deseruisse usu ei, eu nominavi facilisi iudicabit eum. Mel et iracundia torquatos, iudico platonem inciderint nec an, reprimique necessitatibus duo eu.

Enim iusto nec ei, pri no erat mollis erroribus. Usu ex natum cotidieque philosophia, ius cu alienum omittam. Pro dico congue utamur et, vix duis delenit deterruisset ne, te vero atqui usu. Mucius volutpat intellegam duo ea, adhuc putent tacimates mei ex.

Ut falli impetus honestatis est, id sed decore perpetua principes. Animal electram tractatos eam at. An cum dicunt option timeam, maiorum accumsan nominavi pro ad. Mel ne sint disputationi. Cu mea tibique persequeris, an ius wisi cetero.

END SAMPLE TEXT

also we tried many cell phone textfield examples using

flutter run -d web-server --web-port $1 --web-hostname 0.0.0.0

FLUTTER DOCTOR

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.7.10, on macOS 12.5.1 21G83 darwin-x64, locale
    en-US)
[!] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for
      more details.
[!] Xcode - develop for iOS and macOS (Xcode 14.2)
    ! CocoaPods 1.8.4 out of date (1.11.0 is recommended).
        CocoaPods is used to retrieve the iOS and macOS platform side's plugin
        code that responds to your plugin usage on the Dart side.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/platform-plugins
      To upgrade see
      https://guides.cocoapods.org/using/getting-started.html#installation for
      instructions.
[✓] Chrome - develop for the web
[✓] Android Studio (version 3.5)
[✓] IntelliJ IDEA Ultimate Edition (version 2022.1.1)
[✓] VS Code (version 1.43.2)
[✓] VS Code (version 1.76.2)
[✓] VS Code (version 1.68.1)
[✓] VS Code (version 1.40.2)
[✓] Connected device (3 available)
[✓] HTTP Host Availability

! Doctor found issues in 2 categories.
hhkk commented 1 year ago

this issue can also manifest with shorter text blocks say 100-300 char's

and also when there is no induced TextField scroll, given small font and larger maxLines

darshankawar commented 1 year ago

Thanks for the report @hhkk Looks like your issue is closely related / similar to https://github.com/flutter/flutter/issues/120604 ? Can you check and confirm ?

hhkk commented 1 year ago

It is probably a related issue but not the same. that one focused on end of line tap. this issue concerns tapping almost anywhere.

So with the version here i still get the fail unfortunately :( Flutter 3.10.0-2.0.pre.30 • channel master • Built using flutter build web --release Run on pixel 7

Problem happens easily ...

Test program is below (from the dev cookbook https://docs.flutter.dev/cookbook/forms/focus

lorem ipsum test data is above in comments. Probably don't need 1500 char's of test data.

This is a blocking issue for me and others. Any help so much appreciated.

code sample ``` import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( title: 'Text Field Focus', home: MyCustomForm(), ); } } // Define a custom Form widget. class MyCustomForm extends StatefulWidget { const MyCustomForm({super.key}); @override State createState() => _MyCustomFormState(); } // Define a corresponding State class. // This class holds data related to the form. class _MyCustomFormState extends State { // Define the focus node. To manage the lifecycle, create the FocusNode in // the initState method, and clean it up in the dispose method. late FocusNode myFocusNode; @override void initState() { super.initState(); myFocusNode = FocusNode(); } @override void dispose() { // Clean up the focus node when the Form is disposed. myFocusNode.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Text Field Focus'), ), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ // The first text field is focused on as soon as the app starts. const TextField( maxLines: 5, autofocus: true, ), // The second text field is focused on when a user taps the // FloatingActionButton. TextField( focusNode: myFocusNode, ), ], ), ), floatingActionButton: FloatingActionButton( // When the button is pressed, // give focus to the text field using myFocusNode. onPressed: () => myFocusNode.requestFocus(), tooltip: 'Focus Second Text Field', child: const Icon(Icons.edit), ), // This trailing comma makes auto-formatting nicer for build methods. ); } } ```
darshankawar commented 1 year ago

@hhkk So I tried the same as you mentioned above and observed that upon trying to tap on the given text, it takes me to the end of the line as shown below:

https://user-images.githubusercontent.com/67046386/231072071-f8412464-482f-40c2-b46a-bc2ce1d05f24.MP4

I scrolled all the way up in the textfield and tried to tap, but it took me to the end of the text everytime. Also, while trying to tap in the middle of the text, instead of showing the cursor, it shows me highlighted text which I think is already reported in one of the linked / related issues.

Are you seeing the same behavior as I see from the video ? If not, a short video of the behavior would be helpful.

hhkk commented 1 year ago

Good, so you see issues as well. I will verify and get back with more test results, but on a two minute review, the issues you describe are at least similar if not overlapping to mine.

Are these issues you described something slated for fix soon? They make the text field unusable for me.

If not slated for fix soon, do you know if the issues are limited to longer text strings (eg a particular string length)?

I will get back to you with more complete test. Let me know how else I can help.

Thank you

hhkk commented 1 year ago

Further testing confirms: I see no issues separate from what you mention. (However where you show blocks for highlighted region, I show mostly underlines. If I press enough times/erratically enough, only then do I see block rather than underline. Images herein show both underline only, and block/underline together.

Do you expect these issues to be resolved any time soon? Alternative approach to use in the meantime?

If you know the issue # that you suspect replaces this one, please include here. I read several related issues but I don't think I saw quite the issue - or at least as clearly as you described it - occurring.

https://github.com/flutter/flutter/issues/120604 refers to persian text and clicking at the end. Whereas this item is for any text and clicking anywhere - perhaps requiring a multiline text of longer length such as > 100 or > 300 char's. So I"m not certain it's the same issue.

Thank you

i1 i2
hhkk commented 1 year ago

FYI - here is a list of all related issues i have found

search key: https://github.com/flutter/flutter/issues?q=is%3Aissue+tap+cursor+textfield

https://github.com/flutter/flutter/issues/124483 this

https://github.com/flutter/flutter/issues/98720 [Android] TextField cursor doesn't move to tapped position, but converts into text selection mode after selecting input mode from virtual keyboard. #98720

https://github.com/flutter/flutter/issues/100004 two exclamation points

https://github.com/flutter/flutter/issues/121164 feb 21 2023 Text field cursor position in RTL goes to the penultimate character

https://github.com/flutter/flutter/issues/122443 mar 10 2023 Failed assertion when trying to set caret position to text position that is not visible

https://github.com/flutter/flutter/issues/118566 jan 16 2023 Text field cursor position in RTL goes to the penultimate character

https://github.com/flutter/flutter/issues/114433 not 2022 TextField's cursor cannot move in the middle of the word

https://github.com/flutter/flutter/issues/120604 feb 13 TextField cursor stands in a wrong position while using persian words

https://github.com/flutter/flutter/issues/109175 aug 2022 cursor is not inserting value at the specific position where i tapped when readOnly mode is enabled in textformField

https://github.com/flutter/flutter/issues/100004 mar 2022 tap to move cursor in textfield not working on android

hhkk commented 1 year ago

As I've reviewed and thought about the above list of issues and this one, this problem is not addressed in prior issues in my opinion.

hhkk commented 1 year ago

the iphone version demonstrating this is iPhone 12 Pro Max iOS Version 16.3.1

darshankawar commented 1 year ago

Thanks for the update. Based on the report and my findings earlier, I am going ahead and keeping this issue open.

code sample used ``` import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( title: 'Text Field Focus', home: MyCustomForm(), ); } } // Define a custom Form widget. class MyCustomForm extends StatefulWidget { const MyCustomForm({super.key}); @override State createState() => _MyCustomFormState(); } // Define a corresponding State class. // This class holds data related to the form. class _MyCustomFormState extends State { // Define the focus node. To manage the lifecycle, create the FocusNode in // the initState method, and clean it up in the dispose method. late FocusNode myFocusNode; @override void initState() { super.initState(); myFocusNode = FocusNode(); } @override void dispose() { // Clean up the focus node when the Form is disposed. myFocusNode.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Text Field Focus'), ), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ // The first text field is focused on as soon as the app starts. const TextField( autofocus: true, maxLines: 5, ), // The second text field is focused on when a user taps the // FloatingActionButton. TextField( focusNode: myFocusNode, ), ], ), ), floatingActionButton: FloatingActionButton( // When the button is pressed, // give focus to the text field using myFocusNode. onPressed: () => myFocusNode.requestFocus(), tooltip: 'Focus Second Text Field', child: const Icon(Icons.edit), ), // This trailing comma makes auto-formatting nicer for build methods. ); } } ```
stable, master flutter doctor -v ``` [!] Flutter (Channel stable, 3.7.10, on macOS 12.2.1 21D62 darwin-x64, locale en-GB) • Flutter version 3.7.10 on channel stable at /Users/dhs/documents/fluttersdk/flutter ! Warning: `flutter` on your path resolves to /Users/dhs/Documents/Fluttersdk/flutter/bin/flutter, which is not inside your current Flutter SDK checkout at /Users/dhs/documents/fluttersdk/flutter. Consider adding /Users/dhs/documents/fluttersdk/flutter/bin to the front of your path. ! Warning: `dart` on your path resolves to /Users/dhs/Documents/Fluttersdk/flutter/bin/dart, which is not inside your current Flutter SDK checkout at /Users/dhs/documents/fluttersdk/flutter. Consider adding /Users/dhs/documents/fluttersdk/flutter/bin to the front of your path. • Upstream repository https://github.com/flutter/flutter.git • Framework revision 4b12645012 (6 days ago), 2023-04-03 17:46:48 -0700 • Engine revision ec975089ac • Dart version 2.19.6 • DevTools version 2.20.1 • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades. [!] Xcode - develop for iOS and macOS (Xcode 12.3) • Xcode at /Applications/Xcode.app/Contents/Developer ! Flutter recommends a minimum Xcode version of 13. Download the latest version or update via the Mac App Store. • CocoaPods version 1.11.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] VS Code (version 1.62.0) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.21.0 [✓] Connected device (5 available) • SM G975F (mobile) • RZ8M802WY0X • android-arm64 • Android 11 (API 30) • Darshan's iphone (mobile) • 21150b119064aecc249dfcfe05e259197461ce23 • ios • iOS 14.4.1 18D61 • iPhone 12 Pro Max (mobile) • A5473606-0213-4FD8-BA16-553433949729 • ios • com.apple.CoreSimulator.SimRuntime.iOS-14-3 (simulator) • macOS (desktop) • macos • darwin-x64 • Mac OS X 10.15.4 19E2269 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 98.0.4758.80 [✓] HTTP Host Availability • All required HTTP hosts are available ! Doctor found issues in 1 category. [!] Flutter (Channel master, 3.10.0-3.0.pre.56, on macOS 12.2.1 21D62 darwin-x64, locale en-GB) • Flutter version 3.10.0-3.0.pre.56 on channel master at /Users/dhs/documents/fluttersdk/flutter ! Warning: `flutter` on your path resolves to /Users/dhs/Documents/Fluttersdk/flutter/bin/flutter, which is not inside your current Flutter SDK checkout at /Users/dhs/documents/fluttersdk/flutter. Consider adding /Users/dhs/documents/fluttersdk/flutter/bin to the front of your path. ! Warning: `dart` on your path resolves to /Users/dhs/Documents/Fluttersdk/flutter/bin/dart, which is not inside your current Flutter SDK checkout at /Users/dhs/documents/fluttersdk/flutter. Consider adding /Users/dhs/documents/fluttersdk/flutter/bin to the front of your path. • Upstream repository https://github.com/flutter/flutter.git • Framework revision 8fae9618ce (84 minutes ago), 2023-04-11 23:34:11 -0400 • Engine revision 176ad4a6d8 • Dart version 3.0.0 (build 3.0.0-431.0.dev) • DevTools version 2.23.1 • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades. [!] Android toolchain - develop for Android devices (Android SDK version 30.0.3) • Android SDK at /Users/dhs/Library/Android/sdk ✗ cmdline-tools component is missing Run `path/to/sdkmanager --install "cmdline-tools;latest"` See https://developer.android.com/studio/command-line for more details. ✗ Android license status unknown. Run `flutter doctor --android-licenses` to accept the SDK licenses. See https://flutter.dev/docs/get-started/install/macos#android-setup for more details. [✓] Xcode - develop for iOS and macOS (Xcode 13.2.1) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 13C100 • CocoaPods version 1.11.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] IntelliJ IDEA Ultimate Edition (version 2021.3.2) • IntelliJ at /Applications/IntelliJ IDEA.app • Flutter plugin version 65.1.4 • Dart plugin version 213.7228 [✓] VS Code (version 1.62.0) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.29.0 [✓] Connected device (3 available) • Darshan's iphone (mobile) • 21150b119064aecc249dfcfe05e259197461ce23 • ios • iOS 15.3.1 19D52 • macOS (desktop) • macos • darwin-x64 • macOS 12.2.1 21D62 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 109.0.5414.119 [✓] Network resources • All expected network resources are available. ! Doctor found issues in 1 category. [!] Xcode - develop for iOS and macOS (Xcode 12.3) • Xcode at /Applications/Xcode.app/Contents/Developer ! Flutter recommends a minimum Xcode version of 13. Download the latest version or update via the Mac App Store. • CocoaPods version 1.11.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] VS Code (version 1.62.0) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.21.0 [✓] Connected device (5 available) • SM G975F (mobile) • RZ8M802WY0X • android-arm64 • Android 11 (API 30) • Darshan's iphone (mobile) • 21150b119064aecc249dfcfe05e259197461ce23 • ios • iOS 14.4.1 18D61 • iPhone 12 Pro Max (mobile) • A5473606-0213-4FD8-BA16-553433949729 • ios • com.apple.CoreSimulator.SimRuntime.iOS-14-3 (simulator) • macOS (desktop) • macos • darwin-x64 • Mac OS X 10.15.4 19E2269 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 98.0.4758.80 [✓] HTTP Host Availability • All required HTTP hosts are available ! Doctor found issues in 1 category. ```
hhkk commented 1 year ago

OK thanks.

clicking in various places around the text field may reveal other oddities, but probably all included in existing items.

this is a key issue IMO - can't edit means can't use :)

yjbanov commented 1 year ago

This sounds similar to https://github.com/flutter/flutter/issues/122394. @hhkk do you think it would be reasonable to merge this issue into that one?

hhkk commented 1 year ago

HI @yjbanov - I don't see reference to 1) tapping the pointer 2) on a cell phone and 3) having the cursor end up in a seemingly unrelated place (the bottom). So I do not think they are the same issue. Let me know if I am missing something. Thanks

bleroux commented 1 year ago

FYI, I have a fix for this issue on Android. I will post more details tomorrow (it is late here) and also tried a similar fix on iOS.

hhkk commented 1 year ago

FYI, I have a fix for this issue on Android. I will post more details tomorrow (it is late here) and also tried a similar fix on iOS.

Sweet! Please test with clicking around various places in a longish (eg ~1500 char lorem ipsum) text block and see if you see any other similar anomalies in terms if tap location vs resulting cursor location. (I'm not convinced that it's always "wrongly going to the end of the text block".)

Thank you Henry

bleroux commented 1 year ago

@hhkk Thanks for the detailed report. @darshankawar Thanks for verifying this.

I filed https://github.com/flutter/engine/pull/41202 with a simplified code sample. From my testing, the fix is ok on Android/Chrome, but I have to find why it partially works on iOS/Safari.

I'm not convinced that it's always "wrongly going to the end of the text block".)

From my investigation, the cursor does not always jump to the end. It seems to jump to a place which was visible before (for instance, if we scroll and then tap, the cursor will jump to the text which was at the tap position before the scroll). As described in the PR, it is because both Flutter and the