Android 弹幕功能实现

编程入门 行业动态 更新时间:2024-10-26 21:33:13

Android 弹幕<a href=https://www.elefans.com/category/jswz/34/1771378.html style=功能实现"/>

Android 弹幕功能实现

直接上代码: 

工具类

import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;import java.util.List;/*** 弹幕视图,使用属性动画*/
public class BarrageView extends FrameLayout {private String Tag = BarrageView.class.getSimpleName();private final int CODE_START = 1000;private final int CODE_NEXT = 1001;private final int CODE_END = 1002;//数据源private List<?> datas;private ViewHolder viewHolder;//控件宽private int barrageViewWidth;//控件高private int barrageViewHeight;//弹幕行数private int displayLines = 10;//是否循环显示private boolean isRepeat = true;//动画时间private long animationTime = 6 * 1000L;//两条弹幕最小间隔时间private long minIntervalTime = 1000L;//两条弹幕最大间隔时间private long maxIntervalTime = 3000L;//大当前弹幕索引private int currentIndex;//弹幕状态private boolean isStart;//上一次出现的行数private int lastLine = -1;@SuppressLint("HandlerLeak")private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case CODE_START:handler.sendEmptyMessage(CODE_NEXT);break;case CODE_NEXT:if (isStart && datas != null && currentIndex < datas.size()) {addView();currentIndex++;long interval = maxIntervalTime - minIntervalTime;long randomSleepTime =  minIntervalTime + (long)(interval > 0 ? Math.random() * interval : 0);handler.sendEmptyMessageDelayed(CODE_NEXT, randomSleepTime);} else {handler.sendEmptyMessage(CODE_END);}break;case CODE_END:Log.d(Tag, "CODE_END");if (isRepeat) {if (currentIndex != 0) {currentIndex = 0;handler.sendEmptyMessage(CODE_NEXT);}}break;}}};private LinearInterpolator linearInterpolator;public BarrageView(Context context, AttributeSet attrs) {super(context, attrs);}private void addView() {final View itemView = viewHolder.getItemView(getContext(), datas.get(currentIndex), currentIndex);addView(itemView);itemView.setY(getItemRandomY());itemView.measure(0, 0);int itemViewWidth = itemView.getMeasuredWidth();itemView.setX(this.barrageViewWidth);if (linearInterpolator == null) {linearInterpolator = new LinearInterpolator();}final ObjectAnimator anim = ObjectAnimator.ofFloat(itemView, "translationX", -itemViewWidth);anim.setDuration(animationTime);anim.setInterpolator(linearInterpolator);//释放资源anim.addListener(new Animator.AnimatorListener() {@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {anim.cancel();itemView.clearAnimation();removeView(itemView);}@Overridepublic void onAnimationCancel(Animator animation) {itemView.clearAnimation();removeView(itemView);}@Overridepublic void onAnimationRepeat(Animator animation) {}});anim.start();}/*** 获得随机的Y轴的值*/private float getItemRandomY() {//随机选择弹幕出现的行数位置,跟上一条位置不同行int randomLine = lastLine;if (displayLines > 1) {while (randomLine == lastLine) {randomLine = (int) (Math.random() * displayLines + 1);}}lastLine =randomLine ;//当前itemView y值return (float) (barrageViewHeight*1.0 / displayLines * (randomLine - 1));}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);barrageViewWidth = getWidth();barrageViewHeight = getHeight();}private int dip2px(Context context, float dpValue) {float scale = context.getResources().getDisplayMetrics().density;return (int) (dpValue * scale + 0.5f);}//设置数据public void setData(List<?> list, ViewHolder viewHolder) {datas = list;this.viewHolder = viewHolder;}public void start() {isStart = true;handler.sendEmptyMessage(CODE_START);}public void onResume() {if (!isStart) {isStart = true;handler.sendEmptyMessage(CODE_NEXT);}}public void onPause() {isStart = false;handler.removeMessages(CODE_NEXT);}public void cancle() {isStart = false;currentIndex = 0;if (datas != null) {datas.clear();}removeAllViews();handler.removeMessages(CODE_NEXT);}public void onDestroy() {cancle();}/*** 获取显示行数** @return 行数*/public int getDisplayLines() {return displayLines;}/*** 设置显示行数** @param displayLines 行数*/public void setDisplayLines(int displayLines) {if (displayLines <= 0) {return;}this.displayLines = displayLines;}/*** 是否重复** @return 是否*/public boolean isRepeat() {return isRepeat;}/*** 设置是否重复** @param repeat 是否*/public void setRepeat(boolean repeat) {isRepeat = repeat;}/*** 获取动画持续时间** @return 时长ms*/public long getAnimationTime() {return animationTime;}/*** 设置动画持续时长** @param animationTime ms*/public void setAnimationTime(long animationTime) {this.animationTime = animationTime;}/*** 获取最小间隔时间** @return ms*/public long getMinIntervalTime() {return minIntervalTime;}/*** 设置最小间间隔时间** @param minIntervalTime ms*/public void setMinIntervalTime(long minIntervalTime) {if (minIntervalTime <= 0) {return;}this.minIntervalTime = minIntervalTime;}/*** 获取最大间隔时间** @return ms*/public long getMaxIntervalTime() {return maxIntervalTime;}/*** 设置最大间间隔时间** @param maxIntervalTime ms*/public void setMaxIntervalTime(long maxIntervalTime) {if (maxIntervalTime <= 0) {return;}this.maxIntervalTime = maxIntervalTime;}public interface ViewHolder {View getItemView(Context context, Object item, int index);}
}

bean类:

import java.io.Serializable;/*** 弹幕bean*/
public class BarrageViewBean implements Serializable {private String head;private String name;private String desc;public BarrageViewBean(String head, String name, String desc) {this.head = head;this.name = name;this.desc = desc;}public BarrageViewBean( String desc) {this.desc = desc;}public String getHead() {return head;}public void setHead(String head) {this.head = head;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}
}

布局:

<com.xxx.BarrageViewandroid:id="@+id/barrage_view"android:layout_width="match_parent"android:layout_height="92dp"android:layout_marginTop="25dp"app:layout_constraintBottom_toTopOf="@+id/iv_bg_tips"app:layout_constraintTop_toBottomOf="@+id/view_gray" />

调用:

private fun showBarrageView(){val data = CommonUtils.getAssetsData(AppContext.appContext, "barrview.json")if (!TextUtils.isEmpty(data)) {val list :List<VipUserBean> = Gson().fromJson(data,object : TypeToken<List<VipUserBean>>() {}.type)mBinding.barrageView.setData(list) { context, item, index ->getItem(context, item as VipUserBean)}mBinding.barrageView.displayLines = 2 //设置行数mBinding.barrageView.minIntervalTime = 800L //设置最小显示间隔时间mBinding.barrageView.maxIntervalTime = 1200L //设置最大显示间隔时间mBinding.barrageView.animationTime = 4000L //设置弹幕持续时长mBinding.barrageView.start()}}

更多推荐

Android 弹幕功能实现

本文发布于:2023-12-08 03:57:12,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1672285.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:功能   弹幕   Android

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!