You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 01:57:33