这篇文章主要介绍“Flutter怎么实现笑嘻嘻的动态表情”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Flutter怎么实现笑嘻嘻的动态表情”文章能帮助大家解决问题。
效果如下图所示
AnimatedContainer 介绍
在实现之前,先介绍一个新组件 —— AnimatedContainer
。看这个名字就知道和 Container
有关,实际上AnimatedContainer
是 Flutter 中的一个动画容器,Container
有的属性基本上它都有,我们看一下二者的构造方法的区别。
AnimatedContainer({ Key? key, this.alignment, this.padding, Color? color, Decoration? decoration, this.foregroundDecoration, double? width, double? height, BoxConstraints? constraints, this.margin, this.transform, this.transformAlignment, this.child, this.clipBehavior = Clip.none, Curve curve = Curves.linear, required Duration duration, VoidCallback? onEnd, });Container({ Key? key, this.alignment, this.padding, this.color, this.decoration, this.foregroundDecoration, double? width, double? height, BoxConstraints? constraints, this.margin, this.transform, this.transformAlignment, this.child, this.clipBehavior = Clip.none, });
可以看到,实际上 AnimatedContainer
和 Container
只差了3个属性,而这三个属性就是控制动画的参数:
curve
:动画曲线,默认是线性;duration
:动效时长参数;onEnd
:动效结束后的回调方法。
AnimatedContainer
的特性是所有涉及外观的属性都会生成一个过渡动效,当这些外观属性发生改变的时候就会使用生成的的动效来完成过渡,从而展现出动画效果。像我们要实现的笑嘻嘻的表情其实就是利用 AnimatedContainer
实现的。
组件结构
我们的笑嘻嘻动效,底部是一个圆形脑袋,上面有两颗眼睛和一个嘴巴,其中眼睛和嘴巴有移动动效,而眼睛的眼珠还有方向的动效。这些动效都可以使用AnimatedContainer
来实现。大的页面结构如下:
细节实现
脑袋这个很容易,直接用原型裁剪,设置尺寸和底色即可:
// 脑袋ClipOval( child: Container( width: 120, height: 120, color: Colors.blue, ),),
眼睛左眼和右眼有点不一样,眼球实际就是AnimatedContainer
使用 borderRadius
裁剪为圆形,而眼珠是AnimatedContainer
的子组件 —— 黑色的圆圈。具体实现向左或向右看使用一个变量 seeLeft
控制,而向左向右的转换过渡效果都由 AnimatedContainer
控制。
seeLeft = true
,向左看:眼珠对齐的方式是bottomLeft
,左眼纵向方向上稍微往下移一点;右眼往左移动一定的位置,这样就会有向左看的效果了;seeLeft = false
,向右看:眼珠对齐的方式是bottomRight
,右眼纵向方向上稍微往下移一点;左眼往右移动一定的位置,这样就会有向右看的效果了;
实现代码如下:
// 左眼Positioned( top: marginTop, left: marginLR, child: AnimatedContainer( alignment: seeLeft ? Alignment.bottomLeft : Alignment.bottomRight, padding: EdgeInsets.all(eyePadding), transform: Matrix4.identity() ..translate( seeLeft ? 0.0 : sideOffset, seeLeft ? eyeOffset : 0.0, 0), duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn, width: eyeSize, height: eyeSize, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(eyeSize / 2), ), child: ClipOval( child: Container( color: Colors.black, width: eyeBallSize, height: eyeBallSize, ), ), ),),// 右眼Positioned( top: marginTop, right: marginLR, child: AnimatedContainer( alignment: seeLeft ? Alignment.bottomLeft : Alignment.bottomRight, padding: EdgeInsets.all(eyePadding), transform: Matrix4.identity() ..translate(seeLeft ? -sideOffset : 0.0, seeLeft ? 0.0 : eyeOffset, 0), duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn, width: eyeSize, height: eyeSize, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(eyeSize / 2), ), child: ClipOval( child: Container( color: Colors.black, width: eyeBallSize, height: eyeBallSize, ), ), ),),
这里的眼珠对齐使用的就是AnimatedContainer
的 alignment
参数控制,而眼球的位置使用 Matrix4
的平移实现:
Matrix4.identity() ..translate(seeLeft ? -sideOffset : 0.0, seeLeft ? 0.0 : eyeOffset, 0),
笑脸的实现使用ClipPath
,绘制两条弧线就可以了,然后平移的幅度和眼珠保持一致,就可以感觉是转头的效果了,AnimatedContainer
部分的代码如下:
// 笑嘻嘻的嘴巴Positioned( bottom: 10, height: 40, left: 0, child: AnimatedContainer( alignment: seeLeft ? Alignment.bottomLeft : Alignment.bottomRight, padding: EdgeInsets.all(4.0), transform: Matrix4.identity() ..translate(seeLeft ? 25.0 : 35.0, 0, 0), duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn, child: ClipPath( clipper: SmileClipPath(), child: Container( width: 60, height: 40, color: Colors.yellow, ), ), ),),
笑嘻嘻的嘴巴的裁剪类 SmileClipPath
代码如下:
class SmileClipPath extends CustomClipper<Path> { @override Path getClip(Size size) { return Path() ..moveTo(0, 0) ..arcToPoint( Offset(size.width, 0), radius: Radius.circular(size.width * 0.55), clockwise: false, ) ..arcToPoint( Offset(0, 0), radius: Radius.circular(size.width), clockwise: true, ); } @override bool shouldReclip(covariant CustomClipper<Path> oldClipper) { return false; }}
最后,控制状态变量 seeLeft
的变化通过一个按钮点击触发就好了。
floatingActionButton: FloatingActionButton( child: Icon(Icons.play_arrow, color: Colors.white), onPressed: () { setState(() { seeLeft = !seeLeft; }); },),
最终运行效果如下,完整代码已提交至:动画相关代码。
关于“Flutter怎么实现笑嘻嘻的动态表情”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网行业资讯频道,小编每天都会为大家更新不同的知识点。