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

Unexpected behavior of SelectableText when specifying PageStorageKey on parent List #125298

Open
2 tasks done
MaximMonakhov opened this issue Apr 21, 2023 · 4 comments
Open
2 tasks done
Labels
f: scrolling Viewports, list views, slivers, etc. f: selection SelectableRegion, SelectionArea, SelectionContainer, Selectable, and related APIs found in release: 3.7 Found to occur in 3.7 found in release: 3.10 Found to occur in 3.10 framework flutter/packages/flutter repository. See also f: labels. has reproducible steps The issue has been confirmed reproducible and is ready to work on P2 Important issues not at the top of the work list team-framework Owned by Framework team triaged-framework Triaged by Framework team

Comments

@MaximMonakhov
Copy link

Is there an existing issue for this?

Steps to reproduce

  1. Adding a PageStorageKey to a ListView that contains SelectableText.
  2. Scroll down and then quickly up.

Expected results

SelectableText looks like regular, static text. Without any scrolling experience.

Actual results

This caused strange behavior for SelectableText inside the list. It feels like SelectableText wants to save/receive its position too. Because of this, the text jumps around (сalls animateTo() as Scrollable, i guess).

Code sample

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(
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  const Home({super.key});

  @override
  Widget build(BuildContext context) => Scaffold(
        body: ListView(
          key: const PageStorageKey("key"), // works fine without key
          children: [
            ...List.generate(10, (index) => const SelectableText("Selectable", style: TextStyle(fontSize: 20))),
            ...List.generate(200, (index) => const Text("Text")),
          ],
        ),
      );
}

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]
ezgif com-video-to-gif

Logs

No response

Flutter Doctor output

Doctor output
[√] Flutter (Channel stable, 3.7.8, on Microsoft Windows [Version 10.0.19041.450], locale ru-RU)
    • Flutter version 3.7.8 on channel stable at C:\Users\monakhov\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 90c64ed42b (4 weeks ago), 2023-03-21 11:27:08 -0500
    • Engine revision 9aa7816315
    • Dart version 2.19.5
    • DevTools version 2.20.1

[X] Windows Version (Unable to confirm if installed Windows version is 10 or greater)

[√] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    • Android SDK at C:\Users\monakhov\AppData\Local\Android\Sdk
    • Platform android-33, build-tools 33.0.0
    • ANDROID_HOME = C:\Users\monakhov\AppData\Local\Android\Sdk
    • Java binary at: C:\Users\monakhov\AppData\Local\JetBrains\Toolbox\apps\AndroidStudio\ch-0\212.5712.43.2112.8609683\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 11.0.12+7-b1504.28-7817840)
    • All Android licenses accepted.

[√] Android Studio (version 2021.2)
    • Flutter plugin version 65.2.1
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.12+7-b1504.28-7817840)

[√] VS Code (version 1.77.3)
    • Flutter extension version 3.28.0

[√] Connected device (3 available)
    • M2101K9AG (mobile) • d8ad86e0 • android-arm64  • Android 13 (API 33)
    • Windows (desktop)  • windows  • windows-x64    • Microsoft Windows [Version 10.0.19041.450]
    • Chrome (web)       • chrome   • web-javascript • Google Chrome 112.0.5615.122

[√] HTTP Host Availability
    • All required HTTP hosts are available
@MaximMonakhov
Copy link
Author

I created a question on StackOverflow, but didn't get an answer. In any case, it looks buggy. I hope for help, because the UI looks weird with this behavior.

@huycozy huycozy added the in triage Presently being triaged by the triage team label Apr 24, 2023
@huycozy
Copy link
Member

huycozy commented Apr 24, 2023

Thanks for filing the issue @MaximMonakhov! This issue is reproducible on the latest stable and master channels with provided sample code.

(*) The issue only happens with SelectableText in the list. When the ListView only contains SelectableText as children (without any Text child) and do scroll the list, there is exception log from the output console:

Exception logs - in case (*)
Error: This widget has been unmounted, so the State no longer has a context (and should be considered defunct).
Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 288:49  throw_
packages/flutter/src/widgets/framework.dart 951:9                             <fn>
packages/flutter/src/widgets/framework.dart 956:14                            get context
packages/flutter/src/widgets/scrollable.dart 537:38                           get storageContext
packages/flutter/src/widgets/scroll_position.dart 244:77                      get devicePixelRatio
packages/flutter/src/widgets/scroll_physics.dart 435:39                       toleranceFor
packages/flutter/src/widgets/scroll_physics.dart 434:20                       toleranceFor
packages/flutter/src/widgets/scroll_physics.dart 434:20                       toleranceFor
packages/flutter/src/widgets/scroll_physics.dart 434:20                       toleranceFor
packages/flutter/src/widgets/scroll_physics.dart 748:33                       createBallisticSimulation
packages/flutter/src/widgets/scroll_position_with_single_context.dart 142:44  goBallistic
packages/flutter/src/widgets/scroll_activity.dart 572:14                      [_end]
dart-sdk/lib/async/zone.dart 1655:54                                          run
dart-sdk/lib/async/future_impl.dart 190:18                                    handleWhenComplete
dart-sdk/lib/async/future_impl.dart 754:38                                    handleWhenCompleteCallback
dart-sdk/lib/async/future_impl.dart 810:11                                    _propagateToListeners
dart-sdk/lib/async/future_impl.dart 584:5                                     [_completeWithValue]
dart-sdk/lib/async/future_impl.dart 657:7                                     callback
dart-sdk/lib/async/schedule_microtask.dart 40:11                              _microtaskLoop
dart-sdk/lib/async/schedule_microtask.dart 49:5                               _startMicrotaskLoop
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 177:15           <fn>
Error: This widget has been unmounted, so the State no longer has a context (and should be considered defunct).
Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 288:49  throw_
packages/flutter/src/widgets/framework.dart 951:9                             <fn>
packages/flutter/src/widgets/framework.dart 956:14                            get context
packages/flutter/src/widgets/scrollable.dart 537:38                           get storageContext
packages/flutter/src/widgets/scroll_position.dart 244:77                      get devicePixelRatio
packages/flutter/src/widgets/scroll_physics.dart 435:39                       toleranceFor
packages/flutter/src/widgets/scroll_physics.dart 434:20                       toleranceFor
packages/flutter/src/widgets/scroll_physics.dart 434:20                       toleranceFor
packages/flutter/src/widgets/scroll_physics.dart 434:20                       toleranceFor
packages/flutter/src/widgets/scroll_physics.dart 748:33                       createBallisticSimulation
packages/flutter/src/widgets/scroll_position_with_single_context.dart 142:44  goBallistic
packages/flutter/src/widgets/scroll_activity.dart 572:14                      [_end]
dart-sdk/lib/async/zone.dart 1655:54                                          run
dart-sdk/lib/async/future_impl.dart 190:18                                    handleWhenComplete
dart-sdk/lib/async/future_impl.dart 754:38                                    handleWhenCompleteCallback
dart-sdk/lib/async/future_impl.dart 810:11                                    _propagateToListeners
dart-sdk/lib/async/future_impl.dart 584:5                                     [_completeWithValue]
dart-sdk/lib/async/future_impl.dart 657:7                                     callback
dart-sdk/lib/async/schedule_microtask.dart 40:11                              _microtaskLoop
dart-sdk/lib/async/schedule_microtask.dart 49:5                               _startMicrotaskLoop
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 177:15           <fn>
Sample code - in case (*)
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(
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  const Home({super.key});

  @override
  Widget build(BuildContext context) => Scaffold(
    body: ListView(
      key: const PageStorageKey("key"), // works fine without key
      shrinkWrap: true,
      children: [
        ...List.generate(100, (index) => const SelectableText("Selectable", style: TextStyle(fontSize: 20))),
        // ...List.generate(100, (index) => const Text("Text")),
      ],
    ),
  );
}
flutter doctor -v (stable and master)
[✓] Flutter (Channel stable, 3.7.12, on macOS 13.0.1 22A400 darwin-x64, locale en-VN)
    • Flutter version 3.7.12 on channel stable at /Users/huynq/Documents/GitHub/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 4d9e56e694 (2 days ago), 2023-04-17 21:47:46 -0400
    • Engine revision 1a65d409c7
    • Dart version 2.19.6
    • DevTools version 2.20.1

[✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0)
    • Android SDK at /Users/huynq/Library/Android/sdk
    • Platform android-33, build-tools 32.0.0
    • ANDROID_HOME = /Users/huynq/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14E222b
    • CocoaPods version 1.11.3

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

[✓] Android Studio (version 2022.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)

[✓] IntelliJ IDEA Community Edition (version 2022.1.1)
    • IntelliJ at /Users/huynq/Library/Application Support/JetBrains/Toolbox/apps/IDEA-C/ch-0/221.5591.52/IntelliJ IDEA CE.app
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart

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

[✓] Connected device (3 available)
    • SM T225 (mobile) • R9JT3004VRJ • android-arm64  • Android 13 (API 33)
    • macOS (desktop)  • macos       • darwin-x64     • macOS 13.0.1 22A400 darwin-x64
    • Chrome (web)     • chrome      • web-javascript • Google Chrome 112.0.5615.137

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!
[!] Flutter (Channel master, 3.10.0-12.0.pre.29, on macOS 13.0.1 22A400 darwin-x64, locale en-VN)
    • Flutter version 3.10.0-12.0.pre.29 on channel master at /Users/huynq/Documents/GitHub/flutter_master
    ! Warning: `flutter` on your path resolves to /Users/huynq/Documents/GitHub/flutter/bin/flutter, which is not inside your current Flutter SDK checkout at /Users/huynq/Documents/GitHub/flutter_master. Consider adding /Users/huynq/Documents/GitHub/flutter_master/bin to the front of your path.
    ! Warning: `dart` on your path resolves to /Users/huynq/Documents/GitHub/flutter/bin/dart, which is not inside your current Flutter SDK checkout at /Users/huynq/Documents/GitHub/flutter_master. Consider adding /Users/huynq/Documents/GitHub/flutter_master/bin to the front of your path.
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 60077ff979 (16 hours ago), 2023-04-23 07:09:16 -0400
    • Engine revision fcf46af2d3
    • Dart version 3.1.0 (build 3.1.0-35.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 32.0.0)
    • Android SDK at /Users/huynq/Library/Android/sdk
    • Platform android-33, build-tools 32.0.0
    • ANDROID_HOME = /Users/huynq/Library/Android/sdk
    • Java binary at: /Applications/Android Studio Flamingo.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14E222b
    • CocoaPods version 1.11.3

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

[✓] Android Studio (version 2022.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)

[✓] Android Studio (version 2022.2)
    • Android Studio at /Applications/Android Studio Flamingo.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)

[✓] IntelliJ IDEA Community Edition (version 2022.1.1)
    • IntelliJ at /Users/huynq/Library/Application Support/JetBrains/Toolbox/apps/IDEA-C/ch-0/221.5591.52/IntelliJ IDEA CE.app
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart

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

[✓] Connected device (3 available)
    • SM T225 (mobile) • R9JT3004VRJ • android-arm64  • Android 13 (API 33)
    • macOS (desktop)  • macos       • darwin-x64     • macOS 13.0.1 22A400 darwin-x64
    • Chrome (web)     • chrome      • web-javascript • Google Chrome 112.0.5615.137

[✓] Network resources
    • All expected network resources are available.

! Doctor found issues in 1 category.

@huycozy huycozy added framework flutter/packages/flutter repository. See also f: labels. f: scrolling Viewports, list views, slivers, etc. has reproducible steps The issue has been confirmed reproducible and is ready to work on f: selection SelectableRegion, SelectionArea, SelectionContainer, Selectable, and related APIs found in release: 3.7 Found to occur in 3.7 found in release: 3.10 Found to occur in 3.10 and removed in triage Presently being triaged by the triage team labels Apr 24, 2023
@MaximMonakhov
Copy link
Author

The case you described and the fact that it throws an exception led me to try using another widget instead of ListView, which can save its state using PageStorage.

If you replace ListView with ExpansionTile, the following error occurs:

Exception when using ExpansionTile

exception

════════ Exception caught by widgets library ═══════════
The following _CastError was thrown building _FocusMarker: type 'bool' is not a subtype of type 'double?' in type cast

The relevant error-causing widget was SelectableText main.dart:30
When the exception was thrown, this was the stack
#0      ScrollPosition.restoreScrollOffset scroll_position.dart:427
#1      new ScrollPosition scroll_position.dart:109
#2      new ScrollPositionWithSingleContext (package:flutter/src/widgets/scroll_position_with_single_context.dart) scroll_position_with_single_context.dart:1
#3      ScrollController.createScrollPosition scroll_controller.dart:235
#4      ScrollableState._updatePosition scrollable.dart:486
#5      ScrollableState.didChangeDependencies scrollable.dart:520
#6      StatefulElement._firstBuild framework.dart:5119
#7      ComponentElement.mount
Sample code when using ExpansionTile
class Home2 extends StatelessWidget {
  const Home2({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.only(top: 100),
        child: ExpansionTile(
          key: const PageStorageKey("key"),
          title: Text("Title"),
          children: [
            const SelectableText("Selectable"),
          ],
        ),
      ),
    );
  }
}

Accordingly SelectableText as a Scrollable wants to restore its position from PageStorage, but "isExpanded" state from ExpansionTile is already written there and we get an error.
The same thing is with ListView. SelectableText wants to restore its position, but the ListView position is already written inside PageStorage. But because they are both doubles, it doesn't cause an exception. And SelectableText starts to build with the wrong position and jumps because of it (animates to initial position from wrong ListView offset).

I found a similar issue: #62332, but with TextField. As described here #62332 (comment), the problem is due to mutual influence. The suggested solution is to specify PageStorageKey in children. And as a temporary solution it works. But it shouldn't work like that in fact.

@goderbauer goderbauer added the P2 Important issues not at the top of the work list label Apr 25, 2023
@flutter-triage-bot flutter-triage-bot bot added team-framework Owned by Framework team triaged-framework Triaged by Framework team labels Jul 8, 2023
@meowofficial
Copy link

Still reproducible on 3.13 stable and 3.14 master

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
f: scrolling Viewports, list views, slivers, etc. f: selection SelectableRegion, SelectionArea, SelectionContainer, Selectable, and related APIs found in release: 3.7 Found to occur in 3.7 found in release: 3.10 Found to occur in 3.10 framework flutter/packages/flutter repository. See also f: labels. has reproducible steps The issue has been confirmed reproducible and is ready to work on P2 Important issues not at the top of the work list team-framework Owned by Framework team triaged-framework Triaged by Framework team
Projects
None yet
Development

No branches or pull requests

4 participants