如何在Flutter中实现卡片层叠式垂直轮播滑块?
垂直层叠轮播滑块实现方案
可以通过Stack结合动画控制器、手势监听来实现你要的层叠式垂直轮播效果,核心思路是用Stack堆叠卡片,通过动画控制卡片的位移、缩放和透明度,模拟层叠递进的视觉效果。
完整实现代码
import 'package:flutter/material.dart'; class VerticalStackCarousel extends StatefulWidget { final List<Widget> items; final double visibleItemCount; const VerticalStackCarousel({ super.key, required this.items, this.visibleItemCount = 3, }); @override State<VerticalStackCarousel> createState() => _VerticalStackCarouselState(); } class _VerticalStackCarouselState extends State<VerticalStackCarousel> with SingleTickerProviderStateMixin { late AnimationController _animationController; int _currentIndex = 0; final double _itemHeight = 200; final double _itemWidth = 300; final double _scaleFactor = 0.1; final double _opacityFactor = 0.3; @override void initState() { super.initState(); _animationController = AnimationController( vsync: this, duration: const Duration(milliseconds: 300), ); } @override void dispose() { _animationController.dispose(); super.dispose(); } void _handleDragEnd(DragEndDetails details) { if (details.velocity.pixelsPerSecond.dy > 0) { _nextItem(); } else if (details.velocity.pixelsPerSecond.dy < 0) { _previousItem(); } } void _nextItem() { if (_currentIndex < widget.items.length - 1) { _animationController.forward().then((_) { setState(() => _currentIndex++); _animationController.reset(); }); } } void _previousItem() { if (_currentIndex > 0) { _animationController.reverse().then((_) { setState(() => _currentIndex--); _animationController.reset(); }); } } @override Widget build(BuildContext context) { return GestureDetector( onVerticalDragEnd: _handleDragEnd, child: SizedBox( height: _itemHeight * widget.visibleItemCount * 0.8, child: Stack( alignment: Alignment.center, children: List.generate( widget.items.length, (index) { final itemOffset = index - _currentIndex; if (itemOffset < 0 || itemOffset >= widget.visibleItemCount) { return const SizedBox.shrink(); } final animationValue = _animationController.value; final currentOffset = itemOffset - animationValue; return Transform.translate( offset: Offset(0, currentOffset * _itemHeight * 0.6), child: Transform.scale( scale: 1 - (currentOffset * _scaleFactor), child: Opacity( opacity: 1 - (currentOffset * _opacityFactor), child: SizedBox( height: _itemHeight, width: _itemWidth, child: widget.items[index], ), ), ), ); }, ).reversed.toList(), ), ), ); } } // 使用示例 class CarouselDemo extends StatelessWidget { const CarouselDemo({super.key}); @override Widget build(BuildContext context) { final List<Widget> carouselItems = [ Container(color: Colors.red, child: const Center(child: Text('卡片1'))), Container(color: Colors.blue, child: const Center(child: Text('卡片2'))), Container(color: Colors.green, child: const Center(child: Text('卡片3'))), Container(color: Colors.yellow, child: const Center(child: Text('卡片4'))), ]; return Scaffold( appBar: AppBar(title: const Text('垂直层叠轮播')), body: Center( child: VerticalStackCarousel(items: carouselItems), ), ); } }
关键逻辑说明
- Stack层叠布局:将卡片堆叠,通过
reversed确保当前显示的卡片处于最上层 - 动画控制器:控制切换过程的平滑过渡,同步处理位移、缩放、透明度的变化
- 手势监听:通过垂直拖拽的速度方向,判断切换上一张还是下一张卡片
- Transform组件:用
translate控制垂直偏移,scale控制卡片大小,Opacity控制透明度,实现层叠递进的视觉层级
内容的提问来源于stack exchange,提问作者Papon sarker
相关产品推荐
相关产品推荐

