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

Flutter如何实现旧版iPhone CoverFlow双向重叠且可横向滚动的效果

要实现双向重叠的Coverflow效果,核心需要动态调整每个卡片的层级、偏移量和3D变换,你之前的方案只用到了Align的widthFactor,没有动态修改层级和滚动时的参数,所以只能实现单方向重叠。以下是可直接运行的完整实现:

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(
      title: 'Flutter Coverflow Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const CoverflowPage(),
    );
  }
}

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

  @override
  State<CoverflowPage> createState() => _CoverflowPageState();
}

class _CoverflowPageState extends State<CoverflowPage> {
  final ScrollController _scrollController = ScrollController();
  final double _cardWidth = 120;
  final int _itemCount = 25;
  double _scrollOffset = 0;

  @override
  void initState() {
    super.initState();
    _scrollController.addListener(() {
      setState(() {
        _scrollOffset = _scrollController.offset;
      });
    });
  }

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

  @override
  Widget build(BuildContext context) {
    final screenWidth = MediaQuery.of(context).size.width;
    // 计算滚动中心位置
    final centerX = screenWidth / 2;

    return Scaffold(
      appBar: AppBar(title: const Text('Coverflow 效果')),
      body: SizedBox(
        height: 300,
        child: Stack(
          alignment: Alignment.centerLeft,
          children: [
            // 占位用的透明ListView,仅用来提供滚动能力
            ListView.builder(
              controller: _scrollController,
              scrollDirection: Axis.horizontal,
              physics: const PageScrollPhysics(),
              itemCount: _itemCount,
              itemBuilder: (context, index) => SizedBox(width: _cardWidth * 0.6),
            ),
            // 渲染所有卡片
            ...List.generate(_itemCount, (index) {
              // 当前卡片的中心X坐标
              final cardCenterX = index * _cardWidth * 0.6 + _cardWidth / 2 - _scrollOffset;
              // 卡片和屏幕中心的距离差
              final diff = cardCenterX - centerX;
              // 归一化的距离比例
              final ratio = (diff / centerX).clamp(-1.0, 1.0);

              // 计算变换参数
              final rotateY = ratio * 0.5; // Y轴旋转角度
              final scale = 1 - ratio.abs() * 0.2; // 缩放比例
              final zIndex = 100 - ratio.abs() * 100; // 层级,中间最高

              return Positioned(
                left: index * _cardWidth * 0.6 - _scrollOffset,
                child: Transform(
                  transform: Matrix4.identity()
                    ..setEntry(3, 2, 0.001) // 开启透视效果
                    ..rotateY(rotateY)
                    ..scale(scale),
                  alignment: Alignment.center,
                  child: Container(
                    height: 200,
                    width: _cardWidth,
                    decoration: BoxDecoration(
                      color: Colors.green.withOpacity(0.4),
                      borderRadius: BorderRadius.circular(8),
                      boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 6, spreadRadius: 2)],
                    ),
                    child: Center(
                      child: Text(
                        index.toString(),
                        style: const TextStyle(fontSize: 32, color: Colors.white),
                      ),
                    ),
                  ),
                ),
              );
            }).toList()..sort((a, b) => (a.zIndex ?? 0).compareTo(b.zIndex ?? 0)),
          ],
        ),
      ),
    );
  }
}

以上代码实现的效果支持:

  • 双向重叠:中间卡片始终覆盖在左右两侧卡片之上
  • 横向滚动:支持平滑滚动,配合PageScrollPhysics可实现滑动停靠效果
  • 3D变换:包含透视、旋转、缩放效果,完全匹配旧版iPhone的Coverflow设计
    如果需要调整重叠间距,可以修改_cardWidth * 0.6中的系数,系数越小重叠程度越高;调整变换参数即可修改旋转角度和缩放比例,适配不同的设计需求。

内容的提问来源于stack exchange,提问作者Md Delwar Hossain

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 04:24:08