首页 > 解决方案 > 即使在使用键后 Flutter TabbarView 也不会保持滚动位置

问题描述

问题

在 Imgur 上观看视频:Imgur

您也可以在这里观看视频:Cloudinary

正如您在视频中看到的那样,滚动位置没有被保持。看起来页面正在一起滚动。

基本应用结构

我正在使用带有 SliverAppBar 和 TabBarView 的 NestedScrollView 来实现简单的滚动效果。标签栏显示不同的页面,这些页面反过来使用Provider进行状态管理,我正在返回 CustomScrollView。

主页 :

    DefaultTabController(
          length: 3,
          child: Scaffold(
            body: NestedScrollView(
              headerSliverBuilder: (context, innerBoxIsScrolled) => [
                SliverAppBar(
                  floating: true,
                  pinned: true,
                  snap: true,
                  forceElevated: true,
                  title: Text('Title'),
                  bottom: TabBar(
                    tabs: [
                      Tab(
                        icon: Icon(Icons.extension_rounded),
                      ),
                      Tab(
                        icon: Icon(Icons.folder_rounded),
                      ),
                      Tab(
                        icon: Icon(Icons.settings_rounded),
                      )
                    ],
                  ),
                ),
              ],
              body: TabBarView(
                children: [
                  PageStorage(
                    bucket: _bucket,
                    child: ExtensionsView(
                      key: PageStorageKey('extensions_view'),
                    ),
                  ),
                  PageStorage(
                    bucket: _bucket,
                    child: VideosView(
                      key: PageStorageKey('videos_view'),
                    ),
                  ),
                  PageStorage(
                    bucket: _bucket,
                    child: SettingsView(
                      key: PageStorageKey('settings'),
                    ),
                  ),
                ],
              ),
            ),
          ),
        );

标签栏查看页面

return ViewModelBuilder<ExtensionsViewModel>.reactive(
      viewModelBuilder: () => ExtensionsViewModel(),
      onModelReady: (model) => model.fetchData(),
      builder: (context, model, child) => CustomScrollView(
        slivers: [
          if (model.isBusy)
            SliverList(
              delegate: SliverChildBuilderDelegate(
                (context, index) {
                  return FilledVideoCard.loading(
                    borderRadius: BorderRadius.zero,
                  );
                },
                childCount: 3,
              ),
            )
          else
            SliverList(
              delegate: SliverChildBuilderDelegate(
                (context, index) {
                  final data = model.extensions[index];
                  return FilledVideoCard(
                    key: ObjectKey(data),
                    title: data.title,
                    price: data.price,
                    date: data.date,
                    image: data.image,
                    tags: [data.version, ...data.tags],
                    borderRadius: BorderRadius.zero,
                    onTap: () {},
                  );
                },
                childCount: model.extensions.length,
              ),
            ),
        ],
      ),
    )

笔记 :

  1. 在所有 tabbarview 页面中,我使用AutomaticKeepAliveClientMixin来确保该页面只创建一次。
  2. 在所有 tabbarview 页面中,我都返回了 CutomScrollView。

到目前为止我尝试过的

我尝试了不同的方法来保持 tabbarview 内的滚动位置。

  1. PageStorageKey('page')
  2. PageStorageKey('page')PageStorage()
  3. ScrollController使用 CustomScrollView
  4. 通过小部件构造函数传递PageStorageKey给 CustomScrollView

我尝试了以上所有方法来保留滚动位置,但正如您在视频中看到的那样,滚动位置没有保持不变。只有直接将 CustomScrollView 添加到 TabbarView 时,滚动位置才会被保留。但在我的情况下,CustomScrollView 嵌套在一个有状态的小部件中,该小部件使用 Stacked(提供)进行状态管理和未维护的滚动位置。

但是,如果我在每个页面中为 CustomScrollView 分配一个控制器,那么我就会失去 SliverAppBar 的滚动动画。

那么有什么方法可以保持嵌套滚动视图中的状态吗?

标签: flutterflutter-layoutflutter-sliverappbar

解决方案


推荐阅读