在Flutter的版本更新后,一个 Hero widget不能是另一个Hero widget的后代。在此情况下,可以使用 HeroController
类自定义 Hero
动画。
以下是一个使用 HeroController
自定义 Hero
动画的示例:
import 'package:flutter/material.dart';
class CustomHeroController extends HeroController {
@override
Animation createHeroAnimation(
{required String tag,
required Animation fromHero,
required Animation toHero}) {
return Tween(
begin: fromHero.value,
end: toHero.value,
).animate(CurvedAnimation(
parent: super.createHeroAnimation(tag: tag, fromHero: fromHero, toHero: toHero),
curve: Curves.easeInOut,
));
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Custom Hero'),
),
body: Center(
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailPage(),
),
);
},
child: Hero(
tag: 'hero',
createRectTween: (begin, end) {
return RectTween(
begin: begin,
end: end,
);
},
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
),
),
);
}
}
class DetailPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Detail Page'),
),
body: Center(
child: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Hero(
tag: 'hero',
createRectTween: (begin, end) {
return RectTween(
begin: begin,
end: end,
);
},
child: Container(
width: 200,
height: 200,
color: Colors.red,
),
),
),
),
);
}
}
void main() {
runApp(MaterialApp(
home: HomePage(),
theme: ThemeData(
heroController: CustomHeroController(),
),
));
}
在这个示例中,我们自定义了一个 CustomHeroController
类来处理 Hero
动画。在 CustomHeroController
中,我们重写了 createHeroAnimation
方法来创建自定义的动画。然后,我们在 main
方法中将 CustomHeroController
设置为主题数据的一部分。
在 HomePage
中,我们使用 GestureDetector
包装 Hero
,以便在点击时导航到 DetailPage
。 Hero
的 tag
属性用于标识 Hero
,以便在页面切换时进行匹配。
在 DetailPage
中,我们也使用了一个 GestureDetector
包装 Hero
,并使用相同的 tag
属性。这样,在页面切换时,Hero
将根据 CustomHeroController
中定义的动画进行过渡。
这样,我们就成功地解决了Flutter版本更新后 Hero
的后代问题,并自定义了 Hero
的动画效果。