Skip to content

kalismeras61/flutter_page_transition

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Flutter Page Transition Package

A Flutter package that provides beautiful page transitions with an easy-to-use API.

flutter platform pub package BSD-2-Clause

Installation

dependencies:
  page_transition: ^latest_version

Usage

Using Extensions (Recommended)

// Simple transition
context.pushTransition(
  type: PageTransitionType.fade,
  child: DetailScreen(),
);

// Using builder pattern
context.pushTransition(
  type: PageTransitionType.fade,
  childBuilder: (context) => DetailScreen(
    id: someId,
    title: someTitle,
  ),
);

// Push replacement
context.pushReplacementTransition(
  type: PageTransitionType.rightToLeft,
  child: DetailScreen(),
);

// Push and remove until
context.pushAndRemoveUntilTransition(
  type: PageTransitionType.fade,
  child: HomePage(),
  predicate: (route) => false,
);

// Named route with transition
context.pushNamedTransition(
  routeName: '/detail',
  type: PageTransitionType.fade,
  arguments: {'id': 1},
);

Traditional Usage

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

// Or using builder pattern
Navigator.push(
  context,
  PageTransition(
    type: PageTransitionType.fade,
    childBuilder: (context) => DetailScreen(id: someId),
  ),
);

Using with Route Generation (GoRouter, AutoRoute, etc.)

MaterialApp(
  onGenerateRoute: (settings) {
    switch (settings.name) {
      case '/details':
        return PageTransition(
          type: PageTransitionType.rightToLeftJoined,
          childCurrent: context.currentRoute, // Get current route widget
          child: DetailsPage(),
          settings: settings,
        );

      case '/shared-axis':
        // Example of shared axis transition
        return PageTransition(
          type: PageTransitionType.rightToLeftJoined,
          childCurrent: context.currentRoute,
          child: SharedAxisPage(),
          settings: settings,
          curve: Curves.easeInOut,
          duration: Duration(milliseconds: 400),
        );
    }
  },
);

Using with 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),
        );
      },
    ),
  ],
);

Using with AutoRoute

First, define your routes:

@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 {}

Then use it in your app:

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

// Navigate using AutoRoute
context.router.push(DetailsRoute(id: 123)); // Will use shared axis horizontal
context.router.push(const ProfileRoute()); // Will use shared axis vertical

Using with Navigation 2.0 (Router)

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

Additional Features

iOS Swipe Back

Enable iOS-style swipe back gesture:

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

Note: iOS swipe back works only with rightToLeft and fade transitions.

Inherit Theme

Use the parent's theme in the transition:

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

Custom Duration and Curve

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

Advanced Usage

Shared Axis Transitions

Material Design 3 style shared axis transitions:

// Horizontal shared axis
context.pushTransition(
  type: PageTransitionType.sharedAxisHorizontal,
  child: DetailScreen(),
  duration: Duration(milliseconds: 400),
  curve: Curves.easeInOut,
);

// Vertical shared axis
context.pushTransition(
  type: PageTransitionType.sharedAxisVertical,
  child: DetailScreen(),
);

// Scale shared axis
context.pushTransition(
  type: PageTransitionType.sharedAxisScale,
  child: DetailScreen(),
);

Nested Navigation with Named Routes

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(),
        );
    }
  },
);

// Navigate using extensions
context.pushNamedTransition(
  routeName: '/details',
  type: PageTransitionType.sharedAxisHorizontal,
  arguments: {'id': 123},
);

Using with 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),
        );
      },
    ),
  ],
);

Using with AutoRoute

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),
        );
      },
    ),
  ],
);

Using with Navigation 2.0 (Router)

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

Resources

Video Tutorial

Check out Johannes Milke's tutorial for a detailed walkthrough.

Contributing

Pull requests are welcome! For major changes, please open an issue first to discuss what you would like to change.

License

BSD 2-Clause

Performance Tips

For optimal performance:

  1. Keep transition durations short (200-300ms)
  2. Use simpler curves like Curves.easeOut
  3. Avoid complex transitions for frequent navigation
  4. Consider using childBuilder for lazy widget construction
  5. Use RepaintBoundary on heavy widgets being transitioned
context.pushTransition(
  type: PageTransitionType.fade, // Simpler transitions are more performant
  duration: Duration(milliseconds: 200),
  curve: Curves.easeOut,
  child: RepaintBoundary(
    child: HeavyWidget(),
  ),
);