今天簡單介紹一下開源的彈幕引擎---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