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();
}
DFM彈幕庫的使用和配置在DEMO的TCDanmuMgr都有展示,歡迎下載體驗。