跨页面切换的动效 Widget (Hero animations)
在页面跳转过程中给用户加以引导是非常有用的。实现引导的一种通用做法是在页面切换时为某个组件加上转场动画,从而在两个页面间建立视觉上的锚定关联。
It’s often helpful to guide users through an app as they navigate from screen to screen. A common technique to lead users through an app is to animate a widget from one screen to the next. This creates a visual anchor connecting the two screens.
在 Flutter 中,可以通过 Hero
widget 实现页面切换时组件的转场动画。
Use the Hero
widget
to animate a widget from one screen to the next.
这个教程将包含以下步骤:
This recipe uses the following steps:
-
创建两个页面,展示相同的图片
Create two screens showing the same image.
-
在第一个页面中加入
Hero
组件Add a
Hero
widget to the first screen. -
在第二个页面中加入
Hero
组件Add a
Hero
widget to the second screen.
1. 创建两个页面,展示相同的图片
1. Create two screens showing the same image
在这个示例中,将在两个页面中展示相同的图片。当用户在第一个页面点击图片,会通过一个转场动画切换到第二个页面。现在,我们将会创建页面的视觉结构,并在后续步骤中处理动画。
In this example, display the same image on both screens. Animate the image from the first screen to the second screen when the user taps the image. For now, create the visual structure; handle animations in the next steps.
class MainScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Main Screen'),
),
body: GestureDetector(
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return DetailScreen();
}));
},
child: Image.network(
'https://picsum.photos/250?image=9',
),
),
);
}
}
class DetailScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Center(
child: Image.network(
'https://picsum.photos/250?image=9',
),
),
),
);
}
}
Hero
组件
2. 在第一个页面中加入
Hero
widget to the first screen
2. Add a 为了通过动画在两个页面间建立联系,需要把每个页面的 Image
组件都包裹进 Hero
组件里面。
Hero
组件有两个参数:
To connect the two screens together with an animation, wrap
the Image
widget on both screens in a Hero
widget.
The Hero
widget requires two arguments:
- `tag`
-
作为 `Hero` 组件的标识,在这两个页面中必须相同。
An object that identifies the `Hero`. It must be the same on both screens.
- `child`
-
在两个屏幕直接跨越的那个 widget。
The widget to animate across screens.
Hero(
tag: 'imageHero',
child: Image.network(
'https://picsum.photos/250?image=9',
),
);
Hero
组件
3. 在第二个页面中加入
Hero
widget to the second screen
3. Add a 为了完善与第一个页面的关联,同样需要把第二个页面中的 Image
组件包裹进 Hero
组件里面。它的 tag
也必须和第一个页面相同。
To complete the connection with the first screen,
wrap the Image
on the second screen with a Hero
widget that has the same tag
as the Hero
in the first screen.
当 Hero
组件被应用到第二个页面后,页面的转场动画就生效了。
After applying the Hero
widget to the second screen,
the animation between screens just works.
Hero(
tag: 'imageHero',
child: Image.network(
'https://picsum.photos/250?image=9',
),
);
交互式样例
Interactive example
import 'package:flutter/material.dart';
void main() => runApp(HeroApp());
class HeroApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Transition Demo',
home: MainScreen(),
);
}
}
class MainScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Main Screen'),
),
body: GestureDetector(
child: Hero(
tag: 'imageHero',
child: Image.network(
'https://picsum.photos/250?image=9',
),
),
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return DetailScreen();
}));
},
),
);
}
}
class DetailScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
child: Center(
child: Hero(
tag: 'imageHero',
child: Image.network(
'https://picsum.photos/250?image=9',
),
),
),
onTap: () {
Navigator.pop(context);
},
),
);
}
}