最近這個啪一啪效果挺火的啊 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交流微信羣: