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

如何在Flutter中实现带动画效果的性别选择页面?

Flutter实现带缩放动画的性别选择PageView

你的现有代码仅实现了基础的PageView滚动功能,缺少选中项放大、未选中项缩小的过渡动画。要达成目标效果,核心是监听PageController的页面偏移量,动态调整每个item的缩放比例和透明度,以下是修改后的完整实现:

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

  @override
  State<GenderSelectionPage> createState() => _GenderSelectionPageState();
}

class _GenderSelectionPageState extends State<GenderSelectionPage> with SingleTickerProviderStateMixin {
  late PageController pageController;
  double currentPage = 0.0;

  @override
  void initState() {
    super.initState();
    // 初始化PageController,设置初始页面和视口比例
    pageController = PageController(initialPage: 0, viewportFraction: .5)
      ..addListener(() {
        // 实时监听页面偏移,更新当前页面值
        setState(() {
          currentPage = pageController.page!;
        });
      });
  }

  @override
  void dispose() {
    // 销毁控制器,避免内存泄漏
    pageController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    List<Widget> genders = [
      Image.asset("assets/fitness_app/area1.png"),
      Image.asset("assets/fitness_app/area3.png")
    ];

    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: premiumDialogue,
        backgroundColor: primary,
        child: const Icon(Icons.add),
      ),
      backgroundColor: bgcolor,
      appBar: AppBar(
        toolbarHeight: 70,
        leadingWidth: 65,
        backgroundColor: Colors.transparent,
        centerTitle: true,
        title: const Text("Home Workouts", style: h2black),
        elevation: 0,
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Expanded(
            child: PageView.builder(
              controller: pageController,
              clipBehavior: Clip.antiAlias,
              physics: const BouncingScrollPhysics(),
              itemCount: genders.length,
              itemBuilder: (context, index) {
                // 计算当前item与活跃页面的距离
                double offset = (currentPage - index).abs();
                // 计算缩放比例:距离越远,缩放越小
                double scale = 1.0 - (offset * 0.3);
                // 限制缩放范围,避免过度缩小
                scale = scale.clamp(0.7, 1.0);
                // 同步调整透明度,增强层次感
                double opacity = 0.8 + ((1.0 - scale) * 0.2);

                return Center(
                  child: Transform.scale(
                    scale: scale,
                    child: Opacity(
                      opacity: opacity,
                      child: genders[index],
                    ),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }

  void premiumDialogue() {
    // 此处实现你的弹窗逻辑
  }
}

关键修改说明:

  1. 添加页面偏移监听:通过pageController.addListener实时获取滚动位置,用currentPage保存当前页面的精确偏移值
  2. 动态缩放与透明度:在itemBuilder中根据每个item与当前页面的距离,计算缩放比例和透明度,实现选中项放大、未选中项缩小的过渡效果
  3. 内存泄漏防护:在dispose方法中销毁PageController,避免内存泄漏
  4. 代码优化:修正了原代码中TabController无用、initState初始化冗余、Column闭合括号错误等问题

你可以调整scale计算中的系数(比如把0.3改成0.2),来控制动画的强弱程度,适配你的设计需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 07:55:29