DFM弹幕库在直播中的使用

版权声明:本文为博主原创文章,转载请注明转载地址 https://blog.csdn.net/g_ying_jie/article/details/73107814
第一步、添加弹幕库依赖
compile 'com.github.ctiao:DanmakuFlameMaster:0.8.3'


第二步、弹幕适配不同机型

 /**
     * 对数值进行转换,适配手机,必须在初始化之前,否则有些数据不会起作用
     */
    private void setSize(Context context) {
        BITMAP_WIDTH = TCUtils.dp2pxConvertInt(context, BITMAP_HEIGHT);
        BITMAP_HEIGHT = TCUtils.dp2pxConvertInt(context, BITMAP_HEIGHT);
        DANMU_PADDING = TCUtils.dp2pxConvertInt(context, DANMU_PADDING);
        DANMU_PADDING_INNER = TCUtils.dp2pxConvertInt(context, DANMU_PADDING_INNER);
        DANMU_RADIUS = TCUtils.dp2pxConvertInt(context, DANMU_RADIUS);
        DANMU_TEXT_SIZE = TCUtils.sp2px(context, DANMU_TEXT_SIZE);
    }
public static int dp2pxConvertInt(Context context, float dpValue) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, context.getResources().getDisplayMetrics());
    }
public static float sp2px(Context context, float spValue) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spValue, context.getResources().getDisplayMetrics());
    }


第三步、初始化弹幕配置

   /**
     * 初始化配置
     */
    private void initDanmuConfig() {
        // 设置最大显示行数
        HashMap<Integer, Integer> maxLinesPair = new HashMap<Integer, Integer>();
        maxLinesPair.put(BaseDanmaku.TYPE_SCROLL_RL, 5); // 滚动弹幕最大显示5行
        // 设置是否禁止重叠
        HashMap<Integer, Boolean> overlappingEnablePair = new HashMap<Integer, Boolean>();
        overlappingEnablePair.put(BaseDanmaku.TYPE_SCROLL_RL, true);
        overlappingEnablePair.put(BaseDanmaku.TYPE_FIX_TOP, true);

        mDanmakuContext = DanmakuContext.create();
        mDanmakuContext
                .setDanmakuStyle(IDisplayer.DANMAKU_STYLE_NONE) // 弹幕样式
                .setDuplicateMergingEnabled(true)  // 合并重复弹幕
                .setScrollSpeedFactor(1.2f)     //越大速度越慢
                .setScaleTextSize(1.2f)     // 弹幕文字大小
                .setCacheStuffer(new BackgroundCacheStuffer(), mCacheStufferAdapter)   // 缓存绘制
                .setMaximumLines(maxLinesPair)      // 弹幕最大行数
                .preventOverlapping(overlappingEnablePair);     // 防止弹幕重叠
    }
/**
     * 绘制背景(自定义弹幕样式)
     */
    private class BackgroundCacheStuffer extends SpannedCacheStuffer {
        // 通过扩展SimpleTextCacheStuffer或SpannedCacheStuffer个性化你的弹幕样式
        final Paint paint = new Paint();

        @Override
        public void measure(BaseDanmaku danmaku, TextPaint paint, boolean fromWorkerThread) {
            //danmaku.padding = 20;  // 在背景绘制模式下增加padding
            super.measure(danmaku, paint, fromWorkerThread);
        }

        @Override
        public void drawBackground(BaseDanmaku danmaku, Canvas canvas, float left, float top) {
            paint.setAntiAlias(true);
            paint.setColor(Color.BLACK);
            //由于该库并没有提供margin的设置,所以我这边试出这种方法:将danmaku.padding也就是内间距设置大一点,并在这里的RectF中设置绘制弹幕的位置,就可以形成类似margin的效果
            canvas.drawRoundRect(new RectF(left + DANMU_PADDING_INNER, top + DANMU_PADDING_INNER
                                , left + danmaku.paintWidth - DANMU_PADDING_INNER + 6,
                                top + danmaku.paintHeight - DANMU_PADDING_INNER + 6),//+6 主要是底部被截得太厉害了,+6是增加padding的效果
                                DANMU_RADIUS, DANMU_RADIUS, paint);
        }

        @Override
        public void drawStroke(BaseDanmaku danmaku, String lineText, Canvas canvas, float left, float top, Paint paint) {
            // 禁用描边绘制
        }
    }
 private BaseCacheStuffer.Proxy mCacheStufferAdapter = new BaseCacheStuffer.Proxy() {

        @Override
        public void prepareDrawing(final BaseDanmaku danmaku, boolean fromWorkerThread) {
            // 根据你的条件检查是否需要需要更新弹幕
        }

        @Override
        public void releaseResource(BaseDanmaku danmaku) {
            // TODO 重要:清理含有ImageSpan的text中的一些占用内存的资源 例如drawable
            if (danmaku.text instanceof Spanned) {
                danmaku.text = "";
            }
        }
    };

第四步、处理图片和文字同时显示效果

public class TCCircleDrawable extends Drawable {

    private Paint   mPaint;
    private Bitmap  mBitmap;
    private Bitmap  mBitmapHeart;
    private boolean mHasHeart;

    private static final int BLACK_COLOR          = 0xb2000000;//黑色 背景
    private static final int BLACKGROUDE_ADD_SIZE = 4;//背景比图片多出来的部分

    public TCCircleDrawable(Bitmap bitmap) {
        mBitmap = bitmap;
        BitmapShader bitmapShader = new BitmapShader(bitmap,
                Shader.TileMode.CLAMP,
                Shader.TileMode.CLAMP);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setShader(bitmapShader);
    }

    /**
     * 右下角包含一个‘心’的圆形drawable
     *
     * @param context context
     * @param bitmap btimap
     * @param hasHeart hasHeart
     */
    public TCCircleDrawable(Context context, Bitmap bitmap, boolean hasHeart) {
        this(bitmap);
        mHasHeart = hasHeart;
        if (hasHeart) {
            setBitmapHeart(context);
        }
    }

    private void setBitmapHeart(Context context) {
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_liked);
        if (bitmap != null) {
            Matrix matrix = new Matrix();
            matrix.postScale(0.8f, 0.8f);
            mBitmapHeart = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        }
    }

    @Override
    public void draw(Canvas canvas) {
        if (mHasHeart && mBitmapHeart != null) {
            //设置背景
            Paint backgroundPaint = new Paint();
            backgroundPaint.setAntiAlias(true);
            backgroundPaint.setColor(BLACK_COLOR);
            canvas.drawCircle(getIntrinsicWidth() / 2 + BLACKGROUDE_ADD_SIZE, getIntrinsicHeight() / 2 + BLACKGROUDE_ADD_SIZE,
                    getIntrinsicWidth() / 2 + BLACKGROUDE_ADD_SIZE, backgroundPaint);

            //先将画布平移,防止图片不在正中间,然后绘制图片
            canvas.translate(BLACKGROUDE_ADD_SIZE, BLACKGROUDE_ADD_SIZE);
            canvas.drawCircle(getIntrinsicWidth() / 2, getIntrinsicHeight() / 2, getIntrinsicWidth() / 2, mPaint);

            //在右下角绘制‘心’
            Rect srcRect = new Rect(0, 0, mBitmapHeart.getWidth(), mBitmapHeart.getHeight());
            Rect desRect = new Rect(getIntrinsicWidth() - mBitmapHeart.getWidth() + BLACKGROUDE_ADD_SIZE * 2,
                    getIntrinsicHeight() - mBitmapHeart.getHeight() + BLACKGROUDE_ADD_SIZE * 2,
                    getIntrinsicWidth() + BLACKGROUDE_ADD_SIZE * 2, getIntrinsicHeight() + BLACKGROUDE_ADD_SIZE * 2);
            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setFilterBitmap(true);
            paint.setDither(true);
            canvas.drawBitmap(mBitmapHeart, srcRect, desRect, paint);
        } else {
            canvas.drawCircle(getIntrinsicWidth() / 2, getIntrinsicHeight() / 2, getIntrinsicWidth() / 2, mPaint);
        }
    }

    @Override
    public int getIntrinsicWidth() {
        return mBitmap.getWidth();
    }

    @Override
    public int getIntrinsicHeight() {
        return mBitmap.getHeight();
    }

    @Override
    public void setAlpha(int alpha) {
        mPaint.setAlpha(alpha);
    }

    @Override
    public void setColorFilter(ColorFilter cf) {
        mPaint.setColorFilter(cf);
    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }
}


第五步、添加弹幕

	private void addDanmu(String headUrl, String sender, String text) {
		if (mDanmakuView == null) {
			return;
		}
		BaseDanmaku danmaku = mDanmakuContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL);
		if (danmaku == null) {
			return;
		}
		danmaku.userId = 0;
		danmaku.isGuest = false;// isGuest此处用来判断是赞还是评论

		SpannableStringBuilder spannable;
		Bitmap headBitmap = null;
		if (!TextUtils.isEmpty(headUrl)) {
			RequestManager req = Glide.with(mContext);
			try {
				headBitmap = req.load(headUrl).asBitmap().centerCrop().into(BITMAP_WIDTH, BITMAP_HEIGHT).get();
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (ExecutionException e) {
				e.printStackTrace();
			}
		}
		if (headBitmap == null) {
			headBitmap = getDefaultBitmap(R.drawable.ic_circle_empty);
		}
		TCCircleDrawable circleDrawable = new TCCircleDrawable(mContext, headBitmap, danmaku.isGuest);
		circleDrawable.setBounds(0, 0, BITMAP_WIDTH, BITMAP_HEIGHT);
		spannable = createSpannable(circleDrawable, sender, text);
		danmaku.text = spannable;

		danmaku.padding = DANMU_PADDING;
		danmaku.priority = 0; // 1:一定会显示, 一般用于本机发送的弹幕,但会导致行数的限制失效
		danmaku.isLive = false;
		danmaku.time = mDanmakuView.getCurrentTime() + ADD_DANMU_TIME;
		// danmaku.textSize = DANMU_TEXT_SIZE *
		// (mDanmakuContext.getDisplayer().getDensity() - 0.6f);
		danmaku.textSize = DANMU_TEXT_SIZE;
		danmaku.textColor = Color.WHITE;
		danmaku.textShadowColor = 0; // 重要:如果有图文混排,最好不要设置描边(设textShadowColor=0),否则会进行两次复杂的绘制导致运行效率降低
		mDanmakuView.pause();
		mDanmakuView.addDanmaku(danmaku);
		mDanmakuView.resume();
	}


第六步、在需要显示的地方展示弹幕,即调用addDanmu方法


DFM弹幕库的使用和配置在DEMO的TCDanmuMgr都有展示,欢迎下载体验。

展开阅读全文

没有更多推荐了,返回首页