๐ Swipe to navigate back and admire beautifully morphing widgets.
SwipeablePageRoute
is a specialized CupertinoPageRoute
that allows your users to go back by swiping anywhere on the current page. Use it instead of MaterialPageRoute
or CupertinoPageRoute
:
Navigator.of(context).push(SwipeablePageRoute(
builder: (BuildContext context) => MyPageContent(),
));
If your page contains horizontally scrollable content, you can limit SwipeablePageRoute
to only react on drags from the start (left in LTR, right in RTL) screen edgeโโโjust like CupertinoPageRoute
:
Navigator.of(context).push(SwipeablePageRoute(
canOnlySwipeFromEdge: true,
builder: (BuildContext context) => MyHorizontallyScrollablePageContent(),
));
You can get the SwipeablePageRoute
wrapping your current page using context.getSwipeablePageRoute<T>()
.
To use swipeable pages with a
PageTransitionsTheme
, useSwipeablePageTransitionsBuilder
.
โ ๏ธ SwipeablePageTransitionsBuilder
must be set forTargetPlatform.iOS
. For all other platforms, you can decide whether you want to use it. This is becausePageTransitionsTheme
uses the builder for iOS whenever a pop gesture is in progress.
To use swipeable pages with Flutter's Go Router, use SwipeablePage
and the pageBuilder
parameter in GoRoute
instead of builder
:
// Before, without swipeable pages:
GoRoute(
builder: (context, state) => const MyScreen(),
// ...
)
// After, with swipeable pages:
GoRoute(
pageBuilder: (context, state) => SwipeablePage(
builder: (context) => MyScreen(),
),
// ...
)
As you can see in the demo above, there's a beautiful animation happening to the app bar. That's a MorphingAppBar
!
You can construct MorphingAppBar
(corresponds to AppBar
) and MorphingSliverAppBar
(corresponds to SliverAppBar
) just like the originals:
MorphingAppBar(
backgroundColor: Colors.green,
title: Text('My Page'),
actions: [
IconButton(
key: ValueKey('play'),
icon: Icon(Icons.play_arrow),
onPressed: () {},
),
IconButton(
key: ValueKey('favorite'),
icon: Icon(Icons.favorite),
onPressed: () {},
),
PopupMenuButton<void>(
key: ValueKey('overflow'),
itemBuilder: (context) => [
PopupMenuItem<void>(child: Text('Overflow action 1')),
PopupMenuItem<void>(child: Text('Overflow action 2')),
],
),
],
bottom: TabBar(tabs: [
Tab(text: 'Tab 1'),
Tab(text: 'Tab 2'),
Tab(text: 'Tab 3'),
]),
)
Both MorphingAppBar
s internally use Hero
s, so if you're not navigating directly inside a MaterialApp
, you have to add a HeroController
to your Navigator
:
Navigator(
observers: [HeroController()],
onGenerateRoute: // ...
)
To animate additions, removals, and constants in your AppBar
s actions
, we compare them using Widget.canUpdate(Widget old, Widget new)
. It compares Widget
s based on their type and key
, so it's recommended to give every action Widget
a key (that you reuse across pages) for correct animations.