100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > Android 仿斗鱼 映客 礼物打赏 包括连击 追加等功能

Android 仿斗鱼 映客 礼物打赏 包括连击 追加等功能

时间:2023-11-22 15:26:47

相关推荐

Android 仿斗鱼 映客 礼物打赏 包括连击 追加等功能

Android 仿斗鱼、映客 礼物打赏

公司之前需要对直播功能添加打赏模块,我把自己的方法以及参考的demo分享出来。

参考demo:/Qiang3570/LiveLayout点击打开链接

在这个demo中让我最受启发的是它使用给View添加tag的方式,来区别view。但它没有礼物的连击,追加等功能,在此我对它做了完善,使之成为一个可直接用到商业直播的demo。

首先我们需要实现什么功能呢?礼物从左边滑出,做一个连击数字的动画,然后停留2-3秒后,再消失。其中需要注意的点有以下几个:

1.收到礼物的消息后,因为礼物同时只能展示3个左右,为防止消息丢失,我们需要做一个消息队列来缓存这些消息,定时来遍历消息队列。(定时器、集合)。

2.数字的连击动画。

3.当这个礼物view 正处于“连击”中 或者 连击完成但还未消失的这2-3秒内,用户又送了一次礼物,我们需要做一个追加。

我是使用一个model AnimMessage 来承载一个礼物消息的全部信息,包括送礼物的用户名,礼物数量,礼物名,动画活跃时间,是否连击完成等。

对于问题1.使用list 来作为消息队列,使用计时器来定时清除当前已展示完毕的view,并从队列中取出消息、添加新的view。

private static void startTimer() {mGiftClearTimer = new Timer();mGiftClearTimer.schedule(new TimerTask() {@Overridepublic void run() {final int count = mAnimViewContainer.getChildCount();// 清除礼物for (int i = 0; i < count; i++) {View view = mAnimViewContainer.getChildAt(i);AnimMessage message = (AnimMessage) view.getTag();long nowTime = System.currentTimeMillis();long upTime = message.getUpdateTime();if ((nowTime - upTime) >= mGiftClearInterval) {removeAnimalView(i);return;}}// 添加礼物if (count < mGiftMaxNumber) {if (mGiftList.size() > 0) {((Activity) mContext).runOnUiThread(new Runnable() {@Overridepublic void run() {startGiftAnim(mGiftList.get(0));mGiftList.remove(0);}});}}}}, 0, mGiftClearTimerInterval);}

uptime是指这个view的最后活跃时间,它需要不断的更新,但是更新的频率不得小于定时器的间隔,否则会被当做已展示完毕的view被清除掉。

对于问题2. 我则是采用的上述demo中的属性动画,做了一些修改,具体看下面代码。

对于问题3. 我们需要先检查后面的礼物消息在当前的展示中是否已有对应的view存在,如果没有,则直接重建,如果已经存在,则是需要更新AnimMessage中的礼物数量,来达到追加的目的,代码如下:

private static void startGiftAnim(final AnimMessage giftMessage) {View giftView = findViewByMessage(giftMessage);if (giftView == null) {//该用户不在礼物显示列表 或者又送了一个新的礼物giftView = addAnimalView(giftMessage);mAnimViewContainer.addView(giftView);/*将礼物的View添加到礼物的ViewGroup中*/mAnimViewContainer.invalidate();} else {//该用户在礼物显示列表 1. 连击动画还未结束,只更新message即可final AnimMessage message = (AnimMessage) giftView.getTag();// 原来的礼物view的信息message.setGiftNum(message.getGiftNum() + giftMessage.getGiftNum()); // 合并追送的礼物数量giftView.setTag(message);if (message.isComboAnimationOver()) {// 2.连击动画已完成 此时view 未消失,除了1 的操作外,还需重新启动连击动画final MagicTextView giftNum = (MagicTextView) giftView.findViewById(R.id.giftNum);giftNum.setText("x" + giftNum.getTag());((LPGiftView) giftView).startComboAnim(giftNum);}}}

private static View findViewByMessage(AnimMessage message) {for (int i = 0; i < mAnimViewContainer.getChildCount(); i++) {AnimMessage giftMessage = (AnimMessage) mAnimViewContainer.getChildAt(i).getTag();if (giftMessage.getUserName().equals(message.getUserName()) &&giftMessage.getGiftName().equals(message.getGiftName())) {return mAnimViewContainer.getChildAt(i);}}return null;}

通过findViewByMessage 方法来找到当前展示的礼物中是否有对应的view,如果没有则重建,如果有,则分两种情况(1)正处于连击中,只需要更新礼物上限,即message.setGiftNum 即可。(2)礼物连击完毕,连击动画已停止,这时候除了更新礼物上限外,还需要重启下连击动画。

public void startComboAnim(final View giftNumView) {ObjectAnimator anim1 = ObjectAnimator.ofFloat(giftNumView, "scaleX", 1.8f, 1.0f);ObjectAnimator anim2 = ObjectAnimator.ofFloat(giftNumView, "scaleY", 1.8f, 1.0f);AnimatorSet animSet = new AnimatorSet();animSet.setDuration(300);animSet.setInterpolator(new OvershootInterpolator());animSet.playTogether(anim1, anim2);animSet.start();animSet.addListener(new Animator.AnimatorListener() {@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {((AnimMessage) getTag()).setUpdateTime(System.currentTimeMillis());//设置时间标记giftNumView.setTag((Integer) giftNumView.getTag() + 1);//这里用((GiftMessage)giftView.getTag()) 来实时的获取GiftMessage 便于礼物的追加if ((Integer) giftNumView.getTag() <= ((AnimMessage) getTag()).getGiftNum()) {((MagicTextView) giftNumView).setText("x" + giftNumView.getTag());startComboAnim(giftNumView);} else {((AnimMessage)getTag()).setComboAnimationOver(true);return;}}@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationRepeat(Animator animation) {}});}

上面代码可以看到,我们在每次执行完一次连击后,来判断是否达到数目的要求,类似一个while循环,如果执行完毕,则将执行完毕的变量设置为true 即可,否则不断的执行动画。

最后就是移除问题了,当这个view 已经不活跃,并且被定时器检查到后,将其移除,另外如果队列中已经没有礼物消息的时候,要定时器停止,在添加消息的时候,再将之重建。

private static void removeAnimalView(final int index) {if (index >= mAnimViewContainer.getChildCount()) {return;}final View removeView = mAnimViewContainer.getChildAt(index);mGiftLayoutOutAnim.setAnimationListener(new Animation.AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {new Handler().post(new Runnable() {@Overridepublic void run() {mAnimViewContainer.removeViewAt(index);}});if (mGiftList.size() == 0 && mAnimViewContainer.getChildCount() == 0 && mGiftClearTimer != null) {mGiftClearTimer.cancel();mGiftClearTimer = null;}}@Overridepublic void onAnimationRepeat(Animation animation) {}});((Activity) mContext).runOnUiThread(new Runnable() {@Overridepublic void run() {removeView.startAnimation(mGiftLayoutOutAnim);}});}

大致就是这些了,至此礼物全部功能已经完毕了,由于我是封装在一个manager 静态类里面,所以为了防止内存泄漏,最后需要对context释放。

最后来几张效果图吧

源码地址:/ahaCloud/LiveRewardGift-master 源码地址 ,第一次写东西,如有错误欢迎指正,求收藏

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。