Android 弹幕(bilibili-DanmakuFlameMaster)—1

姚淳
2023-12-01

1、地址:github-DanmakuFlameMaster

2、依赖:

implementation 'com.github.ctiao:DanmakuFlameMaster:0.9.25'
implementation 'com.github.ctiao:ndkbitmap-armv7a:0.9.21'
// Other ABIs: optional
implementation 'com.github.ctiao:ndkbitmap-armv5:0.9.21'
implementation 'com.github.ctiao:ndkbitmap-x86:0.9.21'

3、初始化:

xml文件:    
<master.flame.danmaku.ui.widget.DanmakuView
            android:id="@+id/hot_barrage_chat_dkv"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

//弹幕View
DanmakuView danmakuView = findViewById(R.id.hot_barrage_chat_dkv);

弹幕配置:

  // 滚动弹幕最大显示4行
  HashMap<Integer, Integer> maxLinesPair = new HashMap<Integer, Integer>();
  maxLinesPair.put(BaseDanmaku.TYPE_SCROLL_RL, 4); 
  //设置是否禁止重叠
  HashMap<Integer, Boolean>  overlappingEnablePair = new HashMap<Integer, Boolean>();
  overlappingEnablePair.put(BaseDanmaku.TYPE_SCROLL_LR, true);
  overlappingEnablePair.put(BaseDanmaku.TYPE_FIX_BOTTOM, true);

  //初始化配置
   DanmakuContext danmakuContext = DanmakuContext.create();
   danmakuContext.setDanmakuStyle(IDisplayer.DANMAKU_STYLE_STROKEN, 3) //设置描边样式
                .setDuplicateMergingEnabled(false)//是否启用合并重复弹幕
                .setScrollSpeedFactor(1.2f)   //设置弹幕滚动速度系数,只对滚动弹幕有效
                .setScaleTextSize(1.2f)
                .setCacheStuffer(new SpannedCacheStuffer(), null) // 图文混排使用SpannedCacheStuffer  设置缓存绘制填充器,默认使用{@link SimpleTextCacheStuffer}只支持纯文字显示, 如果需要图文混排请设置{@link SpannedCacheStuffer}如果需要定制其他样式请扩展{@link SimpleTextCacheStuffer}|{@link SpannedCacheStuffer}
                .setMaximumLines(maxLinesPair) //设置最大显示行数
                .preventOverlapping(overlappingEnablePair); //设置防弹幕重叠,null为允许重叠
   
    //设置解析器
     baseDanmakuParser = new BaseDanmakuParser() {
            @Override
            protected IDanmakus parse() {
                return new Danmakus();
            }
        };


    //配置弹幕
    danmakuView.setCallback(this);
    danmakuView.prepare(baseDanmakuParser, danmakuContext);
    danmakuView.showFPS(false); //是否显示FPS
    danmakuView.enableDanmakuDrawingCache(true);


    //监听回调
    @Override
    public void updateTimer(DanmakuTimer timer) {
        //定时器更新的时候回调
    }

    @Override
    public void drawingFinished() {
        //弹幕绘制完成时回调

    }

    @Override
    public void danmakuShown(BaseDanmaku danmaku) {
        //弹幕展示的时候回调

    }

    @Override
    public void prepared() {
        //弹幕准备好的时候回调,这里启动弹幕
        if (danmakuView != null)
            danmakuView.start();
    }
  
  

注意一定要在prepared 开启弹幕

4、发送文字弹幕
 

文字弹幕 
public void addDanmaku(boolean isLive,  String sendContent) {
        if (danmakuView == null || danmakuContext == null) {
            return;
        }
        //创建一个弹幕对象,这里后面的属性是设置滚动方向的!
        BaseDanmaku danmaku = danmakuContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL);
        if (danmaku == null || sendContent == null) {
            return;
        }
        //弹幕显示的文字
       danmaku.text = sendContent;

        //设置相应的边距,这个设置的是四周的边距
        danmaku.padding = 5;
        // 可能会被各种过滤器过滤并隐藏显示,若果是本机发送的弹幕,建议设置成1;
        danmaku.priority = 0;
        //是否是直播弹幕
        danmaku.isLive = isLive;
        danmaku.setTime(danmakuView.getCurrentTime() + 3600);
        //设置文字大小
        danmaku.textSize = danmaTextSize;
        //设置文字颜色
        danmaku.textColor = textColor;
        //设置阴影的颜色
        danmaku.textShadowColor = Color.WHITE;
        //设置线颜色
         danmaku.underlineColor = Color.GREEN;
        //设置背景颜色
        danmaku.borderColor = Color.GREEN;
        //添加这条弹幕,也就相当于发送
        danmakuView.addDanmaku(danmaku);
    }

5、发送图片文字弹幕

 public void addDanmaKuShowTextAndImage(boolean isLive) {
        if (danmakuView == null || danmakuContext == null) {
            return;
        }
        BaseDanmaku danmaku = danmakuContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL);
        if (danmaku == null) {
            return;
        }
        Drawable drawable = getContext().getResources().getDrawable(R.mipmap.ic_launcher);
        drawable.setBounds(0, 0, 100, 100);
        SpannableStringBuilder spannable = createSpannable(drawable);
        danmaku.text = spannable;
        danmaku.padding = 5;
        danmaku.priority = 0;  // 一定会显示, 一般用于本机发送的弹幕
        danmaku.isLive = isLive;
        danmaku.setTime(danmakuView.getCurrentTime() + 1200);
        danmaku.textSize = danmaTextSize;
        danmaku.textColor = Color.RED;
        danmaku.borderColor = Color.GRAY; // 重要:如果有图文混排,最好不要设置描边(设textShadowColor=0),否则会进行两次复杂的绘制导致运行效率降低
//        danmaku.underlineColor = Color.GREEN;
        danmakuView.addDanmaku(danmaku);
    }

    /**
     * 创建图文混排模式
     *
     * @param drawable
     * @return
     */
    private SpannableStringBuilder createSpannable(Drawable drawable) {
        String text = "bitmap";
        SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(text);
        CenteredImageSpan span = new CenteredImageSpan(drawable);//ImageSpan.ALIGN_BOTTOM);
        spannableStringBuilder.setSpan(span, 0, text.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
        spannableStringBuilder.append("bitmap图文混bitmap图文混bitmap图文混bitmap图文混");
        spannableStringBuilder.setSpan(new BackgroundColorSpan(Color.parseColor("#8A2233B1")), 0, spannableStringBuilder.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        return spannableStringBuilder;
    }

其实弹幕图文、表情、字体变色都是通过 Spannable 来实现。

6.其他 --CacheStufferAdapter

  private BaseCacheStuffer.Proxy mCacheStufferAdapter = new BaseCacheStuffer.Proxy() {

        private Drawable mDrawable;

        /**
         * 在弹幕显示前使用新的text,使用新的text
         * @param danmaku
         * @param fromWorkerThread 是否在工作(非UI)线程,在true的情况下可以做一些耗时操作(例如更新Span的drawblae或者其他IO操作)
         * @return 如果不需重置,直接返回danmaku.text
         */
        @Override
        public void prepareDrawing(final BaseDanmaku danmaku, boolean fromWorkerThread) {
            if (danmaku.text instanceof Spanned) { // 根据你的条件检查是否需要需要更新弹幕
                // FIXME 这里只是简单启个线程来加载远程url图片,请使用你自己的异步线程池,最好加上你的缓存池
                new Thread() {

                    @Override
                    public void run() {
                        String url = "https://img1.baidu.com/it/u=2648389307,756086504&fm=26&fmt=auto";
                        InputStream inputStream = null;
                        Drawable drawable = mDrawable;
                        if (drawable == null) {
                            try {
                                HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
                                inputStream = urlConnection.getInputStream();
                                drawable = BitmapDrawable.createFromStream(inputStream, "bitmap");
                                mDrawable = drawable;
                            } catch (MalformedURLException e) {
                                e.printStackTrace();
                            } catch (IOException e) {
                                e.printStackTrace();
                            } finally {
                                IOUtils.closeQuietly(inputStream);
                            }
                        }
                        if (drawable != null) {
                            drawable.setBounds(0, 0, 100, 100);
                            SpannableStringBuilder spannable = createSpannable(drawable);
                            danmaku.text = spannable;
                            if (danmakuView != null) {
                                danmakuView.invalidateDanmaku(danmaku, false);
                            }
                            return;
                        }
                    }
                }.start();
            }
        }

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

以上就是DanmakuFlameMaster使用。

 类似资料: