使用b站开源弹幕引擎实现炫酷的弹幕效果

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013200308/article/details/57123100

转载请注明出处
作者:AboutJoke ( http://blog.csdn.net/u013200308 )
原文链接:http://blog.csdn.net/u013200308/article/details/57123100


现在各大视屏网站都有了弹幕功能,但显示效果最好的非b站莫属了。如果你也想拥有和b站一样炫酷的弹幕效果,那么就跟着我来一步步实现。

首先放上地址

https://github.com/Bilibili/DanmakuFlameMaster

使用也很简单

repositories {
    jcenter()
}

dependencies {
    compile 'com.github.ctiao:DanmakuFlameMaster:0.6.4'
    compile 'com.github.ctiao:ndkbitmap-armv7a:0.6.4'

    # Other ABIs: optional
    compile 'com.github.ctiao:ndkbitmap-armv5:0.6.4'
    compile 'com.github.ctiao:ndkbitmap-x86:0.6.4'
}

到这里我们就将库导入了as了,接下来就是真正的使用。

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

用来承载弹幕显示的布局,有了布局就可以去实现代码了,一些方法我也都标上了注释。

    //初始化弹幕层
    public void initDanmaku() {
        mDanmakuContext = DanmakuContext.create();
        HashMap<Integer, Integer> maxLine = new HashMap<>();
        maxLine.put(BaseDanmaku.TYPE_SCROLL_RL, 3);// 滚动弹幕最大显示3行
        // 设置是否禁止重叠
        HashMap<Integer, Boolean> overlappingEnablePair = new HashMap<Integer, Boolean>();
        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)//设置字体缩放
                .setMaximumLines(maxLine)//设置最大显示行数
                .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() {

                }
            });

            //弹幕解析器,如不想使用使用xml格式的可以以自己定义或默认
//            mParser = new BaseDanmakuParser() {
//                @Override
//                protected IDanmakus parse() {
//                    return new Danmakus();
//                }
//            };

            mParser = createParser(this.getResources().openRawResource(R.raw.comments));
            mDanmakuView.showFPS(true);//显示fps
            mDanmakuView.enableDanmakuDrawingCache(true);//显示弹幕绘制缓冲
            mDanmakuView.prepare(mParser, mDanmakuContext);
        }
    }

b站的弹幕使用的是xml格式保存的,而a站的弹幕使用的是json格式,如果你也准备使用xml格式可以借鉴b站的解析方式,而或者这两种格式你都不使用的话,可以使用默认的弹幕解析器。

mParser = new BaseDanmakuParser() {
                @Override
                protected IDanmakus parse() {
                    return new Danmakus();
                }
            };

接下来需要创建弹幕解析器,用来解析不同格式的弹幕,如前面所说,你的弹幕格式是xml或json就需要这一步。

//创建解析器对象,解析输入流
    private BaseDanmakuParser createParser(InputStream stream) {

        if (stream == null) {
            return new BaseDanmakuParser() {

                @Override
                protected Danmakus parse() {
                    return new Danmakus();
                }
            };
        }

        //DanmakuLoaderFactory.create(DanmakuLoaderFactory.TAG_BILI) xml解析
        //DanmakuLoaderFactory.create(DanmakuLoaderFactory.TAG_ACFUN) json文件格式解析

        ILoader loader = DanmakuLoaderFactory.create(DanmakuLoaderFactory.TAG_BILI);

        try {
            loader.load(stream);
        } catch (IllegalDataException e) {
            e.printStackTrace();
        }
        BaseDanmakuParser parser = new BiliDanmukuParser();
        IDataSource<?> dataSource = loader.getDataSource();
        parser.load(dataSource);
        return parser;

    }

弹幕解析器的主要作用是接受从服务器传来的弹幕文件,解析后将其一一展示出来,那么我们发出去的弹幕则需要一个单独的方法来实现弹幕的发送,在这一步你可以对发送的弹幕进行个性化定制。

//添加弹幕
    public void addDanmaku(boolean islive, String msg, boolean isUs) {
        BaseDanmaku danmaku = mDanmakuContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL);
        if (danmaku == null || mDanmakuView == null) {
            return;
        }
        danmaku.text = msg;//弹幕内容
        danmaku.padding = 5;
        danmaku.priority = 1;//0 表示可能会被各种过滤器过滤并隐藏显示 1 表示一定会显示, 一般用于本机发送的弹幕
        danmaku.isLive = islive; //是否是直播弹幕
        danmaku.setTime(mDanmakuView.getCurrentTime() + 1200); //显示时间
        danmaku.textSize = 18f * (mParser.getDisplayer().getDensity() - 0.6f); //字体大小
        danmaku.textColor = Color.WHITE;
        danmaku.textShadowColor = Color.parseColor("#333333");// 阴影颜色,可防止白色字体在白色背景下不可见
        if (isUs)
            danmaku.borderColor = Color.YELLOW; //对于自己发送的弹幕可以加框显示,0表示无边框
        mDanmakuView.addDanmaku(danmaku);
    }

有了发送弹幕的方法,那我们当然也得有接收弹幕的布局,在这里我是用PopupWindow来实现,你可以去使用你习惯的方式。来看看我们要实现的布局

这里写图片描述

从图片里可以看到右边有数字的标示,那是因为我还要实现一个弹幕字数的限制,一次如果发送太多字数的弹幕难免太影响观看了。对于字数的限制也很简单,可以使用EditText的TextWatcher来实现,如果有不会的可以去源码里面查看。那么到此我们就实现了弹幕的播放和发送,赶快来看看效果,不过在看效果之前我们还得再写几句代码,mDanmakuView.release();别忘记去onDestroy()和onBackPressed()里面去释放资源。好了,来看看效果吧。

这里写图片描述

录屏效果看起来有点差,真机效果可是棒棒哒。另外附上源码地址:

https://github.com/AboutJoke/DanmuDemo

猜你喜欢

转载自blog.csdn.net/u013200308/article/details/57123100