Flutter页面过渡动画插件page_transition的使用

发布于 1周前 作者 vueper 来自 Flutter

Flutter页面过渡动画插件page_transition的使用

page_transition 是一个Flutter插件,它提供了简单易用的API来创建美观的页面过渡动画。以下是关于如何安装和使用该插件的详细指南。

安装

在你的 pubspec.yaml 文件中添加依赖:

dependencies:
  page_transition: ^latest_version

确保将 latest_version 替换为最新版本号,可以通过 Pub 查看最新版本。

使用方法

使用扩展(推荐)

page_transition 提供了便捷的方法来执行页面过渡,例如:

// 简单的淡入淡出过渡
context.pushTransition(
  type: PageTransitionType.fade,
  child: DetailScreen(),
);

// 使用构造器模式
context.pushTransition(
  type: PageTransitionType.fade,
  childBuilder: (context) => DetailScreen(
    id: someId,
    title: someTitle,
  ),
);

// 替换当前页面
context.pushReplacementTransition(
  type: PageTransitionType.rightToLeft,
  child: DetailScreen(),
);

// 推送并移除直到满足条件
context.pushAndRemoveUntilTransition(
  type: PageTransitionType.fade,
  child: HomePage(),
  predicate: (route) => false,
);

// 命名路由过渡
context.pushNamedTransition(
  routeName: '/detail',
  type: PageTransitionType.fade,
  arguments: {'id': 1},
);

传统用法

你也可以通过传统的 Navigator 方法来实现:

Navigator.push(
  context,
  PageTransition(
    type: PageTransitionType.fade,
    child: DetailScreen(),
  ),
);

// 或者使用构造器模式
Navigator.push(
  context,
  PageTransition(
    type: PageTransitionType.fade,
    childBuilder: (context) => DetailScreen(id: someId),
  ),
);

路由生成器(GoRouter、AutoRoute等)

GoRouter 示例

final router = GoRouter(
  routes: [
    GoRoute(
      path: '/details/:id',
      pageBuilder: (context, state) {
        return PageTransition(
          type: PageTransitionType.rightToLeftJoined,
          childCurrent: context.currentRoute,
          child: DetailsPage(id: state.params['id']),
          settings: RouteSettings(name: state.location),
        );
      },
    ),
  ],
);

AutoRoute 示例

首先定义你的路由:

@MaterialAutoRouter(
  replaceInRouteName: 'Page,Route',
  routes: <AutoRoute>[
    AutoRoute(
      page: HomePage,
      initial: true,
    ),
    CustomRoute(
      page: DetailsPage,
      path: '/details/:id',
      transitionsBuilder: (context, animation, secondaryAnimation, child) {
        return PageTransition(
          type: PageTransitionType.sharedAxisHorizontal,
          child: child,
        ).buildTransitions(
          context,
          animation,
          secondaryAnimation,
          child,
        );
      },
    ),
    CustomRoute(
      page: ProfilePage,
      path: '/profile',
      transitionsBuilder: (context, animation, secondaryAnimation, child) {
        return PageTransition(
          type: PageTransitionType.sharedAxisVertical,
          child: child,
        ).buildTransitions(
          context,
          animation,
          secondaryAnimation,
          child,
        );
      },
    ),
  ],
)
class $AppRouter {}

然后在应用中使用:

@override
Widget build(BuildContext context) {
  return MaterialApp.router(
    routerDelegate: _appRouter.delegate(),
    routeInformationParser: _appRouter.defaultRouteParser(),
  );
}

// 导航使用 AutoRoute
context.router.push(DetailsRoute(id: 123)); // 使用共享轴水平过渡
context.router.push(const ProfileRoute()); // 使用共享轴垂直过渡

其他特性

iOS 手势返回

启用iOS风格的手势返回:

context.pushTransition(
  type: PageTransitionType.rightToLeft,
  child: DetailScreen(),
  isIos: true,
);

注意:iOS手势返回仅适用于 rightToLeftfade 过渡。

继承主题

使用父级的主题进行过渡:

context.pushTransition(
  type: PageTransitionType.rightToLeft,
  child: DetailScreen(),
  inheritTheme: true,
);

自定义持续时间和曲线

context.pushTransition(
  type: PageTransitionType.fade,
  child: DetailScreen(),
  duration: Duration(milliseconds: 300),
  curve: Curves.easeInOut,
);

高级用法

共享轴过渡

Material Design 3风格的共享轴过渡:

// 水平共享轴
context.pushTransition(
  type: PageTransitionType.sharedAxisHorizontal,
  child: DetailScreen(),
  duration: Duration(milliseconds: 400),
  curve: Curves.easeInOut,
);

// 垂直共享轴
context.pushTransition(
  type: PageTransitionType.sharedAxisVertical,
  child: DetailScreen(),
);

// 缩放共享轴
context.pushTransition(
  type: PageTransitionType.sharedAxisScale,
  child: DetailScreen(),
);

嵌套导航与命名路由

MaterialApp(
  onGenerateRoute: (settings) {
    switch (settings.name) {
      case '/details':
        return PageTransition(
          type: PageTransitionType.sharedAxisHorizontal,
          settings: settings,
          child: DetailsPage(),
        );
      case '/profile/settings':
        return PageTransition(
          type: PageTransitionType.sharedAxisVertical,
          settings: settings,
          child: SettingsPage(),
        );
    }
  },
);

// 使用扩展进行导航
context.pushNamedTransition(
  routeName: '/details',
  type: PageTransitionType.sharedAxisHorizontal,
  arguments: {'id': 123},
);

性能提示

为了获得最佳性能,请遵循以下建议:

  1. 保持过渡时间较短(200-300ms)
  2. 使用简单的曲线如 Curves.easeOut
  3. 避免频繁导航时使用复杂的过渡效果
  4. 使用 childBuilder 实现懒加载
  5. 在重载的小部件上使用 RepaintBoundary
context.pushTransition(
  type: PageTransitionType.fade, // 更简单的过渡更高效
  duration: Duration(milliseconds: 200),
  curve: Curves.easeOut,
  child: RepaintBoundary(
    child: HeavyWidget(),
  ),
);

示例代码

下面是一个完整的示例项目,演示了如何使用 page_transition 插件:

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

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

/// 示例应用程序
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        pageTransitionsTheme: PageTransitionsTheme(builders: {
          TargetPlatform.iOS:
              PageTransition(type: PageTransitionType.fade, child: this)
                  .matchingBuilder,
        }),
      ),
      home: MyHomePage(),
      onGenerateRoute: (settings) {
        switch (settings.name) {
          case '/second':
            return PageTransition(
              type: PageTransitionType.sharedAxisHorizontal,
              settings: settings,
              child: SecondPage(title: 'Shared Axis Horizontal'),
            );
          case '/third':
            return PageTransition(
              type: PageTransitionType.sharedAxisVertical,
              settings: settings,
              child: ThirdPage(title: 'Shared Axis Vertical'),
            );
          case '/fourth':
            return PageTransition(
              type: PageTransitionType.sharedAxisScale,
              settings: settings,
              child: FourthPage(title: 'Shared Axis Scale'),
            );
          default:
            return null;
        }
      },
    );
  }
}

/// 示例主页
class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.blue,
      appBar: AppBar(
        title: Text('Page Transition'),
      ),
      body: Center(
        child: ListView(
          padding: EdgeInsets.all(16),
          children: <Widget>[
            ElevatedButton(
              child: Text('Fade Second Page - Default'),
              onPressed: () {
                Navigator.push(
                  context,
                  PageTransition(
                    type: PageTransitionType.fade,
                    childBuilder: (context) => SecondPage(
                      title: 'Second Page from builder',
                    ),
                  ),
                );
              },
            ),
            // 其他按钮...
          ],
        ),
      ),
    );
  }
}

/// 示例第二页
class SecondPage extends StatelessWidget {
  final String? title;

  const SecondPage({super.key, this.title});

  @override
  Widget build(BuildContext context) {
    final args = ModalRoute.of(context)?.settings.arguments;
    return Scaffold(
      appBar: AppBar(
        title: Text(args as String? ?? title ?? 'Page Transition Plugin'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Text('Second Page'),
            SizedBox(height: 10),
            ElevatedButton(
              onPressed: () {
                Navigator.push(
                  context,
                  PageTransition(
                    duration: Duration(milliseconds: 300),
                    reverseDuration: Duration(milliseconds: 300),
                    type: PageTransitionType.topToBottom,
                    child: ThirdPage(
                      title: '',
                    ),
                  ),
                );
              },
              child: Text('Go Third Page'),
            )
          ],
        ),
      ),
    );
  }
}

/// 示例第三页
class ThirdPage extends StatelessWidget {
  final String? title;

  const ThirdPage({super.key, required this.title});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Page Transition Plugin"),
      ),
      body: Center(
        child: Column(
          children: [
            Text('Third Page'),
            ElevatedButton(
              onPressed: () {
                context.pushNamedTransition(
                  type: PageTransitionType.sharedAxisHorizontal,
                  routeName: '/fourth',
                  arguments: 'Fourth Page',
                );
              },
              child: Text('Go Fourth Page'),
            ),
          ],
        ),
      ),
    );
  }
}

/// 示例第四页
class FourthPage extends StatelessWidget {
  final String title;

  const FourthPage({super.key, required this.title});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Text('Fourth Page'),
      ),
    );
  }
}

这个例子展示了如何使用 page_transition 插件创建不同的页面过渡效果,并且包括了从一个页面导航到另一个页面的具体实现方式。你可以根据需要调整这些代码以适应自己的项目。


更多关于Flutter页面过渡动画插件page_transition的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter页面过渡动画插件page_transition的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter中使用page_transition插件来实现页面过渡动画的示例代码。page_transition插件提供了多种页面过渡效果,例如淡入淡出、缩放、滑动等。

首先,你需要在你的pubspec.yaml文件中添加page_transition依赖:

dependencies:
  flutter:
    sdk: flutter
  page_transition: ^2.0.0  # 请确保使用最新版本

然后运行flutter pub get来安装依赖。

接下来,下面是一个简单的示例,展示如何在两个页面之间使用不同的过渡动画。

主页面(Main Page)

import 'package:flutter/material.dart';
import 'package:page_transition/page_transition.dart';
import 'second_page.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Page Transition Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MainPage(),
    );
  }
}

class MainPage extends StatefulWidget {
  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Main Page'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.push(
              context,
              PageTransition(
                type: PageTransitionType.fade,  // 你可以更改这里的过渡类型
                child: SecondPage(),
              ),
            );
          },
          child: Text('Go to Second Page'),
        ),
      ),
    );
  }
}

第二页面(Second Page)

import 'package:flutter/material.dart';

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Second Page'),
      ),
      body: Center(
        child: Text('This is the second page!'),
      ),
    );
  }
}

过渡类型

PageTransitionType枚举提供了多种过渡类型,你可以根据需要选择:

  • fade
  • slide
  • scale
  • cupertino
  • rotate
  • default

例如,如果你想使用滑动过渡效果,只需将PageTransitionType.fade更改为PageTransitionType.slide

Navigator.push(
  context,
  PageTransition(
    type: PageTransitionType.slide,  // 使用滑动过渡效果
    child: SecondPage(),
  ),
);

这个示例展示了如何使用page_transition插件在Flutter中实现页面之间的过渡动画。你可以根据具体需求选择不同的过渡效果,以创建更丰富的用户体验。

回到顶部