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

Flutter实现卡片旋转滑动平滑效果的无包方案求助

实现平滑卡片滑动旋转效果

核心问题是你当前只在页面切换完成后更新索引,导致旋转角度是突变的。要实现平滑过渡,需要监听PageController的实时页面偏移量,动态计算每个卡片的旋转角度和位置。

修改步骤:

  • 移除onPageChanged的setState逻辑,改为监听PageController的页面滚动偏移
  • 基于实时的页面偏移值,动态计算每个卡片的旋转角度和位置偏移
  • 通过矩阵变换同时实现旋转和位移,让过渡效果更自然

修改后的完整代码:

import 'package:flutter/material.dart';
import 'package:mawada/cardCollections/widgets/card_play_widget.dart';
import 'package:mawada/constants/app_color.dart';
import 'package:mawada/shared/widgets/app_button.dart';

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

  @override
  State<CardPlay> createState() => _CardPlayState();
}

class _CardPlayState extends State<CardPlay> {
  final PageController pageController = PageController(viewportFraction: 0.7);
  double currentPage = 0.0;

  @override
  void initState() {
    super.initState();
    // 监听页面滚动的实时偏移
    pageController.addListener(() {
      setState(() {
        currentPage = pageController.page!;
      });
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: AppColor.background,
      appBar: AppBar(
        actions: [
          Padding(
            padding: const EdgeInsets.only(right: 10.0),
            child: Image.asset(
              'assets/logo2.png',
              fit: BoxFit.cover,
              height: 55,
            ),
          )
        ],
      ),
      body: ListView(
        padding: const EdgeInsets.symmetric(vertical: 30),
        children: [
          // Progress indicator
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 20),
            child: Container(
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(30),
                boxShadow: [
                  BoxShadow(
                    offset: const Offset(0, 2),
                    color: Colors.grey.withOpacity(0.5),
                    spreadRadius: 1,
                    blurRadius: 2,
                  )
                ],
              ),
              child: LinearProgressIndicator(
                value: 0.2,
                semanticsLabel: "0.2",
                backgroundColor: Colors.white,
                valueColor: const AlwaysStoppedAnimation<Color>(
                  AppColor.primary,
                ),
                minHeight: 45,
                borderRadius: BorderRadius.circular(30),
              ),
            ),
          ),
          const SizedBox(height: 50),
          SizedBox(
            height: 400,
            child: PageView.builder(
              controller: pageController,
              itemCount: 10,
              itemBuilder: (context, index) {
                // 计算当前卡片与滚动位置的差值
                double difference = index - currentPage;
                // 限制旋转角度范围,避免过度旋转
                double rotationAngle = difference.clamp(-0.1, 0.1);
                
                // 计算卡片Y轴偏移,让当前卡片更突出
                double translateY = difference.abs() * 30;

                return Transform(
                  transform: Matrix4.identity()
                    ..rotateZ(rotationAngle)
                    ..translate(0, translateY),
                  alignment: Alignment.center,
                  child: const CardPlayWidget(),
                );
              },
            ),
          )
        ],
      ),
      bottomNavigationBar: Container(
        height: 150,
        padding: const EdgeInsets.symmetric(horizontal: 20),
        child: Center(
          child: AppButton(
            elevation: 0,
            borderSideColor: AppColor.primary,
            backgroundColor: AppColor.background,
            foregroundColor: AppColor.primary,
            buttonText: "Close",
            onPressed: () {},
          ),
        ),
      ),
    );
  }
}

关键改动说明:

  • 新增currentPage变量存储实时页面偏移值,通过pageController.addListener实时更新状态
  • 在itemBuilder中,根据卡片索引与currentPage的差值动态计算旋转角度和Y轴偏移,实现滑动过程中的平滑过渡
  • 使用Matrix4同时应用旋转和位移效果,让卡片的动画联动更自然
  • 移除了原有的AnimationController,因为PageController的实时偏移已经可以驱动平滑动画

这样修改后,滑动过程中卡片的旋转和位置会随着手势实时平滑变化,完全符合你想要的效果,且未使用任何第三方包。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 12:24:53