DFM彈幕庫在直播中的使用

第一步、添加彈幕庫依賴
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都有展示,歡迎下載體驗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章