Flutter实现带动画堆叠ListView:横向列表左图滚动消失效果
实现Flutter横向列表左侧背景图随滚动消失效果
核心思路:通过Stack堆叠背景图与横向ListView,利用ScrollController监听滚动偏移,动态调整背景图的可见宽度,实现滚动时背景图逐渐消失的效果。
具体实现步骤
1. 初始化滚动控制器与状态变量
创建ScrollController监听滚动事件,用变量存储当前滚动偏移,用于计算背景图的可见范围。
2. 构建Stack布局
Stack底层放置背景图(通过动态宽度控制可见区域),上层放置横向滚动的列表。背景图初始宽度可自定义,滚动时根据偏移量逐步缩小宽度,直至完全隐藏。
3. 监听滚动事件
在组件初始化时添加滚动监听,更新偏移状态;组件销毁时释放控制器,避免内存泄漏。
完整代码示例
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('滚动消失背景示例')), body: const ScrollBackgroundDemo(), ), ); } } class ScrollBackgroundDemo extends StatefulWidget { const ScrollBackgroundDemo({super.key}); @override State<ScrollBackgroundDemo> createState() => _ScrollBackgroundDemoState(); } class _ScrollBackgroundDemoState extends State<ScrollBackgroundDemo> { final ScrollController _scrollController = ScrollController(); double _scrollOffset = 0.0; // 背景图初始可见宽度,可按需调整 final double _initialBgWidth = 200.0; @override void initState() { super.initState(); // 监听滚动偏移,更新状态 _scrollController.addListener(() { setState(() { _scrollOffset = _scrollController.offset; }); }); } @override void dispose() { _scrollController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { // 计算背景图当前可见宽度,确保不会出现负数 double bgVisibleWidth = (_initialBgWidth - _scrollOffset).clamp(0.0, _initialBgWidth); return Stack( children: [ // 背景图:通过SizedBox控制可见宽度,靠左对齐 Align( alignment: Alignment.centerLeft, child: SizedBox( width: bgVisibleWidth, child: Image.network( 'https://picsum.photos/200/300', // 替换为你的背景图地址 fit: BoxFit.cover, height: double.infinity, ), ), ), // 横向滚动列表 ListView.builder( controller: _scrollController, scrollDirection: Axis.horizontal, itemCount: 20, itemBuilder: (context, index) { return Container( width: 150, margin: const EdgeInsets.symmetric(horizontal: 8), color: Colors.blue[100 * ((index % 9) + 1)], child: Center(child: Text('Item $index')), ); }, ), ], ); } }
优化平滑过渡(可选)
如果需要更流畅的宽度变化动画,可将背景图的SizedBox替换为AnimatedContainer:
Align( alignment: Alignment.centerLeft, child: AnimatedContainer( duration: const Duration(milliseconds: 50), width: bgVisibleWidth, child: Image.network( 'https://picsum.photos/200/300', fit: BoxFit.cover, height: double.infinity, ), ), )
内容的提问来源于stack exchange,提问作者Muhammad Arif
相关产品推荐
相关产品推荐

