Android弹幕实现基于B站弹幕开源系统1.docx
《Android弹幕实现基于B站弹幕开源系统1.docx》由会员分享,可在线阅读,更多相关《Android弹幕实现基于B站弹幕开源系统1.docx(16页珍藏版)》请在冰豆网上搜索。
Android弹幕实现基于B站弹幕开源系统1
Android弹幕实现:
基于B站弹幕开源系统〔1〕
Android弹幕实现:
基于B站弹幕开源系统〔1〕
如今的视频播放,流行在视频上飘弹幕。
这里面做的相比照较成熟、稳定、使用量较多的弹幕系统,当推B站的弹幕系统,B站的弹幕系统已经作为开源项目在github上,其项目地址:
/Bilibili/DanmakuFlameMaster
以B站开源的弹幕项目为基础,现给出一个简单的例子,实现发送简单的文本弹幕。
第一步,首先要在Android的build.gradle文件中引入B站的项目:
[plain] viewplain copy
1.repositories {
2. jcenter()
3.}
4.
5.
6.dependencies {
7.
8. compile 'com.github.ctiao:
DanmakuFlameMaster:
0.7.3'
9. compile 'com.github.ctiao:
ndkbitmap-armv7a:
0.7.3'
10.
11.}
第二步,写一个布局文件,引入B站的弹幕view:
[html] viewplain copy
1.
xml version="1.0" encoding="utf-8"?
>
2.android="/apk/res/android"
3. android:
layout_width="match_parent"
4. android:
layout_height="match_parent"
5. android:
orientation="vertical">
6.
7.
第三步,写上层Java代码〔该处java代码改造自B站弹幕github上的demo代码〕:
[java] viewplain copy
1.package zhangphil.danmaku;
2.
3.import android.app.Activity;
4.import android.graphics.Color;
5.import android.os.Bundle;
6.import android.util.Log;
7.import android.view.View;
8.import android.widget.Button;
9.
10.import java.util.HashMap;
11.
12.import master.flame.danmaku.danmaku.model.BaseDanmaku;
13.import master.flame.danmaku.danmaku.model.DanmakuTimer;
14.import master.flame.danmaku.danmaku.model.IDisplayer;
15.import master.flame.danmaku.danmaku.model.android.DanmakuContext;
16.import master.flame.danmaku.ui.widget.DanmakuView;
17.
18.public class MainActivity extends Activity {
19.
20. private DanmakuView mDanmakuView;
21. private DanmakuContext mContext;
22.
23. private AcFunDanmakuParser mParser;
24.
25. @Override
26. protected void onCreate(Bundle savedInstanceState) {
27. super.onCreate(savedInstanceState);
28. setContentView(R.layout.activity_main);
29.
30. mDanmakuView = (DanmakuView) findViewById(R.id.danmakuView);
31.
32. Button show = (Button) findViewById(R.id.show);
33. Button hide = (Button) findViewById(R.id.hide);
34. Button sendText = (Button) findViewById(R.id.sendText);
35. Button pause = (Button) findViewById(R.id.pause);
36. Button resume = (Button) findViewById(R.id.resume);
37.
38. show.setOnClickListener(new View.OnClickListener() {
39. @Override
40. public void onClick(View v) {
41. mDanmakuView.show();
42. }
43. });
44.
45. hide.setOnClickListener(new View.OnClickListener() {
46. @Override
47. public void onClick(View v) {
48. mDanmakuView.hide();
49. }
50. });
51.
52. sendText.setOnClickListener(new View.OnClickListener() {
53. @Override
54. public void onClick(View v) {
55. //每点击一次按钮发送一条弹幕
56. sendTextMessage();
57. }
58. });
59.
60. pause.setOnClickListener(new View.OnClickListener() {
61. @Override
62. public void onClick(View v) {
63. mDanmakuView.pause();
64. }
65. });
66.
67. resume.setOnClickListener(new View.OnClickListener() {
68. @Override
69. public void onClick(View v) {
70. mDanmakuView.resume();
71. }
72. });
73.
74.
75. init();
76. }
77.
78. private void init() {
79. mContext = DanmakuContext.create();
80.
81. // 设置最大显示行数
82. HashMap maxLinesPair = new HashMap<>();
83. maxLinesPair.put(BaseDanmaku.TYPE_SCROLL_RL, 8); // 滚动弹幕最大显示5行
84.
85. // 设置是否禁止重叠
86. HashMap overlappingEnablePair = new HashMap<>();
87. overlappingEnablePair.put(BaseDanmaku.TYPE_SCROLL_RL, true);
88. overlappingEnablePair.put(BaseDanmaku.TYPE_FIX_TOP, true);
89.
90. mContext.setDanmakuStyle(IDisplayer.DANMAKU_STYLE_STROKEN, 10) //描边的厚度
91. .setDuplicateMergingEnabled(false)
92. .setScrollSpeedFactor(1.2f) //弹幕的速度。
注意!
此值越小,速度越快!
值越大,速度越慢。
// by phil
93. .setScaleTextSize(1.2f) //缩放的值
94. //.setCacheStuffer(new SpannedCacheStuffer(), mCacheStufferAdapter) // 图文混排使用SpannedCacheStuffer
95.// .setCacheStuffer(new BackgroundCacheStuffer()) // 绘制背景使用BackgroundCacheStuffer
96. .setMaximumLines(maxLinesPair)
97. .preventOverlapping(overlappingEnablePair);
98.
99. mParser = new AcFunDanmakuParser();
100. mDanmakuView.prepare(mParser, mContext);
101.
102. //mDanmakuView.showFPS(true);
103. mDanmakuView.enableDanmakuDrawingCache(true);
104.
105. if (mDanmakuView !
= null) {
106. mDanmakuView.setCallback(new master.flame.danmaku.controller.DrawHandler.Callback() {
107. @Override
108. public void updateTimer(DanmakuTimer timer) {
109. }
110.
111. @Override
112. public void drawingFinished() {
113.
114. }
115.
116. @Override
117. public void danmakuShown(BaseDanmaku danmaku) {
118. Log.d("弹幕文本", "danmakuShown text=" + danmaku.text);
119. }
120.
121. @Override
122. public void prepared() {
123. mDanmakuView.start();
124. }
125. });
126. }
127. }
128.
129. private void sendTextMessage() {
130. addDanmaku(true);
131. }
132.
133. private void addDanmaku(boolean islive) {
134. BaseDanmaku danmaku = mContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL);
135. if (danmaku == null || mDanmakuView == null) {
136. return;
137. }
138.
139. danmaku.text = "zhangphil @ csdn :
" + System.currentTimeMillis();
140. danmaku.padding = 5;
141. danmaku.priority = 0; // 可能会被各种过滤器过滤并隐藏显示
142. danmaku.isLive = islive;
143. danmaku.setTime(mDanmakuView.getCurrentTime() + 1200);
144. danmaku.textSize = 20f * (mParser.getDisplayer().getDensity() - 0.6f); //文本弹幕字体大小
145. danmaku.textColor = getRandomColor(); //文本的颜色
146. danmaku.textShadowColor = getRandomColor(); //文本弹幕描边的颜色
147. //danmaku.underlineColor = Color.DKGRAY; //文本弹幕下划线的颜色
148. danmaku.borderColor = getRandomColor(); //边框的颜色
149.
150. mDanmakuView.addDanmaku(danmaku);
151. }
152.
153. @Override
154. protected void onPause() {
155. super.onPause();
156. if (mDanmakuView !
= null && mDanmakuView.isPrepared()) {
157. mDanmakuView.pause();
158. }
159. }
160.
161. @Override
162. protected void onResume() {
163. super.onResume();
164. if (mDanmakuView !
= null && mDanmakuView.isPrepared() && mDanmakuView.isPaused()) {
165. mDanmakuView.resume();
166. }
167. }
168.
169. @Override
170. protected void onDestroy() {
171. super.onDestroy();
172. if (mDanmakuView !
= null) {
173. // dont forget release!
174. mDanmakuView.release();
175. mDanmakuView = null;
176. }
177. }
178.
179. /**
180. * 从一系列颜色中随机选择一种颜色
181. *
182. * @return
183. */
184. private int getRandomColor() {
185. int[] colors = {Color.RED, Color.YELLOW, Color.BLUE, Color.GREEN, Color.CYAN, Color.BLACK, Color.DKGRAY};
186. int i = ((int) (Math.random() * 10)) % colors.length;
187. return colors[i];
188. }
189.}
代码运行结果如图:
需要特别注意的是本例使用了一个叫做AcFunDanmakuParser的弹幕parser,这个解析器得自己写,自己基于json数据格式实现。
该类写好基本就可以拿来稳定使用,现给出AcFunDanmakuParser的全部源代码:
[java] viewplain copy
1.package zhangphil.danmaku;
2.
3.import org.json.JSONArray;
4.import org.json.JSONException;
5.import org.json.JSONObject;
6.
7.import master.flame.danmaku.danmaku.model.BaseDanmaku;
8.import master.flame.danmaku.danmaku.model.android.Danmakus;
9.import master.flame.danmaku.danmaku.parser.BaseDanmakuParser;
10.import master.flame.danmaku.danmaku.parser.android.JSONSource;
11.import master.flame.danmaku.danmaku.util.DanmakuUtils;
12.
13./**
14. * Created by phil on 2017/3/29.
15. */
16.
17.public class AcFunDanmakuParser extends