Flutter 解决NestedScrollView与TabBar双列表滚动位置同步问题



前言

最近写flutter项目,遇到NestedScrollView与TabBar双列表滚动位置同步问题,下面是解决方案,希望帮助到大家。


一、需要实现的效果如下

1、UI图:
请添加图片描述
需要实现的效果是,左边滑动的时候,右边的列表不要随左边滑动。右边滑动的时候,左边也不要滑动。

二、flutter实现代码如下:

1、用flutter原生的NestedScrollView是有问题的
2、使用第三方库解决这个问题extended_nested_scroll_view: ^6.2.1
3、完整的代码如下:

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

void main() {
  runApp(const MyBitApp());
}

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

  // This widget is the root of your application.
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: MyApp(),
    );
  }
}

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'NestedScrollView Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

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

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  late TabController _tabController;
  late List<ScrollController> _scrollControllers;
  late ScrollController nestedScrollController;

  
  void initState() {
    super.initState();
    _tabController = TabController(length: 2, vsync: this);
    _scrollControllers = [
      ScrollController(),
      ScrollController(),
    ];
    nestedScrollController = ScrollController();
  }

  
  void dispose() {
    _tabController.dispose();
    for (var controller in _scrollControllers) {
      controller.dispose();
    }
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    // var tabBarHeight = primaryTabBar.preferredSize.height;
    double statusBarHeight = MediaQuery.of(context).padding.top;
    var pinnedHeaderHeight = statusBarHeight + kToolbarHeight;
    return Scaffold(
      body: DefaultTabController(
        length: 2,
        child: ExtendedNestedScrollView(
          onlyOneScrollInBody: true,
          pinnedHeaderSliverHeightBuilder: () => pinnedHeaderHeight,
          headerSliverBuilder: (context, innerBoxIsScrolled) {
            return [
              SliverAppBar(
                title: Text('NestedScrollView Demo'),
                pinned: true,
                floating: true,
                expandedHeight: 200,
                stretch: true,
                elevation: 0,
                stretchTriggerOffset: 100,
                bottom: TabBar(
                  controller: _tabController,
                  tabs: [
                    Tab(text: 'Tab 1'),
                    Tab(text: 'Tab 2'),
                  ],
                ),
              ),
            ];
          },
          body: TabBarView(
            controller: _tabController,
            children: [
              KeepAliveWrapper(
                child: MediaQuery.removePadding(
                  removeTop: true,
                  context: context,
                  child: ListView.builder(
                    itemCount: 1000,
                    itemBuilder: (context, index) {
                      return ListTile(
                        title: Text('Tab 1 Item $index'),
                      );
                    },
                  ),
                ),
              ),
              KeepAliveWrapper(
                child: MediaQuery.removePadding(
                  removeTop: true,
                  context: context,
                  child: ListView.builder(
                    itemCount: 1000,
                    itemBuilder: (context, index) {
                      return ListTile(
                        title: Text('Tab 2 Item $index'),
                      );
                    },
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class KeepAliveWrapper extends StatefulWidget {
  final Widget child;

  const KeepAliveWrapper({Key? key, required this.child}) : super(key: key);

  
  _KeepAliveWrapperState createState() => _KeepAliveWrapperState();
}

class _KeepAliveWrapperState extends State<KeepAliveWrapper> with AutomaticKeepAliveClientMixin {
  
  Widget build(BuildContext context) {
    super.build(context);
    return widget.child;
  }

  
  bool get wantKeepAlive => true;
}

总结

这就是Flutter解决NestedScrollView与TabBar双列表滚动位置同步问题相关代码,希望能帮助到你!

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-10 10:40:04       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-10 10:40:04       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-10 10:40:04       87 阅读
  4. Python语言-面向对象

    2024-04-10 10:40:04       96 阅读

热门阅读

  1. CentOS 7详细介绍。

    2024-04-10 10:40:04       40 阅读
  2. 文心一言和GPT-4全面比较

    2024-04-10 10:40:04       40 阅读
  3. 三种芯片:ASIC、FPGA、SoC

    2024-04-10 10:40:04       38 阅读
  4. Vue将iconfont封装成全局组件,自定义类名

    2024-04-10 10:40:04       38 阅读
  5. List接口(1) | ArrayList

    2024-04-10 10:40:04       42 阅读
  6. 关于yolov8x-p2.yaml

    2024-04-10 10:40:04       38 阅读
  7. 链表,栈,队列的区别及其应用

    2024-04-10 10:40:04       34 阅读
  8. 如何生成 ssh 秘钥?

    2024-04-10 10:40:04       35 阅读
  9. 7-11完全二叉树的层序遍历

    2024-04-10 10:40:04       37 阅读
  10. SQL注入漏洞详解

    2024-04-10 10:40:04       32 阅读