第一步蝗拿,首先要在Android的build.gradle文件中引入B站的項目:
repositories {
? ? jcenter()
}
導入依賴
compile 'com.github.ctiao:DanmakuFlameMaster:0.7.3'
compile 'com.github.ctiao:ndkbitmap-armv7a:0.7.3'
第二步臀脏,寫一個布局文件崩溪,引入B站的彈幕view:
? ? android:layout_width="match_parent"
? ? android:layout_height="match_parent"
? ? android:orientation="vertical">
? ? ? ? android:id="@+id/show"
? ? ? ? android:layout_width="wrap_content"
? ? ? ? android:layout_height="wrap_content"
? ? ? ? android:text="顯示彈幕" />
? ? ? ? android:id="@+id/hide"
? ? ? ? android:layout_width="wrap_content"
? ? ? ? android:layout_height="wrap_content"
? ? ? ? android:text="隱藏彈幕" />
? ? ? ? android:id="@+id/sendText"
? ? ? ? android:layout_width="wrap_content"
? ? ? ? android:layout_height="wrap_content"
? ? ? ? android:text="發(fā)送文本彈幕" />
? ? ? ? android:id="@+id/pause"
? ? ? ? android:layout_width="wrap_content"
? ? ? ? android:layout_height="wrap_content"
? ? ? ? android:text="暫停彈幕" />
? ? ? ? android:id="@+id/resume"
? ? ? ? android:layout_width="wrap_content"
? ? ? ? android:layout_height="wrap_content"
? ? ? ? android:text="重啟彈幕" />
? ? ? ? android:id="@+id/danmakuView"
? ? ? ? android:layout_width="match_parent"
? ? ? ? android:layout_height="match_parent" />
第三步拭嫁,寫上層Java代碼(該處java代碼改造自B站彈幕github上的demo代碼):
public class MainActivity extends Activity {
? ? private DanmakuView mDanmakuView;
? ? private DanmakuContext mContext;
? ? private AcFunDanmakuParser mParser;
? ? @Override
? ? protected void onCreate(Bundle savedInstanceState) {
? ? ? ? super.onCreate(savedInstanceState);
? ? ? ? setContentView(R.layout.activity_main);
? ? ? ? mDanmakuView = (DanmakuView) findViewById(R.id.danmakuView);
? ? ? ? Button show = (Button) findViewById(R.id.show);
? ? ? ? Button hide = (Button) findViewById(R.id.hide);
? ? ? ? Button sendText = (Button) findViewById(R.id.sendText);
? ? ? ? Button pause = (Button) findViewById(R.id.pause);
? ? ? ? Button resume = (Button) findViewById(R.id.resume);
? ? ? ? show.setOnClickListener(new View.OnClickListener() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onClick(View v) {
? ? ? ? ? ? ? ? mDanmakuView.show();
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? hide.setOnClickListener(new View.OnClickListener() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onClick(View v) {
? ? ? ? ? ? ? ? mDanmakuView.hide();
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? sendText.setOnClickListener(new View.OnClickListener() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onClick(View v) {
? ? ? ? ? ? ? ? //每點擊一次按鈕發(fā)送一條彈幕
? ? ? ? ? ? ? ? sendTextMessage();
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? pause.setOnClickListener(new View.OnClickListener() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onClick(View v) {
? ? ? ? ? ? ? ? mDanmakuView.pause();
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? resume.setOnClickListener(new View.OnClickListener() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onClick(View v) {
? ? ? ? ? ? ? ? mDanmakuView.resume();
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? init();
? ? }
? ? private void init() {
? ? ? ? mContext = DanmakuContext.create();
? ? ? ? // 設置最大顯示行數(shù)
? ? ? ? HashMap maxLinesPair = new HashMap<>();
? ? ? ? maxLinesPair.put(BaseDanmaku.TYPE_SCROLL_RL, 8); // 滾動彈幕最大顯示5行
? ? ? ? // 設置是否禁止重疊
? ? ? ? HashMap overlappingEnablePair = new HashMap<>();
? ? ? ? overlappingEnablePair.put(BaseDanmaku.TYPE_SCROLL_RL, true);
? ? ? ? overlappingEnablePair.put(BaseDanmaku.TYPE_FIX_TOP, true);
? ? ? ? mContext.setDanmakuStyle(IDisplayer.DANMAKU_STYLE_STROKEN, 10) //描邊的厚度
? ? ? ? ? ? ? ? .setDuplicateMergingEnabled(false)
? ? ? ? ? ? ? ? .setScrollSpeedFactor(1.2f) //彈幕的速度葱椭。注意鸿秆!此值越小廓鞠,速度越快!值越大谣旁,速度越慢床佳。// by phil
? ? ? ? ? ? ? ? .setScaleTextSize(1.2f)? //縮放的值
? ? ? ? ? ? ? ? //.setCacheStuffer(new SpannedCacheStuffer(), mCacheStufferAdapter) // 圖文混排使用SpannedCacheStuffer
//? ? ? ? .setCacheStuffer(new BackgroundCacheStuffer())? // 繪制背景使用BackgroundCacheStuffer
? ? ? ? ? ? ? ? .setMaximumLines(maxLinesPair)
? ? ? ? ? ? ? ? .preventOverlapping(overlappingEnablePair);
? ? ? ? mParser = new AcFunDanmakuParser();
? ? ? ? mDanmakuView.prepare(mParser, mContext);
? ? ? ? //mDanmakuView.showFPS(true);
? ? ? ? mDanmakuView.enableDanmakuDrawingCache(true);
? ? ? ? if (mDanmakuView != null) {
? ? ? ? ? ? mDanmakuView.setCallback(new master.flame.danmaku.controller.DrawHandler.Callback() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void updateTimer(DanmakuTimer timer) {
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void drawingFinished() {
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void danmakuShown(BaseDanmaku danmaku) {
? ? ? ? ? ? ? ? ? ? Log.d("彈幕文本", "danmakuShown text=" + danmaku.text);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void prepared() {
? ? ? ? ? ? ? ? ? ? mDanmakuView.start();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });
? ? ? ? }
? ? }
? ? private void sendTextMessage() {
? ? ? ? addDanmaku(true);
? ? }
? ? private void addDanmaku(boolean islive) {
? ? ? ? BaseDanmaku danmaku = mContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL);
? ? ? ? if (danmaku == null || mDanmakuView == null) {
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? danmaku.text = "zhangphil @ csdn :" + System.currentTimeMillis();
? ? ? ? danmaku.padding = 5;
? ? ? ? danmaku.priority = 0;? // 可能會被各種過濾器過濾并隱藏顯示
? ? ? ? danmaku.isLive = islive;
? ? ? ? danmaku.setTime(mDanmakuView.getCurrentTime() + 1200);
? ? ? ? danmaku.textSize = 20f * (mParser.getDisplayer().getDensity() - 0.6f); //文本彈幕字體大小
? ? ? ? danmaku.textColor = getRandomColor(); //文本的顏色
? ? ? ? danmaku.textShadowColor = getRandomColor(); //文本彈幕描邊的顏色
? ? ? ? //danmaku.underlineColor = Color.DKGRAY; //文本彈幕下劃線的顏色
? ? ? ? danmaku.borderColor = getRandomColor(); //邊框的顏色
? ? ? ? mDanmakuView.addDanmaku(danmaku);
? ? }
? ? @Override
? ? protected void onPause() {
? ? ? ? super.onPause();
? ? ? ? if (mDanmakuView != null && mDanmakuView.isPrepared()) {
? ? ? ? ? ? mDanmakuView.pause();
? ? ? ? }
? ? }
? ? @Override
? ? protected void onResume() {
? ? ? ? super.onResume();
? ? ? ? if (mDanmakuView != null && mDanmakuView.isPrepared() && mDanmakuView.isPaused()) {
? ? ? ? ? ? mDanmakuView.resume();
? ? ? ? }
? ? }
? ? @Override
? ? protected void onDestroy() {
? ? ? ? super.onDestroy();
? ? ? ? if (mDanmakuView != null) {
? ? ? ? ? ? // dont forget release!
? ? ? ? ? ? mDanmakuView.release();
? ? ? ? ? ? mDanmakuView = null;
? ? ? ? }
? ? }
? ? /**
? ? * 從一系列顏色中隨機選擇一種顏色
? ? *
? ? * @return
? ? */
? ? private int getRandomColor() {
? ? ? ? int[] colors = {Color.RED, Color.YELLOW, Color.BLUE, Color.GREEN, Color.CYAN, Color.BLACK, Color.DKGRAY};
? ? ? ? int i = ((int) (Math.random() * 10)) % colors.length;
? ? ? ? return colors[i];
? ? }
}
第四步 :使用了一個叫做AcFunDanmakuParser的彈幕parser,這個解析器得自己寫榄审,自己基于json數(shù)據(jù)格式實現(xiàn)砌们。該類寫好基本就可以拿來穩(wěn)定使用,現(xiàn)給出AcFunDanmakuParser的全部源代碼:
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import master.flame.danmaku.danmaku.model.BaseDanmaku;
import master.flame.danmaku.danmaku.model.android.Danmakus;
import master.flame.danmaku.danmaku.parser.BaseDanmakuParser;
import master.flame.danmaku.danmaku.parser.android.JSONSource;
import master.flame.danmaku.danmaku.util.DanmakuUtils;
/**
* Created by phil on 2017/3/29.
*/
public class AcFunDanmakuParser extends BaseDanmakuParser {
? ? public AcFunDanmakuParser() {
? ? }
? ? public Danmakus parse() {
? ? ? ? if (this.mDataSource != null && this.mDataSource instanceof JSONSource) {
? ? ? ? ? ? JSONSource jsonSource = (JSONSource) this.mDataSource;
? ? ? ? ? ? return this.doParse(jsonSource.data());
? ? ? ? } else {
? ? ? ? ? ? return new Danmakus();
? ? ? ? }
? ? }
? ? private Danmakus doParse(JSONArray danmakuListData) {
? ? ? ? Danmakus danmakus = new Danmakus();
? ? ? ? if (danmakuListData != null && danmakuListData.length() != 0) {
? ? ? ? ? ? for (int i = 0; i < danmakuListData.length(); ++i) {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? JSONObject e = danmakuListData.getJSONObject(i);
? ? ? ? ? ? ? ? ? ? if (e != null) {
? ? ? ? ? ? ? ? ? ? ? ? danmakus = this._parse(e, danmakus);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? } catch (JSONException var5) {
? ? ? ? ? ? ? ? ? ? var5.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? return danmakus;
? ? ? ? } else {
? ? ? ? ? ? return danmakus;
? ? ? ? }
? ? }
? ? private Danmakus _parse(JSONObject jsonObject, Danmakus danmakus) {
? ? ? ? if (danmakus == null) {
? ? ? ? ? ? danmakus = new Danmakus();
? ? ? ? }
? ? ? ? if (jsonObject != null && jsonObject.length() != 0) {
? ? ? ? ? ? for (int i = 0; i < jsonObject.length(); ++i) {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? String c = jsonObject.getString("c");
? ? ? ? ? ? ? ? ? ? String[] values = c.split(",");
? ? ? ? ? ? ? ? ? ? if (values.length > 0) {
? ? ? ? ? ? ? ? ? ? ? ? int type = Integer.parseInt(values[2]);
? ? ? ? ? ? ? ? ? ? ? ? if (type != 7) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? long time = (long) (Float.parseFloat(values[0]) * 1000.0F);
? ? ? ? ? ? ? ? ? ? ? ? ? ? int color = Integer.parseInt(values[1]) | -16777216;
? ? ? ? ? ? ? ? ? ? ? ? ? ? float textSize = Float.parseFloat(values[3]);
? ? ? ? ? ? ? ? ? ? ? ? ? ? BaseDanmaku item = this.mContext.mDanmakuFactory.createDanmaku(type, this.mContext);
? ? ? ? ? ? ? ? ? ? ? ? ? ? if (item != null) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? item.setTime(time);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? item.textSize = textSize * (this.mDispDensity - 0.6F);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? item.textColor = color;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? item.textShadowColor = color <= -16777216 ? -1 : -16777216;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DanmakuUtils.fillText(item, jsonObject.optString("m", "...."));
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? item.index = i;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? item.setTimer(this.mTimer);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? danmakus.addItem(item);
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? } catch (JSONException var13) {
? ? ? ? ? ? ? ? } catch (NumberFormatException var14) {
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? return danmakus;
? ? ? ? } else {
? ? ? ? ? ? return danmakus;
? ? ? ? }
? ? }
}
詳情:網(wǎng)址:https://blog.csdn.net/zhangphil/article/details/68067100