美文网首页Android开发Android开发经验谈
最近很火的微信啪一啪猜猜是怎样通过Flutter实现的?

最近很火的微信啪一啪猜猜是怎样通过Flutter实现的?

作者: Android高级架构 | 来源:发表于2020-06-18 21:49 被阅读0次

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

    群里经常有人啪;

    介绍

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

    关于进度

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

    处理方式【本段来自Android_ZzT】

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

    暴力连续 「啪一啪」

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

    断网下「啪一啪」

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

    啪自己

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

    实现

    其实主要用了一个动画,然后使用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来进行转动;

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

    
    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,
       ),
    )
    复制代码
    

    项目地址

    作者:CrazyQ1
    链接:https://juejin.im/post/5eeb49a1e51d4573c91b91ab

    相关文章

      网友评论

        本文标题:最近很火的微信啪一啪猜猜是怎样通过Flutter实现的?

        本文链接:https://www.haomeiwen.com/subject/irupxktx.html