android弹幕三行展示,数据不重复,不重叠

时间:2024-03-27 08:37:58

android实现弹幕 三行展示,数据不重复,不重叠,还能发弹幕:

Android开源弹幕引擎·烈焰弹幕使 ~:https://github.com/bilibili/DanmakuFlameMaster    (大家都在用这玩意,但是确实不太友好,改起来有点方;不过算是不错的了,至少有开源的源码)

 

android弹幕三行展示,数据不重复,不重叠

 

1、添加依赖:

dependencies {

    implementation 'com.github.ctiao:DanmakuFlameMaster:0.9.16'

}

2、简单实现:

          实现逻辑:    

                 1》、初始化弹幕的列表数据集,启动线程循环展示
                 2》、添加一条弹幕,并且存入列表数据集,保证数据不丢失

   代码逻辑很简单,先看代码,合适再用,不合适仅供参考

import master.flame.danmaku.controller.DanmakuFilters;
import master.flame.danmaku.controller.DrawHandler;
import master.flame.danmaku.danmaku.model.BaseDanmaku;
import master.flame.danmaku.danmaku.model.DanmakuTimer;
import master.flame.danmaku.danmaku.model.IDanmakus;
import master.flame.danmaku.danmaku.model.IDisplayer;
import master.flame.danmaku.danmaku.model.android.DanmakuContext;
import master.flame.danmaku.danmaku.model.android.Danmakus;
import master.flame.danmaku.danmaku.parser.BaseDanmakuParser;
import master.flame.danmaku.ui.widget.DanmakuView;

public class MainActivity extends Activity {

    private boolean showDanmaku;//是否循环展示弹幕

    private DanmakuView danmakuView;//弹幕View

    private DanmakuContext danmakuContext;//弹幕的Context使用对象

    List<DanMuBean> totalDanMuList = new ArrayList<>();//用于记录弹幕的内容列表

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

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        VideoView videoView = (VideoView) findViewById(R.id.video_view);
        videoView.setVideoPath("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4");
        videoView.start();

        Button button = (Button)findViewById(R.id.addDanmu);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                DanMuBean danMuBean = new DanMuBean();
                danMuBean.setContent("漠天");
                danMuBean.setShowBorder(true);
                totalDanMuList.add(danMuBean);
                addDanmaku(danMuBean.getContent(), danMuBean.isShowBorder());
            }
        });

        danmakuView = (DanmakuView) findViewById(R.id.danmaku_view);
        danmakuView.enableDanmakuDrawingCache(true);
        danmakuView.setCallback(new DrawHandler.Callback() {
            @Override
            public void prepared() {
                showDanmaku = true;
                danmakuView.start();

                //初始化弹幕列表,可以替换成自己的数据集
                for(int index=0;index<20;index++) {
                    DanMuBean danMuBean = new DanMuBean();
                    danMuBean.setContent("丫头 ("+index+")");
                    danMuBean.setShowBorder(false);
                    totalDanMuList.add(danMuBean);
                }
                //启动线程展示弹幕
                generateSomeDanmaku();
            }

            @Override
            public void updateTimer(DanmakuTimer timer) {

            }

            @Override
            public void danmakuShown(BaseDanmaku danmaku) {

            }

            @Override
            public void drawingFinished() {

            }
        });
        danmakuContext = DanmakuContext.create();
        danmakuView.prepare(parser, danmakuContext);

        // 设置最大显示行数
        HashMap<Integer, Integer> maxLinesPair = new HashMap<Integer, Integer>();
        maxLinesPair.put(BaseDanmaku.TYPE_SCROLL_RL, 3); // 滚动弹幕最大显示5行

        // 设置是否禁止重叠
        HashMap<Integer, Boolean> overlappingEnablePair = new HashMap<Integer, Boolean>();
        overlappingEnablePair.put(BaseDanmaku.TYPE_SCROLL_RL, true);
        overlappingEnablePair.put(BaseDanmaku.TYPE_FIX_TOP, true);

        danmakuContext.setDanmakuStyle(IDisplayer.DANMAKU_STYLE_STROKEN, 3)
                .setDuplicateMergingEnabled(false)
                .setScrollSpeedFactor(1.2f)
                .setScaleTextSize(1.2f)
                .setDuplicateMergingEnabled(false) //设置不合并相同内容弹幕
                .preventOverlapping(overlappingEnablePair)
                .setMaximumLines(maxLinesPair);
    }
    /**
     * 向弹幕View中添加一条弹幕
     * @param content
     *          弹幕的具体内容
     * @param  withBorder
     *          弹幕是否有边框
     */
    private void addDanmaku(String content, boolean withBorder) {
        BaseDanmaku danmaku = danmakuContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL);
        danmaku.text = content;
        danmaku.padding = 5;
        danmaku.textSize = sp2px(20);
        danmaku.textColor = Color.WHITE;
        danmaku.setTime(danmakuView.getCurrentTime());
        if (withBorder) {
            danmaku.borderColor = Color.GREEN;
        }
        danmakuView.addDanmaku(danmaku);
    }

    /**
     * 循环展示弹幕,展示列表的弹幕
     */
    private void generateSomeDanmaku() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(showDanmaku) {
                    for(int index = 0;index<totalDanMuList.size();index++){
                        int time = new Random().nextInt(1000);
                        DanMuBean danMuBean = totalDanMuList.get(index);
                        if(danMuBean!=null) {
                            addDanmaku(danMuBean.getContent(), danMuBean.isShowBorder());
                            try {
                                Thread.sleep(time);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        }).start();
    }

    /**
     * sp转px的方法。
     */
    public int sp2px(float spValue) {
        final float fontScale = getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (danmakuView != null && danmakuView.isPrepared()) {
            danmakuView.pause();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (danmakuView != null && danmakuView.isPrepared() && danmakuView.isPaused()) {
            danmakuView.resume();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        showDanmaku = false;
        if (danmakuView != null) {
            danmakuView.release();
            danmakuView = null;
        }
    }

}

3、xml代码:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorPrimaryDark"
    tools:context=".MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:gravity="center">

        <VideoView
            android:id="@+id/video_view"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:layout_centerInParent="true" />

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

    </RelativeLayout>


    <Button
        android:id="@+id/addDanmu"
        android:layout_width="200dp"
        android:layout_height="100dp"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="50dp"
        android:text="添加弹幕"
        android:textColor="#ff0000"
        android:textSize="20sp" />


</RelativeLayout>