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

如何在Flutter中实现堆叠卡片滚动动画及对应UI效果?

Flutter堆叠卡片滚动动画实现方案

核心思路

通过ScrollController监听滚动偏移量,结合Transform和Opacity组件,实时计算每个卡片的缩放、位移、透明度参数,模拟堆叠滚动的视觉效果。主要依赖ListView(或横向ListView)作为滚动容器,配合Positioned控制卡片初始堆叠位置。

具体实现步骤

  1. 定义卡片数据模型:封装卡片所需的标题、描述、颜色等信息
  2. 初始化滚动控制器:监听滚动偏移量,用于计算卡片的动画参数
  3. 构建堆叠列表:使用ListView.builder生成卡片,每个卡片通过Transform应用动态变换
  4. 计算动画参数:根据滚动偏移量,实时计算卡片的缩放比例、位移距离和透明度
  5. 优化视觉层次:通过调整阴影、堆叠间距,增强卡片的堆叠立体感

完整代码示例

import 'package:flutter/material.dart';

class CardItem {
  final String title;
  final String description;
  final Color color;

  CardItem({required this.title, required this.description, required this.color});
}

class StackedCardsScreen extends StatefulWidget {
  const StackedCardsScreen({super.key});

  @override
  State<StackedCardsScreen> createState() => _StackedCardsScreenState();
}

class _StackedCardsScreenState extends State<StackedCardsScreen> {
  final ScrollController _scrollController = ScrollController();
  final List<CardItem> _cards = [
    CardItem(title: "卡片1", description: "这是第一张堆叠卡片", color: Colors.blueAccent),
    CardItem(title: "卡片2", description: "这是第二张堆叠卡片", color: Colors.orangeAccent),
    CardItem(title: "卡片3", description: "这是第三张堆叠卡片", color: Colors.greenAccent),
    CardItem(title: "卡片4", description: "这是第四张堆叠卡片", color: Colors.purpleAccent),
  ];
  final double _cardHeight = 280;
  final double _stackOffset = 80; // 上下卡片的重叠间距

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("堆叠卡片滚动")),
      body: ListView.builder(
        controller: _scrollController,
        padding: EdgeInsets.only(top: 100, bottom: 100 + _stackOffset),
        itemCount: _cards.length,
        itemBuilder: (context, index) {
          return _buildStackedCard(index);
        },
      ),
    );
  }

  Widget _buildStackedCard(int index) {
    final double cardTop = index * (_cardHeight - _stackOffset);
    final double scrollOffset = _scrollController.hasClients ? _scrollController.offset : 0;
    // 计算滚动进度(0=未滚动,1=完全滚出视野)
    double scrollRatio = (scrollOffset - cardTop) / _cardHeight;
    scrollRatio = scrollRatio.clamp(0.0, 1.0);

    // 动画参数:可根据需求调整系数
    final double scale = 1 - (0.2 * scrollRatio); // 缩放从1到0.8
    final double translateY = _stackOffset * scrollRatio; // Y轴位移从0到_stackOffset
    final double opacity = 1 - (0.4 * scrollRatio); // 透明度从1到0.6

    return Positioned(
      top: cardTop,
      left: 20,
      right: 20,
      height: _cardHeight,
      child: Transform(
        transform: Matrix4.identity()
          ..translate(0, translateY)
          ..scale(scale),
        alignment: Alignment.topCenter,
        child: Opacity(
          opacity: opacity,
          child: Card(
            elevation: 8 - (6 * scrollRatio), // 滚动时降低阴影
            shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
            color: _cards[index].color,
            child: Padding(
              padding: const EdgeInsets.all(20),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    _cards[index].title,
                    style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold, color: Colors.white),
                  ),
                  const SizedBox(height: 12),
                  Text(
                    _cards[index].description,
                    style: const TextStyle(fontSize: 16, color: Colors.white70),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

自定义调整技巧

  • 修改_cardHeight和_stackOffset可调整卡片尺寸与堆叠密度
  • 调整scale、translateY、opacity的系数,可控制动画的幅度和快慢
  • 若需横向堆叠滚动,将ListView的scrollDirection设为Axis.horizontal,并把translateY改为translateX
  • 可添加卡片的旋转动画,在Matrix4中加入rotateZ参数(如..rotateZ(0.02 * scrollRatio))增强动态效果

内容的提问来源于stack exchange,提问作者Hetal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 02:43:12