Android 自定义View——BarrageView实现弹幕功能

来源:互联网 发布:数据库完整性约束条件 编辑:程序博客网 时间:2024/05/19 00:49

现在很多应用都有弹幕的功能,虽然本人没什么兴趣使用弹幕的功能,但是对如何实现这个弹幕功能还是有兴趣的。先上效果图。

这里写图片描述

原理

在ViewGroup上不定时地添加属性不相同的TextView执行不同的动画。

BarrageView的关键代码

BarrageView所需要的属性

 /**     * 最大的移动速度     */    private int maxSpeed;    /**     * 最小的移动速度     */    private int minSpeed;    /**     * 最大的字体尺寸     */    private float maxTextSize;    /**     * 最小的字体尺寸     */    private float minTextSize;    /**     * 最大的时间间隔     */    private int maxInterval;    /**     * 最小的时间间隔     */    private int minInterval;    /**     * 用于随机设置字体颜色     */    private Random random = new Random();    /**     * 控制是否弹幕     */    private boolean barrageState = true;

为了更方便地使用控件,在attrs.xml中添加控件所需要的自定义属性

  <declare-styleable name="BarrageView">        <attr name="maxSpeed" format="integer"/>        <attr name="minSpeed" format="integer"/>        <attr name="maxInterval" format="integer"/>        <attr name="minInterval" format="integer"/>        <attr name="maxTextSize" format="dimension"/>        <attr name="minTextSize" format="dimension"/>    </declare-styleable>

在构造函数中获取自定义属性的值

 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BarrageView, defStyleAttr, 0);        minSpeed =a.getInt(R.styleable.BarrageView_minSpeed,7000);        maxSpeed =a.getInt(R.styleable.BarrageView_maxSpeed,4000);        maxTextSize = a.getDimension(R.styleable.BarrageView_maxTextSize, 30);        minTextSize = a.getDimension(R.styleable.BarrageView_minTextSize, 10);        maxInterval = a.getInteger(R.styleable.BarrageView_maxInterval, 2000);        minInterval = a.getInteger(R.styleable.BarrageView_minInterval, 500);        a.recycle();

在BarrageView中需要定义Handler来控制弹幕

 private static final int MESSAGE_SHOWITEM = 1;    private Handler barrageHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            if (msg.what == 1) {                if(barrageState) {                    addBarrageItem();                    //随机获取时间间隔                    int interval = (int) (Math.random() * (maxInterval - minInterval) + minInterval);                    sendEmptyMessageDelayed(MESSAGE_SHOWITEM, interval);                }            }        }    };

添加弹幕的方法

 /**     * 添加弹幕     */    private void addBarrageItem() {        final TextView textView = new TextView(getContext());        int textSize = (int) (Math.random() * (maxTextSize - minTextSize) + minTextSize);        textView.setTextSize(textSize);        textView.setSingleLine(true);        //随机设置字体颜色        textView.setTextColor(0xff000000 | random.nextInt(0x00ffffff));        textView.setText(barrageContents.get((int) (Math.random() * barrageContents.size())));        //调用measure确保measuredHeight和measuredWidth能拿到值        textView.measure(0, 0);        int speed = (int) (Math.random() * (maxSpeed - minSpeed) + minSpeed);        int topMargin = (int) (Math.random() * (this.getHeight() - textView.getMeasuredHeight()));        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);        params.addRule(RelativeLayout.ALIGN_PARENT_TOP);        params.topMargin = topMargin;        this.addView(textView, params);        TranslateAnimation anim = new TranslateAnimation(this.getWidth(), -textView.getMeasuredWidth(), 0, 0);        anim.setDuration(speed);        anim.setFillAfter(true);        textView.startAnimation(anim);        anim.setAnimationListener(new Animation.AnimationListener() {            @Override            public void onAnimationStart(Animation animation) {            }            @Override            public void onAnimationEnd(Animation animation) {                textView.clearAnimation();                BarrageView.this.removeView(textView);            }            @Override            public void onAnimationRepeat(Animation animation) {            }        });    }

设置弹幕内容

  /**     * 设置弹幕内容     *     * @param barrageContents 弹幕内容     */    public void setBarrageContents(List<String> barrageContents) {        this.removeAllViews();//移除之前的弹幕        barrageHandler.removeMessages(MESSAGE_SHOWITEM);///移除之前的消息        this.barrageContents = barrageContents;        barrageHandler.sendEmptyMessageDelayed(MESSAGE_SHOWITEM, 0);    }

控件弹幕

/**     * 开始弹幕     */    public void startBarraging(){        barrageState = true;        if(!barrageHandler.hasMessages(MESSAGE_SHOWITEM)){            barrageHandler.sendEmptyMessage(MESSAGE_SHOWITEM);        }    }    /**     * 停止弹幕     */    public void stopBarraging(){        barrageState = false;        barrageHandler.removeMessages(MESSAGE_SHOWITEM);    }

最后是布局代码示例

<?xml version="1.0" encoding="utf-8"?><RelativeLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent">    <com.xiaoniu.barragedemo.BarrageView        android:id="@+id/barrageView"        android:layout_width="match_parent"        android:layout_height="300dp"        android:background="#b1b1b1"        app:maxInterval="1000"        app:minInterval="500"        app:maxSpeed="3000"        app:minSpeed="5000"        app:maxTextSize="20sp"        app:minTextSize="10sp"/></RelativeLayout>

————————————————————

源码地址

0 0
原创粉丝点击