實現(xiàn)簡單的彈幕

第一步蝗拿,首先要在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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末搁进,一起剝皮案震驚了整個濱河市浪感,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌饼问,老刑警劉巖影兽,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異莱革,居然都是意外死亡峻堰,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進店門盅视,熙熙樓的掌柜王于貴愁眉苦臉地迎上來茧妒,“玉大人,你說我怎么就攤上這事左冬。” “怎么了纸型?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵拇砰,是天一觀的道長。 經(jīng)常有香客問我狰腌,道長除破,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任琼腔,我火速辦了婚禮瑰枫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘丹莲。我一直安慰自己光坝,他們只是感情好,可當我...
    茶點故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布甥材。 她就那樣靜靜地躺著盯另,像睡著了一般。 火紅的嫁衣襯著肌膚如雪洲赵。 梳的紋絲不亂的頭發(fā)上鸳惯,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天商蕴,我揣著相機與錄音,去河邊找鬼芝发。 笑死绪商,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的辅鲸。 我是一名探鬼主播格郁,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼瓢湃!你這毒婦竟也來了理张?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤绵患,失蹤者是張志新(化名)和其女友劉穎雾叭,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體落蝙,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡织狐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了筏勒。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片移迫。...
    茶點故事閱讀 39,764評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖管行,靈堂內(nèi)的尸體忽然破棺而出厨埋,到底是詐尸還是另有隱情,我是刑警寧澤捐顷,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布荡陷,位于F島的核電站,受9級特大地震影響迅涮,放射性物質(zhì)發(fā)生泄漏废赞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一叮姑、第九天 我趴在偏房一處隱蔽的房頂上張望唉地。 院中可真熱鬧,春花似錦传透、人聲如沸耘沼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽耕拷。三九已至,卻和暖如春托享,著一層夾襖步出監(jiān)牢的瞬間骚烧,已是汗流浹背浸赫。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留赃绊,地道東北人既峡。 一個月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像碧查,于是被迫代替她去往敵國和親运敢。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,665評論 2 354

推薦閱讀更多精彩內(nèi)容