猜猜微信啪一啪是怎麼用Flutter實現的?

推薦學習項目

最近這個啪一啪效果挺火的啊 git

羣裏常常有人啪;

介紹

其實以前我就雙擊過頭像,但並沒任何效果,估計是當時把這個啪一啪消息隱藏了的,最近才放出來的,恰好看到,纔開始實現。github

關於進度

目前只是先把具體的效果實現,估計過幾天你看wechat_flutter項目的時候就有啪一啪消息體了,個人思路是新增消息體封裝,或者把原有的進行修改,好比說文字消息體自定義下內容,而後顯示的時候判斷便可;微信

處理方式【本段來自Android_ZzT】

咋們儘可能處理的跟微信官方客戶端如出一轍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交流微信羣:

相關文章
相關標籤/搜索