Originally published on bendyworks.com.
For the last post before the month's wrap up tomorrow, I wanted to do something more fun: use a hero animationbetween the home page list and the individual post page.
When I first implemented the
Hero
animation it never worked going back from a PostPage
to the HomePage
. The reason was that HomePage
would get rerendered and that would generate new fake posts. So I moved the fake data generation up a level to MyApp
and pass it into HomePage
. This is more realistic as going to the HomePage
shouldn't request the Post
s every time.HomePage(
title: 'Birb',
posts: _loadPosts(context),
)
The
PostPage
implementation is a simple StatelessWidget
that takes Post
and renders a PostItem
. This will become more complex as things like comments and likes are implemented but works for now.class PostPage extends StatelessWidget {
const PostPage({
Key key,
@required this.post,
}) : super(key: key);
final Post post;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Post'),
centerTitle: true,
elevation: 0.0,
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 8.0),
child: PostItem(post),
),
),
);
}
}
With
PostItem
being used to render on the HomePage
and on the PostPage
, wrapping the Image
in a Hero
is handled in a single place. tag
is how Hero
knows what to transition between pages.Hero(
tag: post.id,
child: ClipRRect(
child: Image.network(post.imageUrl),
borderRadius: BorderRadius.circular(10.0),
),
)
The last piece is navigating from
PostList
to PostPage
when a user taps on a PostItem
. I'll handle this with an InkWell
widget so there is a nice Material ripple.InkWell(
onTap: () => _navigateToPost(context, post),
child: PostItem(post),
)
The navigation is more complex then opening the registration page for two reasons. Named routes don't support parameters and I wanted a simple transitionbetween the rest of the content on the page.
void _navigateToPost(BuildContext context, Post post) {
Navigator.of(context).push(
PageRouteBuilder<PostPage>(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) {
return PostPage(post: post);
},
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
return FadeTransition(
opacity: animation,
child: child,
);
},
),
);
}
Here I will
push
a PageRouteBuilder
onto the navigation stack. PageRouteBuilder
has two key builders in use here. pageBuilder
builds the widget that should be rendered as the new page and transitionBuilder
specifies how to transition between the old and new pages. Note that this FadeTransition
is not related to implementing Hero
earlier.
The tests for
PostPage
is simple and just checking that PostItem
is rendered. I did update the PostItem
test to expect that its Hero
widget had the correct tag
value.expect(tester.widget<Hero>(hero).tag, post.id);
The navigation and animation from
PostsList
to PostPage
is now doing more work so I replaced several pump
pauses with pumpAndSettle
.
Here is the fancy
Hero
animation:
Code changes
Comments
Post a Comment