OpenDanmaku of Android open source framework

Introduction

OpenDanmaku is a third-party barrage control in Android, which pops up user comments during video playback and live broadcast software, and displays them in a scrolling manner.

use

  • Download link: https://github.com/linsea/OpenDanmaku
  • Project related library
Gradle
   dependencies {
    
    
                compile 'com.linsea:opendanmaku:1.0.0@aar'
         }
//或者引用本地lib
compile project(':opendanmaku')

Case study

  • MainActivity
package com.example.dell.myapplication;

import android.media.MediaPlayer;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ImageSpan;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.MediaController;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;
import com.opendanmaku.DanmakuItem;
import com.opendanmaku.DanmakuView;
import com.opendanmaku.IDanmakuItem;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class OpenDanmakuMainActivity extends AppCompatActivity implements View.OnClickListener{
    
    

    /**
     * 定义控件
     */
    private DanmakuView mDanmakuView;
    private Button switcherBtn;
    private Button sendBtn;
    private EditText textEditText;
    private VideoView videoView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_open_danmaku_main);
        //实例化控件
        mDanmakuView = (DanmakuView) findViewById(R.id.danmakuView);
        switcherBtn = (Button) findViewById(R.id.switcher);
        sendBtn = (Button) findViewById(R.id.send);
        textEditText = (EditText) findViewById(R.id.text);
        videoView = (VideoView) findViewById(R.id.videoView);

        //设置相关播放视频
        setVideoView();

        //重点
        List<IDanmakuItem> list = initItems();
        //变成随机数据
        Collections.shuffle(list);

        //添加到弹幕控件里面
        mDanmakuView.addItem(list, true);
        switcherBtn.setOnClickListener(this);
        sendBtn.setOnClickListener(this);
    }

    /**
     * 播放视频想
     */
    private void setVideoView() {
    
    
        //设置准备好的监听
        videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
    
    
            @Override
            public void onPrepared(MediaPlayer mp) {
    
    
                videoView.start();//开始播放
            }
        });
        //设置播放完成
        videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
    
    
            @Override
            public void onCompletion(MediaPlayer mp) {
    
    
                videoView.start();//重新开始播放
            }
        });

        //设置播放出错
        videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
    
    
            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
    
    
                Toast.makeText(OpenDanmakuMainActivity.this, "播放出错了", Toast.LENGTH_SHORT).show();
                return true;
            }
        });

        //设置控制面板
        videoView.setMediaController(new MediaController(this));
        //设置播放地址
        videoView.setVideoPath("http://vfx.mtime.cn/Video/2016/12/12/mp4/161212190638286683_480.mp4");
//        videoView.setVideoPath("http://192.168.11.218:8080/oppo.mp4");

    }

    /**
     * 构建弹幕的数据集合
     * @return
     */
    private List<IDanmakuItem> initItems() {
    
    
        List<IDanmakuItem> list = new ArrayList<>();
        //创建100条文本的弹幕
        for (int i = 0; i < 100; i++) {
    
    
            IDanmakuItem item = new DanmakuItem(this, i + " : plain text danmuku", mDanmakuView.getWidth());
            list.add(item);
        }
        //创建100条文本带图片的弹幕
        String msg = " : text with image   ";
        for (int i = 0; i < 100; i++) {
    
    
            ImageSpan imageSpan = new ImageSpan(this, R.drawable.em);
            SpannableString spannableString = new SpannableString(i + msg);
            spannableString.setSpan(imageSpan, spannableString.length() - 2, spannableString.length() - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            IDanmakuItem item = new DanmakuItem(this, spannableString, mDanmakuView.getWidth(), 0, 0, 0, 1.5f);
            list.add(item);
        }
        return list;
    }

    @Override
    protected void onResume() {
    
    
        super.onResume();
        //显示弹幕
        mDanmakuView.show();
    }

    @Override
    protected void onPause() {
    
    
        super.onPause();
        //隐藏弹幕弹幕
        mDanmakuView.hide();
    }

    @Override
    protected void onDestroy() {
    
    
        super.onDestroy();
        //清除弹幕
        mDanmakuView.clear();
    }

    @Override
    public void onClick(View v) {
    
    
        switch (v.getId()) {
    
    
            case R.id.switcher:
                if (mDanmakuView.isPaused()) {
    
    
                    switcherBtn.setText(R.string.hide);
                    mDanmakuView.show();
                } else {
    
    
                    switcherBtn.setText(R.string.show);
                    mDanmakuView.hide();
                }
                break;
            case R.id.send:
                String input = textEditText.getText().toString();
                if (TextUtils.isEmpty(input)) {
    
    
                    Toast.makeText(OpenDanmakuMainActivity.this, R.string.empty_prompt, Toast.LENGTH_SHORT).show();
                } else {
    
    
                    IDanmakuItem item = new DanmakuItem(this, new SpannableString(input), mDanmakuView.getWidth(),0,R.color.my_item_color,0,1);
//                    IDanmakuItem item = new DanmakuItem(this, input, mDanmakuView.getWidth());
//                    item.setTextColor(getResources().getColor(R.color.my_item_color));
//                    item.setTextSize(14);
//                    item.setTextColor(textColor);
                    mDanmakuView.addItemToHead(item);
                }
                textEditText.setText("");
                break;
        }
    }
}
  • layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/default_bg"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="200dp"
        android:background="@color/default_bg">

        <!-- put a VideoView/SurfaceView here if you want show Danmaku on top of video-->
        <VideoView
            android:id="@+id/videoView"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:background="@color/bg_color" />

        <com.opendanmaku.DanmakuView
            android:id="@+id/danmakuView"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            app:end_Y_offset="0.8"
            app:max_row="4"
            app:max_running_per_row="2"
            app:pick_interval="1000"
            app:show_debug="false"
            app:start_Y_offset="0.2" />
    </FrameLayout>


    <Button
        android:id="@+id/switcher"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_margin="10dp"
        android:text="hide" />


    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="10dp">

        <EditText
            android:id="@+id/text"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:layout_weight="1"
            android:hint="input text here" />

        <Button
            android:id="@+id/send"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:text="send" />
    </LinearLayout>
</LinearLayout>
  • Note: You can add a barrage to the screen through the above steps, but the barrage is like a view that will cover the content of the videoview, so you need to change the source code of OpenDanmaku.
  • As follows: Find the onDraw method in the DanmakuView.java file and make the following changes
@Override
    protected void onDraw(Canvas canvas) {
    
    
        super.onDraw(canvas);
        if (status == STATUS_RUNNING) {
    
    
            try {
    
    
//                canvas.drawColor(Color.TRANSPARENT);//将这句代码注释掉添加下面一句代码即可
                canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
                //先绘制正在播放的弹幕
                for (int i = 0; i < mChannelMap.size(); i++) {
    
    
                    ArrayList<IDanmakuItem> list = mChannelMap.get(i);
                    for (Iterator<IDanmakuItem> it = list.iterator(); it.hasNext(); ) {
    
    
                        IDanmakuItem item = it.next();
                        if (item.isOut()) {
    
    
                            it.remove();
                        } else {
    
    
                            item.doDraw(canvas);
                        }
                    }
                }

                //检查是否需要加载播放下一个弹幕
                if (System.currentTimeMillis() - previousTime > mPickItemInterval) {
    
    
                    previousTime = System.currentTimeMillis();
//                    Log.d(TAG, "start pick new item..");
                    IDanmakuItem di = mWaitingItems.pollFirst();
                    if (di != null) {
    
    
                        int indexY = findVacant(di);
                        if (indexY >= 0) {
    
    
//                            Log.d(TAG, "find vacant channel");
                            di.setStartPosition(canvas.getWidth() - 2, mChannelY[indexY]);
//                            Log.d(TAG, "draw new, text:" + di.getText());
                            //Log.d(TAG, String.format("doDraw, position,x=%s,y=%s", c.getWidth() - 1, mChannelY[indexY]));
                            di.doDraw(canvas);
                            mChannelMap.get(indexY).add(di);//不要忘记加入正运行的维护的列表中

                        } else {
    
    
//                                Log.d(TAG, "Not find vacant channel, add it back");
                            addItemToHead(di);//找不到可以播放的弹道,则把它放回列表中
                        }

                    } else {
    
    
                        //no item 弹幕播放完毕,
                    }

                }

                if (mShowDebug) {
    
    
                    int fps = (int) fps();
                    canvas.drawText("FPS:" + fps, 5f, 20f, fpsPaint);
                    for (float yp : lines) {
    
    
                        canvas.drawLine(0f, yp, getWidth(), yp, fpsPaint);
                    }
                }

            } catch (Exception e) {
    
    
                e.printStackTrace();
            }
            invalidate();

        } else {
    
    //暂停或停止,隐藏弹幕内容
            canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        }
    }

Guess you like

Origin blog.csdn.net/qq_36828822/article/details/104186432