如何在Flutter中实现滚动时逐步显示隐藏元素的列表布局?
Flutter实现带遮挡滚动动画的列表布局
需要实现一个包含7个元素的列表:初始状态下第6、7个元素被第5个元素遮挡在下方;当列表向上滚动时,第5个元素逐渐向上移开,逐步露出第6、7个元素。
实现思路
- 用
ScrollController监听列表滚动偏移量,以此驱动动画逻辑 - 对第5个列表项应用平移动画,滚动超过临界距离后,跟随滚动向上移动
- 第6、7个列表项初始定位在第5个项下方,通过滚动偏移控制其平移距离与透明度,实现逐步显示效果
- 直接在
build方法中结合滚动偏移计算控件变换参数,无需额外动画控制器
完整代码示例
import 'package:flutter/material.dart'; class AnimatedOccludedList extends StatefulWidget { const AnimatedOccludedList({super.key}); @override State<AnimatedOccludedList> createState() => _AnimatedOccludedListState(); } class _AnimatedOccludedListState extends State<AnimatedOccludedList> { final ScrollController _scrollController = ScrollController(); double _item5Offset = 0.0; // 触发动画的临界滚动距离,可根据列表项高度调整 final double _triggerScroll = 100.0; @override void initState() { super.initState(); _scrollController.addListener(_onScroll); } void _onScroll() { final scrollOffset = _scrollController.offset; setState(() { _item5Offset = scrollOffset > _triggerScroll ? scrollOffset - _triggerScroll : 0.0; }); } @override void dispose() { _scrollController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final itemHeight = 80.0; return Scaffold( appBar: AppBar(title: const Text("遮挡滚动动画列表")), body: ListView.builder( controller: _scrollController, padding: const EdgeInsets.symmetric(vertical: 20), itemCount: 7, itemBuilder: (context, index) { final itemIndex = index + 1; if (itemIndex == 5) { return Transform.translate( offset: Offset(0, -_item5Offset), child: _buildListItem(itemIndex, itemHeight), ); } else if (itemIndex >= 6) { final initialOffset = itemHeight; final visibleOffset = _item5Offset > initialOffset ? _item5Offset - initialOffset : 0.0; return Transform.translate( offset: Offset(0, initialOffset - visibleOffset), child: Opacity( opacity: visibleOffset / initialOffset, child: _buildListItem(itemIndex, itemHeight), ), ); } else { return _buildListItem(itemIndex, itemHeight); } }, ), ); } Widget _buildListItem(int index, double height) { return Container( height: height, margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( color: Colors.blue.shade100, borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.blue.shade300), ), alignment: Alignment.center, child: Text( "列表项 $index", style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w500), ), ); } } void main() => runApp(const MaterialApp(home: AnimatedOccludedList()));
代码说明
- 第5个列表项通过
Transform.translate实现向上平移,滚动超过_triggerScroll后开始跟随滚动 - 第6、7个列表项初始被第5个项完全遮挡,随着第5个项上移,通过平移抵消初始遮挡距离,同时配合透明度动画实现平滑显示
_buildListItem方法统一构建列表项样式,可根据需求自定义布局、颜色等属性
内容的提问来源于stack exchange,提问作者felipe Souza
相关产品推荐
相关产品推荐

