自定义-弹幕



import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;


import java.util.ArrayList;
import java.util.List;
import java.util.Random;




public class DanMuView extends View  implements  Runnable{


    private static final String TAG = "DanMuView";


    //用来绘制弹幕的画笔, 通过它来设置弹幕的字体大小, 颜色等等
    private TextPaint mTextPaint;
    //创建一个List来保存所添加的弹幕TextItem
    List<TextItem> mTextItems = new ArrayList<TextItem>();


    Random random = new Random();


    public DanMuView(Context context) {
        this(context, null);
    }


    public DanMuView(Context context, AttributeSet attrs) {
        super(context, attrs);


        init(context, attrs);
    }


    private void init(Context context, AttributeSet attrs) {
        mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setColor(Color.RED);
        mTextPaint.setTextSize(30);


        //开启自己
        new Thread(this). start();
    }


    public void addTextItemRandom(String content) {
        if (content != null) {


            TextItem item = null;
            for (TextItem textItem : mTextItems) {
                if (canReuse(textItem, mDanmuViewWidth, mDanmuViewHeight)) {
                    item = textItem;
                }
            }


            if (item == null) {
                item = new TextItem(content);
                //只有新创建的才会添加到List中, 其他的说明可以复用了
                mTextItems.add(item);
            } else {
                item.setmContent(content);
            }


            float x = 10, y = 100;
            if (mDanmuViewWidth > 0 && mDanmuViewHeight > 0) {
                x = random.nextFloat() * mDanmuViewWidth;
                y = random.nextFloat() * mDanmuViewHeight + mTextPaint.getTextSize();
            } else {
                x = 500;
                y = random.nextFloat() * 100 + mTextPaint.getTextSize();
            }


            //设置TextItem的x,y坐标
            item.setmLocX(x);
            item.setmLocY(y);


            //设置TextItem的颜色为随即的
            int r = random.nextInt(255);
            int g = random.nextInt(255);
            int b = random.nextInt(255);
            item.setmColor(Color.rgb(r, g, b));


            //设置TextItem向左移动的速度也为随机的
            item.setmSteps(random.nextFloat() * 80);


            //设置TextItem的宽度
            item.setmTextWidth(mTextPaint.measureText(content));


            //最后讲创建出的TextItem添加到List中, 然后在onDraw方法中遍历,并画出来
            //mTextItems.add(item);


            Log.e(TAG, "addTextItemRandom: mTextItems.size() is " + mTextItems.size());
        }
    }


    /**
     * 判断是否可以复用
     * @param item
     * @param w
     * @param h
     * @return
     */
    private static final boolean canReuse(TextItem item, float w, float h) {
        boolean ret = true;


        if (item != null && w > 0 && h > 0) {
            float iX = item.getmLocX();
            float iY = item.getmLocY();
            if (iX < w) {
                //没有超过最右侧
                float textWidth = item.getmTextWidth();
                if (iX > -textWidth) {
                    ret = false;
                }
            }
        }
        return ret;
    }


    /**
     * 在onDraw方法中进行绘制弹幕的文本信息
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        Log.e(TAG, "onDraw: ");


        //调用Canvas的drawText方法来进行绘制一个Text文本信息
        if (mDanmuViewWidth > 0 && mDanmuViewHeight > 0) {
            //canvas.drawText("Hello World", mTextX, mTextY, mTextPaint);
            for (TextItem item : mTextItems) {


                // TODO 此处做优化
                /**String content = item.getmContent();
                float x = item.getmLocX();
                float y = item.getmLocY();
                int color = item.getmColor();
                float textWidth = item.getmTextWidth();


                mTextPaint.setColor(color);
                if (y > 0 && y < mDanmuViewHeight
                        && x > -textWidth && x < mDanmuViewWidth){
                    canvas.drawText(content, x, y, mTextPaint);
                }*/
                if (!canReuse(item, mDanmuViewWidth, mDanmuViewHeight)) {
                    String content = item.getmContent();
                    float x = item.getmLocX();
                    float y = item.getmLocY();
                    int color = item.getmColor();


                    mTextPaint.setColor(color);


                    canvas.drawText(content, x, y, mTextPaint);
                }
            }
        }
    }


    /**
     * 当CanvasView的宽高发生改变时调用, 也就是xml文件中的DanMuView已经显示在屏幕上
     * @param w
     * @param h
     * @param oldw
     * @param oldh
     */


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mDanmuViewWidth = w;
        mDanmuViewHeight = h;
    }


    private boolean mRunning;
    //用来判断子线程是否需要继续执行, 当Activity不是前端运行状态时, 需中断线程
    private boolean mPaused;
    //当前CanvasView自己的宽度
    private float mDanmuViewWidth;
    //当前CanvasView自己的高度
    private float mDanmuViewHeight;


    public void onResume() {
        mPaused = false;
    }


    public void onPause () {
        mPaused = true;
    }


    public void exitLoop() {
        mRunning = false;
    }


    /**
     * 自身实现Runnable接口,
     * 注意一定是子线程中更新状态, UI线程的onDraw方法只负责绘制即可
     */
    @Override
    public void run() {


        mRunning = true;
        try {
            while (mRunning) {
                if (mDanmuViewWidth > 0 && mDanmuViewHeight > 0 && !mPaused) {
                    //有尺寸,才绘制
                    //TODO 更新每一个TextItem的位置
                    //TODO 考虑都移出去,并且没有再添加的问题
                    boolean needPaint = false;
                    for (TextItem item : mTextItems) {
                        item.moveLeft();
                        if (!canReuse(item, mDanmuViewWidth, mDanmuViewHeight)) {
                            needPaint = true;
                        }
                    }
                    if (needPaint) {
                        postInvalidate();  //重新调用onDraw方法
                    }
                }
                Thread.sleep(80);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static class TextItem{
        private float mLocX;
        private float mLocY;


        private float mSteps;  //一次刷新的步进数


        private int mColor;


        private float mTextWidth;  //文本的宽度
        private String mContent;


        public TextItem(String mContent) {
            this.mContent = mContent;
        }


        public void moveLeft() {
            mLocX -= mSteps;
        }


        public float getmLocX() {
            return mLocX;
        }


        public void setmLocX(float mLocX) {
            this.mLocX = mLocX;
        }


        public float getmLocY() {
            return mLocY;
        }


        public void setmLocY(float mLocY) {
            this.mLocY = mLocY;
        }


        public float getmSteps() {
            return mSteps;
        }


        public void setmSteps(float mSteps) {
            this.mSteps = mSteps;
        }


        public int getmColor() {
            return mColor;
        }


        public void setmColor(int mColor) {
            this.mColor = mColor;
        }


        public float getmTextWidth() {
            return mTextWidth;
        }


        public void setmTextWidth(float mTextWidth) {
            this.mTextWidth = mTextWidth;
        }


        public String getmContent() {
            return mContent;
        }


        public void setmContent(String mContent) {
            this.mContent = mContent;
        }


    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值