版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Android弹幕实现:基于B站弹幕开源系统(1)Android弹幕实现:基于B站弹幕开源系统(1)如今的视频播放,流行在视频上飘弹幕。这里面做的相对比较成熟、稳定、使用量较多的弹幕系统,当推B站的弹幕系统,B站的弹幕系统已经作为开源项目在github上,其项目地址:/Bilibili/DanmakuFlameMaster
以B站开源的弹幕项目为基础,现给出一个简单的例子,实现发送简单的文本弹幕。
第一步,首先要在Android的build.gradle文件中引入B站的项目:[plain]
\o"viewplain"viewplain
\o"copy"copyrepositories
{
jcenter()
}
dependencies
{
compile
'com.github.ctiao:DanmakuFlameMaster:0.7.3'
compile
'com.github.ctiao:ndkbitmap-armv7a:0.7.3'
}
第二步,写一个布局文件,引入B站的弹幕view:[html]
\o"viewplain"viewplain
\o"copy"copy<?xml
version="1.0"
encoding="utf-8"?>
<LinearLayout
xmlns:android="/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="显示弹幕"
/>
<Button
android:id="@+id/hide"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="隐藏弹幕"
/>
<Button
android:id="@+id/sendText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送文本弹幕"
/>
<Button
android:id="@+id/pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="暂停弹幕"
/>
<Button
android:id="@+id/resume"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="重启弹幕"
/>
<master.flame.danmaku.ui.widget.DanmakuView
android:id="@+id/danmakuView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
第三步,写上层Java代码(该处java代码改造自B站弹幕github上的demo代码):[java]
\o"viewplain"viewplain
\o"copy"copypackage
zhangphil.danmaku;
import
android.app.Activity;
import
android.graphics.Color;
import
android.os.Bundle;
import
android.util.Log;
import
android.view.View;
import
android.widget.Button;
import
java.util.HashMap;
import
master.flame.danmaku.danmaku.model.BaseDanmaku;
import
master.flame.danmaku.danmaku.model.DanmakuTimer;
import
master.flame.danmaku.danmaku.model.IDisplayer;
import
master.flame.danmaku.danmaku.model.android.DanmakuContext;
import
master.flame.danmaku.ui.widget.DanmakuView;
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)
{
//每点击一次按钮发送一条弹幕
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();
//
设置最大显示行数
HashMap<Integer,
Integer>
maxLinesPair
=
new
HashMap<>();
maxLinesPair.put(BaseDanmaku.TYPE_SCROLL_RL,
8);
//
滚动弹幕最大显示5行
//
设置是否禁止重叠
HashMap<Integer,
Boolean>
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数据格式实现。该类写好基本就可以拿来稳定使用,现给出AcFunDanmakuParser的全部源代码:[java]
\o"viewplain"viewplain
\o"copy"copypackage
zhangphil.danmaku;
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
=
(
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 汽车发动机再制造装调工岗位安全考核试卷含答案
- 银幕制造工操作规范测试考核试卷含答案
- 初中物理八年级上册《质量》教学设计
- 初中体育与健康七年级双杠分腿坐前滚翻分腿坐教学设计
- 九年级物理教学设计:简单机械核心模型与解题方法专题复习
- 小学六年级英语“不定代词与指示代词”专题复习教学设计
- 统编版高一语文必修下册《林教头风雪山神庙》教学设计
- 高中地理选择性必修二“多种多样的区域”教学设计
- 高中英语译林版必修一Unit 3 Getting along with others语法教学设计
- 小学四年级劳动教育浙教版“缝香袋”教学设计与实践探索
- 广东深圳市龙岗区实验学校2026-2027学年度第一学期 七年级9月阶段性反馈英语试卷(含答案)
- 2026年鞍山市台安县事业单位面向应届毕业生公开招聘高层次急需紧缺人才15人笔试模拟试题及答案详解
- 2026年静疗专科护士考核考试题库(含答案)
- 2026中控证考试题库及答案解析
- 2026年版概论测试题及答案
- (2026年版)糖尿病患者合并心血管疾病诊治专家共识
- 2025年10月自考00230合同法试题及答案含评分参考
- 纪念抗美援朝队会课件
- 淹萝卜教学课件
- 机械制造技术课程设计-倒档变速叉工艺及铣端面夹具设计
- 内科诊所规章制度
评论
0/150
提交评论