package com.team.zhuoke.danmu.utils; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.RectF; import android.os.Build; import android.support.annotation.RequiresApi; import android.text.TextPaint; import com.team.zhuoke.danmu.client.DyBulletScreenClient; import java.io.InputStream; import java.util.HashMap; import java.util.Random; import master.flame.danmaku.controller.DrawHandler; import master.flame.danmaku.controller.IDanmakuView; import master.flame.danmaku.danmaku.loader.ILoader; import master.flame.danmaku.danmaku.loader.IllegalDataException; import master.flame.danmaku.danmaku.loader.android.DanmakuLoaderFactory; import master.flame.danmaku.danmaku.model.BaseDanmaku; import master.flame.danmaku.danmaku.model.DanmakuTimer; import master.flame.danmaku.danmaku.model.IDisplayer; import master.flame.danmaku.danmaku.model.android.BaseCacheStuffer; import master.flame.danmaku.danmaku.model.android.DanmakuContext; import master.flame.danmaku.danmaku.model.android.Danmakus; import master.flame.danmaku.danmaku.model.android.SpannedCacheStuffer; import master.flame.danmaku.danmaku.parser.BaseDanmakuParser; import master.flame.danmaku.danmaku.parser.IDataSource; import master.flame.danmaku.danmaku.parser.android.BiliDanmukuParser; public class DanmuProcess { private Context mContext; private IDanmakuView mDanmakuView; private DanmakuContext mDanmakuContext; private BaseDanmakuParser mParser; private DyBulletScreenClient mDanmuClient; private int mRoomId; /** * 弹幕 随机颜色 */ private Random random; private int[] ranColor = {0xe0ffffff, 0xe0F0E68C, 0xe0F08080, 0xe0FFC0CB, 0xe000FA9A, 0xe000FF7F, 0xe0FFD700, 0xe07FFFD4, 0xe0FF7F50, 0xe0DC143C, 0xe0FFC0CB, 0xe0DB7093, 0xe87CEEB}; public DanmuProcess(Context context, IDanmakuView danmakuView, int roomId) { this.mContext = context; this.mDanmakuView = danmakuView; this.mRoomId = roomId; random = new Random(); } public void start() { initDanmaku(); getAndAddDanmu(); } private void initDanmaku() { mDanmakuContext = DanmakuContext.create(); try { mParser = createParser(null); } catch (IllegalDataException e) { e.printStackTrace(); } HashMap<Integer, Integer> maxLinesPair = new HashMap<>(); maxLinesPair.put(BaseDanmaku.TYPE_SCROLL_LR, 6); HashMap<Integer, Boolean> overlappingEnablePair = new HashMap<>(); overlappingEnablePair.put(BaseDanmaku.TYPE_SCROLL_RL, true); overlappingEnablePair.put(BaseDanmaku.TYPE_FIX_TOP, true); mDanmakuContext.setDanmakuStyle(IDisplayer.DANMAKU_STYLE_STROKEN, 3) .setDuplicateMergingEnabled(false) .setScrollSpeedFactor(1.2f) .setScaleTextSize(1.2f) .setCacheStuffer(new BackgroundCacheStuffer(), mCacheStufferAdapter) .setMaximumLines(maxLinesPair) .preventOverlapping(overlappingEnablePair); if (mDanmakuView != null) { mDanmakuView.setCallback(new DrawHandler.Callback() { @Override public void prepared() { mDanmakuView.start(); } @Override public void updateTimer(DanmakuTimer timer) { } @Override public void danmakuShown(BaseDanmaku danmaku) { } @Override public void drawingFinished() { } }); mDanmakuView.prepare(mParser, mDanmakuContext); mDanmakuView.enableDanmakuDrawingCache(true); } } private BaseDanmakuParser createParser(InputStream stream) throws IllegalDataException { if (stream == null) { return new BaseDanmakuParser() { @Override protected Danmakus parse() { return new Danmakus(); } }; } ILoader loader = DanmakuLoaderFactory.create(DanmakuLoaderFactory.TAG_BILI); loader.load(stream); BaseDanmakuParser parser = new BiliDanmukuParser(); IDataSource<?> dataSource = loader.getDataSource(); parser.load(dataSource); return parser; } private void getAndAddDanmu() { Thread thread = new Thread(new Runnable() { @Override public void run() { int groupId = -9999; mDanmuClient = DyBulletScreenClient.getInstance(); //设置需要连接和访问的房间ID,以及弹幕池分组号 mDanmuClient.start(mRoomId, groupId); mDanmuClient.setmHandleMsgListener(new DyBulletScreenClient.HandleMsgListener() { @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override public void handleMessage(String txt) { // 发送弹幕 addDanmaku(true, txt); } }); } }); thread.start(); } private void addDanmaku(boolean islive, String txt) { BaseDanmaku danmaku = mDanmakuContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL); if (danmaku == null || mDanmakuView == null) { return; } danmaku.text = txt; danmaku.padding = 10; danmaku.priority = 1; danmaku.isLive = islive; danmaku.textSize = 15f * (mParser.getDisplayer().getDensity() - 0.6f); danmaku.time = mDanmakuView.getCurrentTime(); mDanmakuView.addDanmaku(danmaku); } public void finish() { //停止从服务器获取弹幕 mDanmuClient.stop(); } private BaseCacheStuffer.Proxy mCacheStufferAdapter = new BaseCacheStuffer.Proxy() { @Override public void prepareDrawing(final BaseDanmaku danmaku, boolean fromWorkerThread) { } @Override public void releaseResource(BaseDanmaku danmaku) { danmaku.text = null; } }; class BackgroundCacheStuffer extends SpannedCacheStuffer { // 通过扩展SimpleTextCacheStuffer或SpannedCacheStuffer个性化你的弹幕样式 final Paint paint = new Paint(); final RectF rf = new RectF(); @Override public void measure(BaseDanmaku danmaku, TextPaint paint, boolean fromWorkerThread) { danmaku.padding = 15; // 在背景绘制模式下增加padding super.measure(danmaku, paint, fromWorkerThread); } @Override public void drawBackground(BaseDanmaku danmaku, Canvas canvas, float left, float top) { int ranNumber = random.nextInt(ranColor.length); int color = ranColor[ranNumber]; paint.setAntiAlias(true); if (color != 0xe0ffffff && ranNumber % 2 == 0) { paint.setColor(color); //弹幕背景颜色 rf.left = left; rf.right = left + danmaku.paintWidth; rf.top = top; rf.bottom = top + danmaku.paintHeight; danmaku.textColor = 0xe0ffffff; paint.setStyle(Paint.Style.FILL); canvas.drawRoundRect(rf, 40, 40, paint); } else { danmaku.textColor = color; paint.setColor(color); //弹幕背景颜色 rf.left = left; rf.right = left + danmaku.paintWidth; rf.top = top; rf.bottom = top + danmaku.paintHeight; paint.setStyle(Paint.Style.STROKE); canvas.drawRoundRect(rf, 40, 40, paint); } } @Override public void drawStroke(BaseDanmaku danmaku, String lineText, Canvas canvas, float left, float top, Paint paint) { // 禁用描边绘制 } } }