介绍
公司的项目中包含 IM 模块,其中包含红包功能,在做打开红包的时候,觉得打开的按钮若不旋转感觉太过单调,没有乐趣,所以参考微信的红包,打开的时候,"开" 字旋转起来.这里主要用的是帧动画,先上效果图:
旋转动画的实现
一开始做的时候使用的是 AnimationDrawable,定义 animation-list,,尽管可以实现如上的结果,但是发现动画并没有特别流畅,有些卡顿,最后在 github 上找到了 FrameAnimation , 其设计思路是将图片资源用数组存储,然后通过设定的周期,遍历切换,这样在性能上比使用 AnimationDrawable 高,消耗内存较小,动画也相对比较流畅.
FrameAnimation 的使用
定义图片资源的数组
每一帧为按钮不同角度的图片
private int[] mImgResIds = new int[] {
R.mipmap.icon_open_red_packet1,
R.mipmap.icon_open_red_packet2,
R.mipmap.icon_open_red_packet3,
R.mipmap.icon_open_red_packet4,
R.mipmap.icon_open_red_packet5,
R.mipmap.icon_open_red_packet6,
R.mipmap.icon_open_red_packet7,
R.mipmap.icon_open_red_packet7,
R.mipmap.icon_open_red_packet8,
R.mipmap.icon_open_red_packet9,
R.mipmap.icon_open_red_packet4,
R.mipmap.icon_open_red_packet10,
R.mipmap.icon_open_red_packet11,
};
创建 FrameAnimation 对象
FrameAnimation 中可以设置对执行动画时某些时机的监听.
mFrameAnimation = new FrameAnimation(mIvOpen, mImgResIds, 125, true);
mFrameAnimation.setAnimationListener(new FrameAnimation.AnimationListener() {
@Override
public void onAnimationStart() {
Log.i("", "start");
}
@Override
public void onAnimationEnd() {
Log.i("", "end");
}
@Override
public void onAnimationRepeat() {
Log.i("", "repeat");
}
@Override
public void onAnimationPause() {
mIvOpen.setBackgroundResource(R.mipmap.icon_open_red_packet1);
}
});
弹框中按钮的点击监听
回调给 OnRedPacketDialogClickListener 接口, 当点击弹框的打开按钮时,如果已经在旋转,则无需再进行旋转.
@OnClick({R.id.iv_close, R.id.iv_open})
public void onClick(View view) {
switch (view.getId()) {
case R.id.iv_close:
stopAnim();
if (mListener != null) {
mListener.onCloseClick();
}
break;
case R.id.iv_open:
if (mFrameAnimation != null) {
//如果正在转动,则直接返回
return;
}
startAnim();
if (mListener != null) {
mListener.onOpenClick();
}
break;
}
}
Activity 中弹出红包弹框
点击按钮后的相关业务逻辑,可以在 onOpenClick() 回调中实现.
public void showDialog(View view){
RedPacketEntity entity = new RedPacketEntity("chaychan", "http://upload.51qianmai.com/20171205180511192.png", "大吉大利,今晚吃鸡");
showRedPacketDialog(entity);
}
public void showRedPacketDialog(RedPacketEntity entity) {
if (mRedPacketDialogView == null) {
mRedPacketDialogView = View.inflate(this, R.layout.dialog_red_packet, null);
mRedPacketViewHolder = new RedPacketViewHolder(this, mRedPacketDialogView);
mRedPacketDialog = new CustomDialog(this, mRedPacketDialogView, R.style.custom_dialog);
mRedPacketDialog.setCancelable(false);
}
mRedPacketViewHolder.setData(entity);
mRedPacketViewHolder.setOnRedPacketDialogClickListener(new OnRedPacketDialogClickListener() {
@Override
public void onCloseClick() {
mRedPacketDialog.dismiss();
}
@Override
public void onOpenClick() {
//领取红包,调用接口
}
});
mRedPacketDialog.show();
}
对 FrameAnimation 的修改
FrameAnimation 并没有回调动画暂停的监听,我们在打开红包成功或者请求失败(网络异常)时,按钮应暂停旋转,此时需要监听到暂停,在回调中将图片切换为第一帧.
来源: https://juejin.im/post/5a58638ef265da3e38496ec3