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

PageStorageKey with TabBarView causes PageController and TabController to get out of sync #10969

Open
collinjackson opened this issue Jun 26, 2017 · 14 comments
Labels
f: material design flutter/packages/flutter/material repository. found in release: 3.7 Found to occur in 3.7 found in release: 3.9 Found to occur in 3.9 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-design Owned by Design Languages team triaged-design Triaged by Design Languages team

Comments

@collinjackson
Copy link
Contributor

collinjackson commented Jun 26, 2017

TabBarView uses the index of its tabController to set the initialPage of its PageController. However, the PageController can later determine a different _pageToUseOnStartup using its PageStorage. There's no mechanism currently in place for the TabBarView to notify its tabController that the PageController has decided to start up on a different page.

The result is that you can have a TabBar that doesn't match its TabBarView, even though they share a common TabController. This seems like a bug.

untitled 1

import 'dart:async';
import 'package:flutter/material.dart';

void main() {
  runApp(new MaterialApp(
    home: new MyHomePage(),
  ));
}

class MyHomePage extends StatefulWidget {
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  PageController _controller = new PageController();

  Widget build(BuildContext context) {
    return new Scaffold(
      body: new PageView(
        controller: _controller,
        children: <Widget>[
          new DefaultTabController(
            length: 2,
            child: new Column(
              children: <Widget>[
                new Container(
                  height: 200.0,
                  child: new Center(
                    child: new Text('Swipe here'),
                  ),
                ),
                new Container(
                  height: 100.0,
                  color: Colors.grey,
                  child: new TabBar(
                    key: new PageStorageKey<Type>(TabBar),
                    tabs: <Widget>[
                      new Tab(text: 'Green'),
                      new Tab(text: 'Red'),
                    ],
                  ),
                ),
                new Expanded(
                  child: new TabBarView(
                    key: new PageStorageKey<Type>(TabBarView),
                    children: [
                      new Container(color: Colors.green),
                      new Container(color: Colors.red),
                    ],
                  ),
                ),
              ],
            ),
          ),
          new Center(
            child: new Text('Ok now swipe back'),
          ),
        ],
      ),
    );
  }
}

Flutter Doctor

[✓] Flutter (on Mac OS X 10.12.4 16E195, locale en-US, channel master)
    • Flutter at /Users/jackson/git/flutter
    • Framework revision c5999c74c0 (2 hours ago), 2017-06-26 12:47:43 +0200
    • Engine revision 8a2d337446
    • Tools Dart version 1.24.0

[✓] Android toolchain - develop for Android devices (Android SDK 25.0.3)
    • Android SDK at /Users/jackson/Library/Android/sdk/
    • Platform android-25, build-tools 25.0.3
    • ANDROID_HOME = /Users/jackson/Library/Android/sdk/
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_112-release-b06)

[✓] iOS toolchain - develop for iOS devices (Xcode 8.3.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 8.3.3, Build version 8E3004b, 
    • ios-deploy 1.9.1
    • CocoaPods version 1.2.1

[✓] Android Studio (version 2.3)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Gradle version 3.2
    • Java version OpenJDK Runtime Environment (build 1.8.0_112-release-b06)

[✓] IntelliJ IDEA Community Edition (version 2017.1.3)
    • Flutter plugin version 14.0
    • Dart plugin version 171.4424.63

[✓] Connected devices
    • iPhone 7 Plus • F8A917C4-9848-49C2-8F0D-664B49E0B635 • ios • iOS 10.3 (simulator)
@eseidelGoogle
Copy link
Contributor

@HansMuller would know.

@eseidelGoogle eseidelGoogle added framework flutter/packages/flutter repository. See also f: labels. f: material design flutter/packages/flutter/material repository. labels Jun 26, 2017
@collinjackson collinjackson changed the title TabBarView's PageController and TabController can get out of sync with PageStorageKey PageStorageKey with TabBarView causes PageController and TabController can get out of sync Jun 26, 2017
@collinjackson collinjackson changed the title PageStorageKey with TabBarView causes PageController and TabController can get out of sync PageStorageKey with TabBarView causes PageController and TabController to get out of sync Jun 26, 2017
@collinjackson
Copy link
Contributor Author

Here is a workaround for anyone who is running into this limitation of TabBarView.

@Hixie
Copy link
Contributor

Hixie commented Jun 26, 2017

The fix here should be to make sure there's only one source of truth on the currently selected tab, so that however it gets changed, every client changes automatically to match.

@Hixie Hixie added this to the 5: Make Hixie proud milestone Jun 27, 2017
@zoeyfan
Copy link

zoeyfan commented Jan 3, 2020

I noticed this bug from 2017. Are we still planning to work on it?

@Hixie Hixie modified the milestones: Stretch Goals, Goals Jan 3, 2020
@akshg05
Copy link

akshg05 commented May 5, 2020

Please do! This is important. I wonder why Flutter is building beautiful clocks worldwide while simple Material App components are manifested with troublesome bugs.

@kf6gpe kf6gpe added the P2 Important issues not at the top of the work list label May 29, 2020
@kf6gpe kf6gpe removed this from the Goals milestone Jun 2, 2020
@Hixie Hixie removed this from the Goals milestone Jun 2, 2020
@markusaksli-nc
Copy link
Member

Reproducible on latest master 1.20.0-8.0.pre.125

flutter doctor -v
[√] Flutter (Channel master, 1.20.0-8.0.pre.125, on Microsoft Windows [Version 10.0.18362.900], locale et-EE)
   • Flutter version 1.20.0-8.0.pre.125 at C:\Development\flutter_master
   • Framework revision 9c4a5ef1ed (13 hours ago), 2020-07-15 21:41:27 +0100
   • Engine revision 774ae0313d
   • Dart version 2.9.0 (build 2.9.0-21.0.dev 89fe12b12a)


[√] Android toolchain - develop for Android devices (Android SDK version 30.0.0)
   • Android SDK at C:\Users\Isa\AppData\Local\Android\sdk
   • Platform android-30, build-tools 30.0.0
   • Java binary at: C:\Users\Isa\AppData\Local\JetBrains\Toolbox\apps\AndroidStudio\ch-0\193.6626763\jre\bin\java
   • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)
   • All Android licenses accepted.

[X] Chrome - develop for the web (Cannot find Chrome executable at .\Google\Chrome\Application\chrome.exe)
   ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.

[√] Android Studio (version 4.0)
   • Android Studio at C:\Users\Isa\AppData\Local\JetBrains\Toolbox\apps\AndroidStudio\ch-0\193.6626763
   • Flutter plugin version 47.1.2
   • Dart plugin version 193.7361
   • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)

[√] Connected device (3 available)
   • SM G950F (mobile)       • ce12171c51cc001c03 • android-arm64  • Android 9 (API 28)
   • sdk gphone x86 (mobile) • emulator-5554      • android-x86    • Android 11 (API 30) (emulator)
   • Web Server (web)        • web-server         • web-javascript • Flutter Tools

! Doctor found issues in 1 category.

@markusaksli-nc markusaksli-nc added found in release: 1.20 Found to occur in 1.20 has reproducible steps The issue has been confirmed reproducible and is ready to work on labels Jul 16, 2020
sterlp added a commit to sterlp/daily-challenge that referenced this issue Aug 2, 2020
currently the PageStorageKey doesn’t work in Flutter -.-
flutter/flutter#10969
@Hixie Hixie removed this from the None. milestone Aug 17, 2020
@YeungKC
Copy link
Member

YeungKC commented Oct 31, 2020

It may be difficult to get the TabBar to support PageStorageKey, because the TabController actually affects two widgets, Tab and TabView, and the TabView contains the PageView, which already supports PageStorageKey, It's going to get messy.

So I suggest, if you want the DefaultTabController to support PageStorageKey, you can achieve the same behaviour.

I don't know what you think?

example code:

              DefaultTabController(
                length: 2,
                key: const PageStorageKey<Type>(DefaultTabController),
                child: Column(
                  children: const <Widget>[
                    TabBar(
                      tabs: <Widget>[
                        Tab(text: 'A'),
                        Tab(text: 'B'),
                      ],
                    ),
                    Expanded(
                      child: TabBarView(
                        children: <Widget>[
                          Text('C'),
                          Text('D'),
                        ],
                      ),
                    ),
                  ],
                ),
              ),
              

Actually I've already done the work on the DefaultTabController support for PageStorageKey, so if you approve such a solution I'll PR it right away.

cc @collinjackson @goderbauer @a14n

@goderbauer
Copy link
Member

I wonder if we should just set keepPage of the PageController instantiated by the TabBarView to false to always let the initialPage of it be determined by the TabController. You'd then have to make the TabController be owned by something that's long-lived enough to keep its state. In the example given in the first post this would mean moving the DefaultTabController above the PageView. If you need multiple TabControllers, you'd have to manage those manually (instead of using the DefaultTabController) and pass them to the TabBar and TabBarView that need them.

Doing that would be preferred over integrating PageStorage into the DefaultTabController because PageStorage is not compatible with state restoration.

@YeungKC
Copy link
Member

YeungKC commented Dec 9, 2020

@goderbauer Thank you very much and I will try to use the solution you provided.

@TechAurelian2
Copy link

Here is a workaround for anyone who is running into this limitation of TabBarView.

@collinjackson Thank you for the workaround. It works fine. However, it cannot be used in a StatelessWidget because it requires a TabController initialized in initState.

I think that something like #69702 should be implemented by default.

@danagbemava-nc
Copy link
Member

Issue is reproducible on the latest versions of flutter

recordings
IMG_4422.MP4
updated sample
import 'package:flutter/material.dart';

void main() {
  runApp(
    const MaterialApp(
      home: MyHomePage(),
    ),
  );
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  final PageController _controller = PageController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageView(
        controller: _controller,
        children: <Widget>[
          DefaultTabController(
            length: 2,
            child: Column(
              children: <Widget>[
                const SizedBox(
                  height: 200.0,
                  child: Center(
                    child: Text('Swipe here'),
                  ),
                ),
                Container(
                  height: 100.0,
                  color: Colors.grey,
                  child: const TabBar(
                    key: PageStorageKey<Type>(TabBar),
                    tabs: <Widget>[
                      Tab(text: 'Green'),
                      Tab(text: 'Red'),
                    ],
                  ),
                ),
                Expanded(
                  child: TabBarView(
                    key: const PageStorageKey<Type>(TabBarView),
                    children: [
                      Container(color: Colors.green),
                      Container(color: Colors.red),
                    ],
                  ),
                ),
              ],
            ),
          ),
          const Center(
            child: Text('Ok now swipe back'),
          ),
        ],
      ),
    );
  }
}
flutter doctor -v
[✓] Flutter (Channel stable, 3.7.6, on macOS 13.2.1 22D68 darwin-arm64, locale en-GB)
    • Flutter version 3.7.6 on channel stable at /Users/nexus/dev/sdks/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 12cb4eb7a0 (6 days ago), 2023-03-01 10:29:26 -0800
    • Engine revision ada363ee93
    • Dart version 2.19.3
    • DevTools version 2.20.1

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    • Android SDK at /Users/nexus/Library/Android/sdk
    • Platform android-33, build-tools 33.0.0
    • Java binary at: /Users/nexus/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/221.6008.13.2211.9477386/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.2)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14C18
    • 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.1)
    • Android Studio at /Users/nexus/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/221.6008.13.2211.9477386/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.3.2)
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin version 72.1.4
    • Dart plugin version 223.8617.8

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

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-arm64   • macOS 13.2.1 22D68 darwin-arm64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 110.0.5481.177
    ! Error: Nexus is locked. To use Nexus with Xcode, unlock it. (code 4)

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

• No issues found!
[!] Flutter (Channel master, 3.9.0-1.0.pre.72, on macOS 13.2.1 22D68 darwin-arm64, locale en-GB)
    • Flutter version 3.9.0-1.0.pre.72 on channel master at /Users/nexus/dev/sdks/flutters
    ! Warning: `flutter` on your path resolves to /Users/nexus/dev/sdks/flutter/bin/flutter, which is not inside your current Flutter SDK checkout at /Users/nexus/dev/sdks/flutters. Consider adding /Users/nexus/dev/sdks/flutters/bin to the front of your path.
    ! Warning: `dart` on your path resolves to /Users/nexus/dev/sdks/flutter/bin/dart, which is not inside your current Flutter SDK checkout at /Users/nexus/dev/sdks/flutters. Consider adding /Users/nexus/dev/sdks/flutters/bin to the front of your path.
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 8557ffa024 (8 hours ago), 2023-03-06 22:38:59 -0500
    • Engine revision e2bd89f97e
    • Dart version 3.0.0 (build 3.0.0-290.0.dev)
    • DevTools version 2.22.2
    • 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 33.0.0)
    • Android SDK at /Users/nexus/Library/Android/sdk
    • Platform android-33, build-tools 33.0.0
    • Java binary at: /Users/nexus/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/221.6008.13.2211.9477386/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.2)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14C18
    • 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.1)
    • Android Studio at /Users/nexus/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/221.6008.13.2211.9477386/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.3.2)
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin version 72.1.4
    • Dart plugin version 223.8617.8

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

[✓] Connected device (3 available)
    • Nexus (mobile)  • 00008020-001875E83A38002E • ios            • iOS 16.3.1 20D67
    • macOS (desktop) • macos                     • darwin-arm64   • macOS 13.2.1 22D68 darwin-arm64
    • Chrome (web)    • chrome                    • web-javascript • Google Chrome 110.0.5481.177
    ! Error: Nexus is busy: Waiting to connect and unlock the device. Xcode will continue when Nexus is finished. (code -10)

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

! Doctor found issues in 1 category.

@danagbemava-nc danagbemava-nc added found in release: 3.7 Found to occur in 3.7 found in release: 3.9 Found to occur in 3.9 and removed found in release: 1.20 Found to occur in 1.20 labels Mar 7, 2023
@flutter-triage-bot flutter-triage-bot bot added multiteam-retriage-candidate team-design Owned by Design Languages team triaged-design Triaged by Design Languages team labels Jul 8, 2023
@flutter-triage-bot flutter-triage-bot bot removed the triaged-design Triaged by Design Languages team label Jul 25, 2023
@flutter-triage-bot
Copy link

This issue is assigned to @YeungKC but has had no recent status updates. Please consider unassigning this issue if it is not going to be addressed in the near future. This allows people to have a clearer picture of what work is actually planned. Thanks!

@YeungKC YeungKC removed their assignment Jul 25, 2023
@goderbauer goderbauer self-assigned this Jul 28, 2023
@HansMuller HansMuller added the triaged-design Triaged by Design Languages team label Jul 28, 2023
@flutter-triage-bot flutter-triage-bot bot added the Bot is counting down the days until it unassigns the issue label Dec 15, 2023
@flutter-triage-bot
Copy link

This issue is assigned to @goderbauer but has had no recent status updates. Please consider unassigning this issue if it is not going to be addressed in the near future. This allows people to have a clearer picture of what work is actually planned. Thanks!

@flutter-triage-bot flutter-triage-bot bot removed the triaged-design Triaged by Design Languages team label Feb 17, 2024
@flutter-triage-bot
Copy link

This issue was assigned to @goderbauer but has had no status updates in a long time. To remove any ambiguity about whether the issue is being worked on, the assignee was removed.

@flutter-triage-bot flutter-triage-bot bot removed the Bot is counting down the days until it unassigns the issue label Feb 17, 2024
@HansMuller HansMuller added P3 Issues that are less important to the Flutter project triaged-design Triaged by Design Languages team labels Feb 28, 2024
@flutter-triage-bot flutter-triage-bot bot removed the P3 Issues that are less important to the Flutter project label Feb 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
f: material design flutter/packages/flutter/material repository. found in release: 3.7 Found to occur in 3.7 found in release: 3.9 Found to occur in 3.9 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-design Owned by Design Languages team triaged-design Triaged by Design Languages team
Projects
None yet
Development

Successfully merging a pull request may close this issue.