Flutter CarouselSlider如何实现滑动时下层组件固定效果
问题描述
使用CarouselSlider实现了一个简易可滑动视图分页器,初始实现代码如下:
return Scaffold( body: CarouselSlider( options: CarouselOptions( viewportFraction: 1, // aspectRatio: 1, height: double.maxFinite, // enlargeCenterPage: true, ), items: List.generate( 10, (i) => Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Container( color: (i % 2 == 0) ? Colors.red : Colors.green, ), ), Text('text $i', style: TextStyle(fontSize: 16.0)), ], )), ));
默认运行效果为相邻分页横向相邻排布,不符合预期。预期效果为:向左滑动当前组件时,下一个组件固定显示在当前组件下方,视觉上呈现下层组件固定、仅上层组件被滑动移除的效果。
初始运行效果参考:
实现方案
CarouselSlider的底层布局逻辑是横向平铺所有相邻页面,没有提供层叠布局的配置项,直接修改组件内部参数无法实现预期效果,推荐用Stack层叠结构结合PageView实现,不需要修改原有页面布局代码,实现逻辑更简单:
- 用
Stack作为根布局,第一层(下层)永远固定渲染当前页的下一个页面 - 第二层(上层)放横向滑动的
PageView,渲染当前显示的页面,滑动时上层页面随手势横向移出屏幕,自然露出下层提前渲染好的下一页,即可实现上层滑走、下层固定的视觉效果
完整替换代码如下:
// 首先在对应的State类中声明状态变量记录当前页索引 int currentIndex = 0; @override Widget build(BuildContext context) { return Scaffold( body: Stack( children: [ // 下层固定渲染下一页,索引越界时回到第一页 if (currentIndex < 9) _buildSinglePage(currentIndex + 1), // 上层可横向滑动的分页组件 PageView.builder( scrollDirection: Axis.horizontal, itemCount: 10, onPageChanged: (index) { setState(() { currentIndex = index; }); }, itemBuilder: (context, index) => _buildSinglePage(index), ) ], ), ); } // 抽离单页构造逻辑,复用原有页面布局 Widget _buildSinglePage(int i) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Container( color: (i % 2 == 0) ? Colors.red : Colors.green, ), ), Text('text $i', style: TextStyle(fontSize: 16.0)), ], ); }
扩展说明
- 如果需要支持右滑返回上一页的效果,只需要监听
PageController的滑动偏移值判断滑动方向,动态修改下层渲染的页面索引为上一页/下一页即可 - 该方案没有多余的组件渲染开销,性能和原生
PageView一致 - 如果需要加滑动转场动画,可以在上层页面的构建中通过
PageController的偏移值给当前页添加平移、透明度变化等动画效果
内容的提问来源于stack exchange,提问作者Cyrus the Great
相关产品推荐
相关产品推荐

