在 Flutter 中,图像从当前页面转到另一个页面称为 hero 动画,相同的动作有时也被称为 共享元素过渡。
hero 动画基本结构
- 在不同页面分别使用两个 hero widgets,同时使用配对的标签来实现动画
- Navigator 管理含有 app 页面的堆栈。
- 推送一个页面或弹出一个 Navigator 堆栈中的页面会触发动画。
- Flutter 框架设置了一个
RectTween
类,用来定义 hero 从原页面飞至目标页面的边界。在飞翔过程中,hero 移动到一个应用图层,这样它可以在两个页面上方显示。
Hero 动画需要使用两个 Hero
widgets 来实现:一个用来在原页面中描述 widget,另一个在目标页面中描述 widget。从用户角度来说,hero 似乎是分享的,只有程序员需要了解实施细节。
标准 hero 动画
- 使用 MaterialPageRoute,CupertinoPageRoute 指定页面,或使用 PageRouteBuilder 创建自定义页面。
- 在过渡的最后,通过在
SizedBox
中裹挟目标图像来改变图像大小。 - 通过在布局 widget 中放置目标图像来改变图像位置。
PhotoHero 类
自定义的 PhotoHero 类保留了 hero 以及其大小,图像,和点击时的动作。
import 'package:flutter/material.dart';
class PhotoHero extends StatelessWidget {
const PhotoHero({
super.key,
required this.width,
this.height,
required this.imageUrl,
this.onTap,
});
final double width;
final double? height;
final String imageUrl;
final VoidCallback? onTap;
@override
Widget build(BuildContext context) {
return Container(
width: width,
height: height,
color: Colors.transparent,
child: Hero(
tag: imageUrl,
child: Material(// Provides a canvas for the InkWell's splash during Hero's flight. Otherwise, the splash would be left behind.
child: InkWell(
onTap: onTap,
child: Image.asset(
imageUrl,
fit: BoxFit.cover,
),
),
),
),
);
}
}
hero_page.dart
import 'package:flutter/material.dart';
import '../components/photo_hero.dart';
class HeroPage extends StatelessWidget {
const HeroPage({super.key});
static const url =
'images/products/O1CN01yvMCj11GkmaVukfRK_!!2652950661.jpg_Q75.jpg';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('HeroPage'),
),
body: Center(
child: PhotoHero(
width: 60,
height: 60,
imageUrl: url,
onTap: () {
Navigator.pushNamed(context, '/herophoto', arguments: url);
},
),
),
);
}
}
hero_photo.dart
import 'package:flutter/material.dart';
import '../components/photo_hero.dart';
class HeroPhoto extends StatelessWidget {
final String url;
const HeroPhoto({super.key, required this.url});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('HeroPhoto'),
),
body: Container(
color: Colors.transparent,
padding: const EdgeInsets.all(16),
alignment: Alignment.center,
child: PhotoHero(
width: 300,
height: 300,
imageUrl: url,
onTap: () {
Navigator.pop(context);
},
),
),
);
}
}
标签:动画,const,dart,PhotoHero,hero,Flutter,页面
From: https://www.cnblogs.com/angelwgh/p/17926430.html