OpenDanmaku實現彈幕效果

一、OpenDanmaku簡介

                1.OpenDanmaku介紹

                        OpenDanmaku是Android中第三方的彈幕控件,在播放視頻和直播軟件中過程中彈出用戶的評論,並且以滾動的方式顯示。

                2.下載地址

                            https://github.com/linsea/OpenDanmaku

                3.項目依賴

Gradle
   dependencies {
                compile 'com.linsea:opendanmaku:1.0.0@aar'
         }
//或者引用本地lib
compile project(':opendanmaku')

            

二、OpenDanmaku使用步驟

                 1.佈局文件

<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">

    <include layout="@layout/titlebar"/>

    <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="@string/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="@string/text_hint" />

        <Button
            android:id="@+id/send"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:text="@string/send" />

    </LinearLayout>
</LinearLayout>

 

                2.彈幕邏輯代碼

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 TextView tv_title;
    private VideoView videoView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_opendanmaku_main);
        tv_title = (TextView) findViewById(R.id.tv_title);
        tv_title.setText("Opendanmaku彈幕");
        //實例化控件
        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.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                videoView.start();
            }
        });
        videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                videoView.start();

            }
        });

//        videoView.setVideoPath("http://10.0.2.2:8080/mp4/161122105613271790_480.mp4");
        videoView.setVideoPath("http://10.0.2.2:8080/oppo.mp4");

        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));
    }

    private List<IDanmakuItem> initItems() {
        List<IDanmakuItem> list = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            IDanmakuItem item = new DanmakuItem(this, i + " : plain text danmuku", mDanmakuView.getWidth());
            list.add(item);
        }

        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;
        }
    }
}

 

                3.在視頻上用OpenDanmaku顯示彈幕

                    設置視頻路徑:http://api.m.mtime.cn/PageSubArea/TrailerList.api

                4.解決彈幕把視頻遮擋的問題

    @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);
        }
    }

 

 看到此,是不是接的OpenDanmaku的簡單使用是不是很簡單,謝謝瀏覽!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章