淺談DanmakuView


  今天簡單介紹一下開源的彈幕引擎---danmakuView
  使用之前在build.gradle里面添加下面這一條(目前我使用的工具是AndroidStudio 3.1.2)

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

  庫導入完成之后一定不要忘記 Sync now (emmmm,相信你應該不會忘)

1.設計布局

  首先設計布局,布局文件就很好理解了,采用了谷歌最新的ConstraintLayout布局,簡單實用,內部放置一個VideoView用來播放視頻,EditText用來輸入彈幕,Button用來發送彈幕,介紹Over

<?xml version="1.0" encoding="utf-8"?>  
<android.support.constraint.ConstraintLayout  
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:id="@+id/activity_main"  
android:layout_width="match_parent"  
android:layout_height="match_parent"  
android:background="#000"  
tools:context=".MainActivity">  

<VideoView
    android:id="@+id/videoview"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

<master.flame.danmaku.ui.widget.DanmakuView
    android:id="@+id/danmaku"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginBottom="8dp"
    android:layout_marginLeft="8dp"
    android:layout_marginStart="8dp"
    android:layout_marginTop="8dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<LinearLayout
    android:id="@+id/ly_send"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:background="#FFF"
    android:orientation="horizontal"
    android:visibility="gone"
    app:layout_constraintBottom_toBottomOf="parent">

    <EditText
        android:id="@+id/et_text"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    <Button
        android:id="@+id/btn_send"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:text="發送" />
</LinearLayout>  
</android.support.constraint.ConstraintLayout>  

2.界面邏輯

  點擊屏幕,底部會顯示一個輸入框和一個發送按鈕,當輸入文字並點擊發送之后,屏幕上會出現一個藍色框,里面是剛剛輸入的文字,再次點擊屏幕,底部的輸入框和發送按鈕消失。Over

package com.project.software.company;

import android.graphics.Color;  
import android.net.Uri;  
import android.support.v7.app.AppCompatActivity;  
import android.os.Bundle;  
import android.text.TextUtils;  
import android.view.View;  
import android.widget.Button;  
import android.widget.EditText;  
import android.widget.LinearLayout;  
import android.widget.VideoView;  

import org.w3c.dom.Text;

import java.util.Random;

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.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 AppCompatActivity {

private boolean showDanmaku;
private DanmakuView danmakuView;
private DanmakuContext danmakuContext;
private Button sendButton;
private LinearLayout sendLayout;
private EditText editText;
private VideoView videoView;

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

//初始化界面控件
private void initView() {
    videoView = findViewById(R.id.videoview);
    sendLayout = findViewById(R.id.ly_send);
    sendButton = findViewById(R.id.btn_send);
    editText = findViewById(R.id.et_text);
    danmakuView = findViewById(R.id.danmaku);
}

//播放視頻
private void playVideo() {
    String uri = "android.resource://"+getPackageName()+"/"+R.raw.sun;
    if(uri !=null){
        videoView.setVideoURI(Uri.parse(uri));
        videoView.start();
    } else {
        videoView.getBackground().setAlpha(0);  //將背景設為透明
    }
}

//創建彈幕解析器
private BaseDanmakuParser parser = new BaseDanmakuParser() {
    @Override
    protected IDanmakus parse() {
        return new Danmakus();
    }
};

//初始化彈幕
private void initDanmaku(){
    danmakuView.setCallback(new DrawHandler.Callback() {   //設置回調函數
        @Override
        public void prepared() {
            showDanmaku = true;
            danmakuView.start(); //開始彈幕
            generateDanmakus(); //開始隨機生成彈幕方法
        }

        @Override
        public void updateTimer(DanmakuTimer timer) {
        }

        @Override
        public void drawingFinished() {
        }
    });
    danmakuContext = danmakuContext.create();
    danmakuView.enableDanmakuDrawingCache(true);  //提升屏幕繪制效率
    danmakuView.prepare(parser,danmakuContext);  //進行彈幕准備
    //為danmakuView設置點擊事件
    danmakuView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(sendLayout.getVisibility() == View.GONE){
                sendLayout.setVisibility(View.VISIBLE);   //顯示布局
            } else {
                sendLayout.setVisibility(View.GONE);  //隱藏布局
            }
        }
    });
    //為“發送”按鈕設置點擊事件
    sendButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String content = editText.getText().toString();
            if(!TextUtils.isEmpty(content)){
                addDanmaku(content,true);    //添加一條彈幕
                editText.setText("");
            }
        }
    });
}
//添加一條彈幕
//content 彈幕的具體內容
//border 彈幕是否有邊框
private void addDanmaku(String content,boolean border){
    //創建彈幕對象,TYPE_SCROLL_RL表示從左向右滾動的彈幕
    BaseDanmaku danmaku = danmakuContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL);
    danmaku.text = content;
    danmaku.padding = 6;
    danmaku.textSize = 30;
    danmaku.textColor = Color.WHITE;   //彈幕文字顏色
    danmaku.time = danmakuView.getCurrentTime();
    if(border){
        danmaku.borderColor = Color.BLUE;  //彈幕文字邊框的顏色
    }
    danmakuView.addDanmaku(danmaku);  //添加一條彈幕
}
/*
隨機生成一些彈幕的內容
*/
private void generateDanmakus(){
    new Thread(new Runnable() {
        @Override
        public void run() {
            while(showDanmaku){
                int num = new Random().nextInt(300);
                String content = ""+num;
                addDanmaku(content,false);
                try{
                    Thread.sleep(num);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }
        }
    }).start();
}

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

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

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

  下面簡單解釋一下代碼,在onCreate()方法中調用了三個初始化函數:
    1.initView()用來初始化界面控件
    2.playVideo()用來播放視頻(將視頻名稱為run的視頻放入raw文件夾下面)
    3.initDanmaku()用來初始化屏幕
  接下來是添加彈幕,在發送按鈕的點擊事件中調用了addDanmaku(content,true)函數,將輸入的內容傳遞過來,並在該函數中設置彈幕的一些屬性
  當然,光有自己輸入的彈幕是不美觀的,還要添加一些別人輸入的彈幕,這樣顯得更真實一些,generateDanmakus()函數就做到了這一點,不過這里選擇的是隨機生成一些數字
  剩下的onPause(),onResume(),onDestroy()方法就比較簡單,我就不一一介紹了
  最后,如果你覺得豎屏和標題欄不好看,可以在MainActivity的《activity》標簽(這里我不得不用中文符號,英文符號會出錯)中加入下面這一句,使之橫屏:
    android:screenOrientation="landscape"
  在《application》標簽(這里也是同樣的問題)中下入下面這一句,去掉標題欄:
    android:theme="@style/Theme.AppCompat.Light.NoActionBar"
  最最最后,貼圖看效果

  此文Over


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM