跨页面切换的动效 Widget (Hero animations)
在页面跳转过程中给用户加以引导是非常有用的。实现引导的一种通用做法是在页面切换时为某个组件加上转场动画,从而在两个页面间建立视觉上的锚定关联。
在 Flutter 中,可以通过 Hero
widget 实现页面切换时组件的转场动画。
这个教程将包含以下步骤:
-
创建两个页面,展示相同的图片
-
在第一个页面中加入
Hero
组件 -
在第二个页面中加入
Hero
组件
1. 创建两个页面,展示相同的图片
#在这个示例中,将在两个页面中展示相同的图片。当用户在第一个页面点击图片,会通过一个转场动画切换到第二个页面。现在,我们将会创建页面的视觉结构,并在后续步骤中处理动画。
dart
import 'package:flutter/material.dart';
class MainScreen extends StatelessWidget {
const MainScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Main Screen'),
),
body: GestureDetector(
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return const DetailScreen();
}));
},
child: Image.network(
'https://picsum.photos/250?image=9',
),
),
);
}
}
class DetailScreen extends StatelessWidget {
const DetailScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Center(
child: Image.network(
'https://picsum.photos/250?image=9',
),
),
),
);
}
}
2. 在第一个页面中加入 Hero
组件
#
为了通过动画在两个页面间建立联系,需要把每个页面的 Image
组件都包裹进 Hero
组件里面。
Hero
组件有两个参数:
tag
作为 Hero
组件的标识,在这两个页面中必须相同。
child
在两个屏幕直接跨越的那个 widget。
dart
Hero(
tag: 'imageHero',
child: Image.network(
'https://picsum.photos/250?image=9',
),
)
3. 在第二个页面中加入 Hero
组件
#
为了完善与第一个页面的关联,同样需要把第二个页面中的 Image
组件包裹进 Hero
组件里面。它的 tag
也必须和第一个页面相同。
当 Hero
组件被应用到第二个页面后,页面的转场动画就生效了。
dart
Hero(
tag: 'imageHero',
child: Image.network(
'https://picsum.photos/250?image=9',
),
)
交互式样例
#import 'package:flutter/material.dart';
void main() => runApp(const HeroApp());
class HeroApp extends StatelessWidget {
const HeroApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Transition Demo',
home: MainScreen(),
);
}
}
class MainScreen extends StatelessWidget {
const MainScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Main Screen'),
),
body: GestureDetector(
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return const DetailScreen();
}));
},
child: Hero(
tag: 'imageHero',
child: Image.network(
'https://picsum.photos/250?image=9',
),
),
),
);
}
}
class DetailScreen extends StatelessWidget {
const DetailScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Center(
child: Hero(
tag: 'imageHero',
child: Image.network(
'https://picsum.photos/250?image=9',
),
),
),
),
);
}
}
除非另有说明,本文档之所提及适用于 Flutter 的最新稳定版本,本页面最后更新时间: 2024-07-03。 查看文档源码 或者 为本页面内容提出建议。