最近这个啪一啪效果挺火的啊 git
其实以前我就双击过头像,但并没任何效果,估计是当时把这个啪一啪消息隐藏了的,最近才放出来的,恰好看到,才开始实现。github
目前只是先把具体的效果实现,估计过几天你看wechat_flutter
项目的时候就有啪一啪消息体了,个人思路是新增消息体封装,或者把原有的进行修改,好比说文字消息体自定义下内容,而后显示的时候判断便可;微信
咋们尽可能处理的跟微信官方客户端如出一辙markdown
连续一直双击头像会发现,只有第一次会发送信息,剩下的双击只会触发客户端行为「头像抖动」,是作了防爆处理的。大概过 10s 左右后恢复,能够再次触发网络
断网状况下,双击头像,会发现,本身先能看到 「拍一拍」,而后过了一段时间后,会出现「因网络缘由,对方可能不知道你拍了他」。这就证实是先走客户端的渲染逻辑,而后再发的网络请求,网络很差的状况下应该会通过重试过程,若是最终仍是失败,则显示网络缘由失败的字样ide
双击本身头像,会显示「你拍了拍本身」,只是双击用户信息是本身的状况下这样显示,这没什么特别的,可是请求失败状况下的文案没太能对上,仍然显示的是「对方可能不知道你拍了他」,猜想这个文案是写在客户端的,可能要改的话又得更新版本喽学习
其实主要用了一个动画,而后使用TweenSequence进行多组补间动画动画
TweenSequence<double>([
//使用TweenSequence进行多组补间动画
TweenSequenceItem<double>(tween: Tween(begin: 0, end: 10), weight: 1),
TweenSequenceItem<double>(tween: Tween(begin: 10, end: 0), weight: 1),
TweenSequenceItem<double>(tween: Tween(begin: 0, end: -10), weight: 1),
TweenSequenceItem<double>(tween: Tween(begin: -10, end: 0), weight: 1),
])
复制代码
而后封装成了个动画组件,组件调用了Transform
来进行转动;ui
封装的那个组件继承了AnimatedWidget
,而后调用了super
把自定义的listenable
传了进去,this
class AnimateWidget extends AnimatedWidget {
final Widget child;
AnimateWidget({Animation<double> animation, this.child})
: super(listenable: animation);
@override
Widget build(BuildContext context) {
final Animation<double> animation = listenable;
var result = Transform(
transform: Matrix4.rotationZ(animation.value * pi / 180),
alignment: Alignment.bottomCenter,
child: new ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(5)),
child: this.child,
),
);
return result;
}
}
复制代码
也算是很是简单。
封装以后的代码所在
/wechat_flutter/lib/ui/view/shake_view.dart
而后项目中头像调用啪一啪的地方在
/wechat_flutter/lib/ui/message_view/msg_avatar.dart
你们能够去看下具体是怎么调用和封装的;
import 'dart:math';
import 'package:flutter/material.dart';
/// 封装以后的拍一拍
class ShakeView extends StatefulWidget {
final Widget child;
ShakeView({
this.child,
});
_ShakeViewState createState() => _ShakeViewState();
}
class _ShakeViewState extends State<ShakeView> with SingleTickerProviderStateMixin {
Animation<double> animation;
AnimationController controller;
initState() {
super.initState();
controller = AnimationController(
duration: const Duration(milliseconds: 500), vsync: this);
animation = TweenSequence<double>([
//使用TweenSequence进行多组补间动画
TweenSequenceItem<double>(tween: Tween(begin: 0, end: 10), weight: 1),
TweenSequenceItem<double>(tween: Tween(begin: 10, end: 0), weight: 1),
TweenSequenceItem<double>(tween: Tween(begin: 0, end: -10), weight: 1),
TweenSequenceItem<double>(tween: Tween(begin: -10, end: 0), weight: 1),
]).animate(controller);
controller.forward();
}
Widget build(BuildContext context) {
return AnimateWidget(animation: animation, child: widget.child);
}
dispose() {
controller.dispose();
super.dispose();
}
}
class AnimateWidget extends AnimatedWidget {
final Widget child;
AnimateWidget({Animation<double> animation, this.child})
: super(listenable: animation);
@override
Widget build(BuildContext context) {
final Animation<double> animation = listenable;
var result = Transform(
transform: Matrix4.rotationZ(animation.value * pi / 180),
alignment: Alignment.bottomCenter,
child: new ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(5)),
child: this.child,
),
);
return result;
}
}
复制代码
这个child
就是你要啪一啪以后抖动的widget内容
new ShakeView(
child: new Image.network(
'url',
height: 50,
width: 50,
fit: BoxFit.cover,
),
)
复制代码
Flutter交流QQ群:874592746
Flutter交流微信群: