西苑做网站公司,东莞免费建网站企业,学设计需要什么条件,网站内容排版设计模板flutter sliver 多种滚动组合开发指南 视频 https://youtu.be/4mho1kZ_YQU https://www.bilibili.com/video/BV1WW4y1d7ZC/ 前言 有不少同学工作中遇到需要把几个不同滚动行为组件#xff08;顶部 appBar、内容固定块、tabBar 切换、tabBarView视图、自适应高度、横向滚动顶部 appBar、内容固定块、tabBar 切换、tabBarView视图、自适应高度、横向滚动黏贴成一个组件。 这时候就需要 sliver 出场了本文将会写一个多种滚动的组合。 业务场景分析 下面是淘宝、小红书的常见情况。 原文 https://ducafecat.com/blog/flutter-sliver-scroll 知识点 sliver Sliver 是 Flutter 中用于构建可滚动视图的基本构建块之一。Sliver 是可滚动区域中的一小部分具有固定的大小和位置可以根据需要动态加载和卸载。Sliver 通常用于创建高性能、高度灵活的可滚动视图例如列表、网格、瀑布流等。 在 Flutter 中有许多不同类型的 Sliver 组件每个组件都有特定的作用和用途。下面是一些常见的 Sliver 组件 SliverAppBar一个带有滚动效果的应用栏可以在向上滚动时隐藏并在向下滚动时显示。 SliverList将子组件放置在一个垂直列表中可以根据需要动态加载和卸载列表项。 SliverGrid将子组件放置在一个网格中可以根据需要动态加载和卸载网格项。 SliverPadding为子组件提供填充以使它们与其他 Sliver 组件的大小和位置保持一致。 SliverToBoxAdapter将一个普通的组件包装成一个 Sliver 组件以便将其放置在 CustomScrollView 中。 参考 步骤 第一步Sliver 横向滚动 lib/page.dart Widget _mainView() { return CustomScrollView( slivers: [ // 横向滚动 SliverToBoxAdapter( child: SizedBox( height: 100, child: PageView( children: [ Container( color: Colors.yellow, child: const Center(child: Text(横向滚动)), ), Container(color: Colors.green), Container(color: Colors.blue), ], ), ), ), ... SliverToBoxAdapter 进行包装才能 slivers 使用。 override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text(Sliver Scroll)), body: _mainView(), ); } 第二步固定高度的 tabView return CustomScrollView( slivers: [ ... // 固定高度内容 SliverToBoxAdapter( child: Container( height: 200, color: Colors.greenAccent, child: const Center(child: Text(固定高度内容)), ), ), // tabView 内容 SliverToBoxAdapter( child: DefaultTabController( length: 3, child: Column( children: [ const TabBar( tabs: [ Tab(text: Tab 1), Tab(text: Tab 2), Tab(text: Tab 3), ], ), SizedBox( height: 200, child: TabBarView( children: [ Container(color: Colors.yellow), Container(color: Colors.green), Container(color: Colors.blue), ], ), ), ], ), ), ), 外层嵌套 DefaultTabController 才能让 TabBar、TabBarView 顺利工作。 第三步自适应高度的 tabView 实现 SliverPersistentHeaderDelegate 抽象类 class _SliverDelegate extends SliverPersistentHeaderDelegate { _SliverDelegate({ required this.minHeight, required this.maxHeight, required this.child, }); final double minHeight; //最小高度 final double maxHeight; //最大高度 final Widget child; override double get minExtent minHeight; override double get maxExtent max(maxHeight, minHeight); override Widget build( BuildContext context, double shrinkOffset, bool overlapsContent) { return SizedBox.expand(child: child); } override //是否需要重建 bool shouldRebuild(_SliverDelegate oldDelegate) { return maxHeight ! oldDelegate.maxHeight || minHeight ! oldDelegate.minHeight || child ! oldDelegate.child; }} 编写固定头部 sliver 组件 Widget _buildPersistentHeader(Widget child, {double? minHeight, double? maxHeight}) SliverPersistentHeader( pinned: true, delegate: _SliverDelegate( minHeight: minHeight ?? 40.0, maxHeight: maxHeight ?? 40.0, child: child, )); 定义 TabController class _MyPageViewState extends StateMyPageView with TickerProviderStateMixin { ... 混入 TickerProviderStateMixin late TabController _tabController; override void initState() { _tabController TabController(length: 3, vsync: this); super.initState(); } override void dispose() { _tabController.dispose(); // 释放内存 super.dispose(); } 加入 slivers Widget _mainView() { return CustomScrollView( slivers: [ ... // TabBar 固定 _buildPersistentHeader(TabBar( controller: _tabController, tabs: const [ Tab(text: Tab 1), Tab(text: Tab 2), Tab(text: Tab 3), ], )), 使用 SliverFillRemaining 来撑开剩余空间 // TabBarView 自适应高度 SliverFillRemaining( child: TabBarView( controller: _tabController, children: [ // 第一个选项卡的内容 ListView.builder( itemCount: 20, itemBuilder: (BuildContext context, int index) { return ListTile(title: Text(Item $index)); }, ), // 第二个选项卡的内容 ListView.builder( itemCount: 10, itemBuilder: (BuildContext context, int index) { return ListTile(title: Text(Item $index)); }, ), // 第三个选项卡的内容 ListView.builder( itemCount: 5, itemBuilder: (BuildContext context, int index) { return ListTile(title: Text(Item $index)); }, ), ], ), ), SliverFillRemaining 是一个可以填充剩余空间的 sliver 组件它可以将子组件放置在视图区域的剩余空间中并自动调整子组件的大小以填充整个空间。通常情况下SliverFillRemaining 用于在滚动视图中放置一个占满整个视图区域的组件例如底部栏或页脚。 第四步子 tabBar 还可以加入子 tabBar 组成父子选项切换 // 子 TabBar 固定 _buildPersistentHeader(TabBar( controller: _tabController, tabs: const [ Tab(text: subTab 1), Tab(text: subTab 2), Tab(text: subTab 3), ], )), 父子 tabBar 中间再加一个固定块查看滚动效果 // 固定高度内容 SliverToBoxAdapter( child: Container( height: 100, color: Colors.greenAccent, child: const Center(child: Text(固定高度内容)), ), ), 最后底部再加入 SliverList 我们在底部再加一个 list 模块看看效果。 Widget _mainView() { return CustomScrollView( slivers: [ ... // 固定高度内容 SliverToBoxAdapter( child: Container( height: 200, color: Colors.greenAccent, child: const Center(child: Text(固定高度内容)), ), ), // 列表 100 行 SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return ListTile(title: Text(Item $index)); }, childCount: 100, ), ), 代码 https://github.com/ducafecat/flutter_develop_tips/tree/main/flutter_application_sliver_scroll 小结 使用 Sliver 组件后我们确实把几种滚动给黏贴上了但是不难发现过于复杂的滚动用户体验方面还是要考虑的。 不能只为了堆积功能。 感谢阅读本文 如果我有什么错请在评论中让我知道。我很乐意改进。 © 猫哥 ducafecat.com end