You need to enable JavaScript to run this app. Flutter PageView如何为viewportFraction属性添加切换动画效果
优惠活动
大模型
产品
解决方案
定价
更多

Flutter PageView如何为viewportFraction属性添加切换动画效果

如何为viewportFraction属性添加切换动画?

效果演示动图

问题原因

PageController的viewportFraction是final属性,无法直接修改。你目前直接替换PageController实例的实现方式,两个状态之间没有过渡过程,自然不会出现平滑动画。

实现方案

通过动画控制器驱动viewportFraction数值平滑过渡,过渡过程中动态生成新的PageController并同步当前页码,避免切换过程中页面跳转即可实现效果,完整可运行代码如下:

import 'dart:math';
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) => MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Test',
        theme: ThemeData(),
        home: const Test(),
      );
}

class Test extends StatefulWidget {
  const Test({Key? key}) : super(key: key);

  @override
  State<Test> createState() => _TestState();
}

class _TestState extends State<Test> with SingleTickerProviderStateMixin {
  bool _active = false;
  int _currentPage = 0;
  late AnimationController _animController;
  late Animation<double> _viewportFractionAnim;

  @override
  void initState() {
    super.initState();
    // 初始化动画控制器
    _animController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 300),
    );
    // 定义viewportFraction的过渡范围和插值曲线
    _viewportFractionAnim = Tween<double>(begin: 1 / 3, end: 0.85).animate(
      CurvedAnimation(parent: _animController, curve: Curves.easeInOut),
    );
  }

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

  @override
  Widget build(BuildContext context) {
    // 动画值变化时动态生成新的PageController,同步当前页码
    final pageController = PageController(
      viewportFraction: _viewportFractionAnim.value,
      initialPage: _currentPage,
    );
    return NotificationListener<ScrollNotification>(
      // 监听页面滚动,实时更新当前页码
      onNotification: (notification) {
        if (notification is ScrollUpdateNotification) {
          _currentPage = pageController.page?.round() ?? 0;
        }
        return true;
      },
      child: AnimatedBuilder(
        animation: _viewportFractionAnim,
        builder: (context, child) => PageView.builder(
          padEnds: false,
          controller: pageController,
          itemCount: 10,
          itemBuilder: (context, index) => GestureDetector(
            onTap: () {
              setState(() {
                _active = !_active;
                _active ? _animController.forward() : _animController.reverse();
              });
            },
            child: Container(
              color: Color((Random().nextDouble() * 0xFFFFFF).toInt())
                  .withOpacity(1),
              child: Center(child: Text('$index')),
            ),
          ),
        ),
      ),
    );
  }
}

你可以自行调整动画的时长、插值曲线来匹配你的设计需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 07:33:02