发布网友 发布时间:2024-10-08 01:39
共1个回答
热心网友 时间:2024-10-17 06:50
我们经常看到一些APP在从列表点击进入到详情时会有一个图片放大的渐变效果,不像是页面的跳转。给用户一种无缝切换的感觉。这种效果通常称为共享元素转换动画,那么它在Flutter中是如何实现呢?
其实Flutter中官方给我们提供了非常好用的控件:Hero。
Hero中文网给出的定义是:Hero指的是可以在路由(页面)之间“飞行”的widget。将hero从一个路由飞到另一个路由。
hero动画代码应该具有以下结构:
1.定义一个起始herowidget,称为"源hero"。hero指定其图形表示(通常是图片)和识别标记,并且位于源路由定义的当前显示的widget树中。
2.定义一个结束的herowidget,称为"目标hero"。这位hero也指定了它的图形表示,以及与源hero相同的标记。重要的是两个herowidget都使用相同的标签创建,通常是代表底层数据的对象。为了获得最佳效果,hero应该有几乎相同的widget树。
3.创建一个包含目标hero的路由。目标路由定义了动画结束时的widget树。
4.通过导航器将目标路由入栈来触发动画。Navigator推送和弹出操作会为每对hero配对,并在源路由和目标路由中使用匹配的标签触发hero动画。
5.Flutter计算从起点到终点对hero界限进行动画处理的补间(生成每一帧大小和位置),并在叠加层中执行动画。
根据要求及定义就可以直接撸代码了,很简单:
首先是第一个界面:Widgetbuild(BuildContextcontext){returnScaffold(body:Center(child:Column(mainAxisSize:MainAxisSize.min,children:<Widget>[InkWell(onTap:(){Navigator.push(context,MaterialPageRoute(builder:(context){returnSecondHeroPage(tag:"tag",imageUrl:imageUrl,);}));},child:Hero(tag:"tag",child:Image.network(imageUrl,width:200,height:200,)),),Text("点击图片跳转")],),),);}第二个界面Widgetbuild(BuildContextcontext){returnScaffold(body:Column(children:<Widget>[InkWell(onTap:(){Navigator.of(context).pop();//这里pop后也是有动画的},child:Hero(tag:widget.tag,child:Image.network(widget.imageUrl,width:double.infinity,height:500,fit:BoxFit.fill,)),),Text("点击图片返回")],),);}HeroMode有一些场景,比如单数的图片需要过渡动画,双数的不需要,那么如何处理呢,Flutter中也提供了解决办法就是HeroMode,给Hero嵌套HeroMode组件后可以通过设置enabled属性,当其值为false时,hero动画就会失效。
HeroMode(enabled:isNeedHero,child:Hero(tag:"tag",child:Image.network(imageUrl,width:200,height:200,)),)注意这里的tag一定要和第一个界面Hero中的tag一致
总的来说,这个效果实现起来非常简单的,但是用到实际项目中呈现出的用户体验会非常好!
代码地址