猜猜微信拍一拍是怎么用Flutter实现的?

最近这个拍一拍效果挺火的啊

甚至经常有人拍熊;

介绍

其实之前我就双击过头像,但并没任何效果,估计是当时把这个拍一拍消息隐藏了的,最近才放出来的,刚好看到,才开始实现。

关于进度

目前只是先把具体的效果实现,估计过几天你看wechat_flutter项目的时候就有拍一拍消息体了,我的思路是新增消息体封装,或者把原有的进行修改,比如说文字消息体自定义下内容,然后显示的时候判断即可;

处理方式【本段来自Android_ZzT】

咱们尽量处理的跟微信官方客户端一模一样

暴力连续 「拍一拍」

连续一直双击头像会发现,只有第一次会发送信息,剩下的双击只会触发客户端行为「头像抖动」,是做了防爆处理的。大概过 10s 左右后恢复,可以再次触发

断网下「拍一拍」

断网情况下,双击头像,会发现,自己先能看到 「拍一拍」,然后过了一段时间后,会出现「因网络原因,对方可能不知道你拍了他」。这就证明是先走客户端的渲染逻辑,然后再发的网络请求,网络不好的情况下应该会经过重试过程,如果最终还是失败,则显示网络原因失败的字样

拍自己

双击自己头像,会显示「你拍了拍自己」,只是双击用户信息是自己的情况下这样显示,这没什么特别的,但是请求失败情况下的文案没太能对上,仍然显示的是「对方可能不知道你拍了他」,猜测这个文案是写在客户端的,可能要改的话又得更新版本喽

实现

其实主要用了一个动画,然后使用TweenSequence进行多组补间动画

preferredRefreshRate// 注释: API 23 之后过期,使用preferredDisplayModeId代替

然后封装成了个动画组件,组件调用了Transform来进行转动;

封装的那个组件继承了AnimatedWidget,然后调用了super把自定义的listenable 传了进去,

The preferred refresh rate for the window. // 翻译成人话:window的首选刷新率。

也算是非常简单。

代码所在位置

封装之后的代码所在

/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,   ),)

项目地址

https://github.com/fluttercandies/wechat_flutter

猜你喜欢

转载自blog.csdn.net/ajsliu1233/article/details/106904031