前言
最近做项目需要用到一个弹幕的效果,本来一开始准备自己去捣鼓捣鼓实现一下,后来一看有特别好用的BiliBili的开源库DanmakuFlameMaster,所以就拿来用了,简单的使用就不说了,看看源码,网上有教程,都能跑起来,我在这里记一下使用过程中遇到的问题,弹幕的背景以及行距设置。
需求
需求是这样的,需要给弹幕加一个圆角矩形的效果,并且需要设置一下行距,那么DanmakuFlameMaster自身设置背景需要自定义,自己画一个,并也并没有一个setXXX方法直接方便的去设置行距,那么想来想去我是这么实现的:
设置背景样式是通过DanmakuContext的方法来设置的:
danmakuContext.setDanmakuStyle(IDisplayer.DANMAKU_STYLE_STROKEN,3)//描边
.setDuplicateMergingEnabled(false) //是否合并重复弹幕
.setScrollSpeedFactor(1.2f) //弹幕滚动速度
.setScaleTextSize(1.2f)
.setMaximumVisibleSizeInScreen(9)//一个屏幕最多允许多少弹幕
.setCacheStuffer(new BackgroundCacheStuffer(context),mCacheStufferAdapter) //定义背景样式
.setMaximumLines(maxLinesPair) //设置最大显示行数
.preventOverlapping(overlappingEnablePair); //设置防弹幕重叠,null为允许重叠;
实现BackgroundCacheStuffer内部类,对于圆角矩形和间距的问题,我是通过先画一个大的透明的矩形,再在里面画一个小的圆角矩形,然后通过设置danmaku的padding来实现的,为什么这么做,因为在DanmakFlameMaster中不管你画多大的背景,最后背景的大小只会是将你弹幕中的text紧紧的包围那么大,所以要通过设置padding,然后外面一个透明矩形来实现:
/**
* 绘制弹幕背景(自定义弹幕样式)
*/
public static class BackgroundCacheStuffer extends SpannedCacheStuffer {
// 通过扩展SimpleTextCacheStuffer或SpannedCacheStuffer个性化你的弹幕样式
Paint paint = new Paint();
Paint paint1 = new Paint();
Context context;
public BackgroundCacheStuffer(Context context){
this.context = context;
}
@Override
public void measure(BaseDanmaku danmaku, TextPaint paint, boolean fromWorkerThread) {
// 在背景绘制模式下增加padding
danmaku.padding = dp2px(7);
super.measure(danmaku, paint, fromWorkerThread);
}
/**
* 这个框架并没有设置弹幕行间距的方法,只能自己想办法,画了两个矩形,外面那个是透明的
*/
@Override
public void drawBackground(BaseDanmaku danmaku, Canvas canvas, float left, float top) {
//画一个大的透明矩形
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.TRANSPARENT);
RectF mRectf = new RectF(left, top , left + danmaku.paintWidth, top + danmaku.paintHeight);
canvas.drawRect(mRectf,paint);
//画一个圆角矩形当做背景
paint1.setStyle(Paint.Style.FILL);
paint1.setColor(Color.WHITE);
paint1.setAlpha(140);
paint1.setAntiAlias(true);
RectF mRectf2 = new RectF(left + 2 ,top + dp2px(5),
left + danmaku.paintWidth - 2 , top + danmaku.paintHeight - dp2px(5));
canvas.drawRoundRect(mRectf2,dp2px(100),dp2px(100),paint1);
canvas.save();
}
@Override
public void drawStroke(BaseDanmaku danmaku, String lineText, Canvas canvas, float left, float top, Paint paint) {
// 禁用描边绘制
}
/**
* dp转px,工具类里还得传上下文太麻烦了
*/
public int dp2px(float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
/**
* 必须通过这个来设置弹幕背景样式
*/
private BaseCacheStuffer.Proxy mCacheStufferAdapter = new BaseCacheStuffer.Proxy() {
@Override
public void prepareDrawing(final BaseDanmaku danmaku, boolean fromWorkerThread) {
// if (danmaku.text instanceof Spanned) { // 根据你的条件检查是否需要需要更新弹幕
// }
}
@Override
public void releaseResource(BaseDanmaku danmaku) {
// TODO 重要:清理含有ImageSpan的text中的一些占用内存的资源 例如drawable
if (danmaku.text instanceof Spanned) {
danmaku.text = "";
}
}
};
效果图大体是这样的:
总结
当时是想找个能设置背景,也能设置间距的方法,但是百度了一下并没有前人有这方面的文章,那么自己开始想办法,然后我这里记下来,如果有使用DanmakuFlameMaster的,并且想要设置背景和间距的可以参考下,这是要求圆角矩形,如果什么背景都没有只是设置行间距就更简单了,以上就是一些经验分享,不足之处请大神指点。