先看郭霖大神播客:
http://blog.youkuaiyun.com/sinyu890807/article/details/51933728
我的Demo只是在此基础上
1、加了隐藏和显示的两个按钮
2、点击send后关闭小键盘
详细扩展功能可看:
http://m.blog.youkuaiyun.com/article/details?id=51056646
和官方sample中的MainActivity中代码
哔哩哔哩开源的弹幕效果库:DanmakuFlameMaster
https://github.com/Bilibili/DanmakuFlameMaster
备注:
这个Demo演示的是自己随机生成的弹幕,如果在真实的app中,要基于app中的即时消息模块的聊天室,要获得聊天室中的成员发送的消息内容、消息时间(根据消息时间确定弹幕出现在屏幕上的时间)等,聊天室中每当有消息发送,调用添加弹幕的方法向弹幕view中添加弹幕
布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.sign.danmutest.MainActivity">
<VideoView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"/>
<master.flame.danmaku.ui.widget.DanmakuView
android:id="@+id/danku_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:visibility="gone"
>
<Button
android:id="@+id/btnHide"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="hide"
/>
<Button
android:id="@+id/btnShow"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="show"
/>
<EditText
android:id="@+id/edtText"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
/>
<Button
android:id="@+id/btnSend"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="send"
/>
</LinearLayout>
</RelativeLayout>
代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private VideoView videoView;
private DanmakuView danmakuView;
private LinearLayout ll ;
private EditText edtText;
private Button btnHide,btnShow,btnSend;
private boolean showDanmaku;
private DanmakuContext danmakuContext;
private BaseDanmakuParser parser = new BaseDanmakuParser() {
@Override
protected IDanmakus parse() {
return new Danmakus();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ll = (LinearLayout) findViewById(R.id.ll);//操作栏
edtText = (EditText) findViewById(R.id.edtText);//输入框
btnHide = (Button) findViewById(R.id.btnHide);//隐藏按钮
btnShow = (Button) findViewById(R.id.btnShow);//显示按钮
btnSend = (Button) findViewById(R.id.btnSend);//发送
btnHide.setOnClickListener(this);
btnShow.setOnClickListener(this);
btnSend.setOnClickListener(this);
videoView = (VideoView) findViewById(R.id.video_view);
// 播放本地的abc.mp4
videoView.setVideoPath(Environment.getExternalStorageDirectory() + "/abc.mp4");
videoView.start();
danmakuView = (DanmakuView) findViewById(R.id.danku_view);
danmakuView.enableDanmakuDrawingCache(true);//提升绘制效率
danmakuView.setCallback(new DrawHandler.Callback() {
@Override
public void prepared() {
showDanmaku = true;
danmakuView.start();
generateSomeDanmaku();
}
@Override
public void updateTimer(DanmakuTimer timer) {
}
@Override
public void drawingFinished() {
}
});
// DanmakuContext可以用于对弹幕的各种全局配置进行设定,如设置字体、设置最大显示行数等
danmakuContext = DanmakuContext.create();
// 有了DanmakuContext和BaseDanmakuParser,接下来我们就可以调用DanmakuView的prepare()方法来进行准备,
// 准备完成后会自动调用刚才设置的回调函数中的prepared()方法
danmakuView.prepare(parser, danmakuContext);
// 点击danmukuView,如果下方的操作栏处于显示,则设置为gone,反之。。。
danmakuView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(ll.getVisibility() == View.VISIBLE){
ll.setVisibility(View.GONE);
}else{
ll.setVisibility(View.VISIBLE);
}
}
});
// 由于系统输入法弹出的时候会导致焦点丢失,从而退出沉浸式模式,因此这里还对系统全局的UI变化进行了监听,保证程序一直可以处于沉浸式模式。
getWindow().getDecorView().setOnSystemUiVisibilityChangeListener (new View.OnSystemUiVisibilityChangeListener() {
@Override
public void onSystemUiVisibilityChange(int visibility) {
if (visibility == View.SYSTEM_UI_FLAG_VISIBLE) {
onWindowFocusChanged(true);
}
}
});
}
// 用于向DanmakuView中添加一条弹幕消息
// withBorder参数,这个参数用于指定弹幕消息是否带有边框,这样才好将自己发送的弹幕和别人发送的弹幕进行区分
private void addDanmaku(String content, boolean withBorder) {
BaseDanmaku danmaku = danmakuContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL);
danmaku.text = content;
danmaku.padding = 5;
danmaku.textSize = sp2px(20);
danmaku.textColor = Color.WHITE;
danmaku.time = danmakuView.getCurrentTime();
if (withBorder) {
danmaku.borderColor = Color.BLUE;//边框颜色
danmaku.textColor = Color.YELLOW;//文字颜色
}
danmakuView.addDanmaku(danmaku);
}
// 随机生成一些弹幕以供测试
private void generateSomeDanmaku() {
new Thread(){
@Override
public void run() {
super.run();
while(showDanmaku) {
int time = new Random().nextInt(300);
String content = "" + time + time;
addDanmaku(content, false);//添加随机生成的弹幕,false为没有边框
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
/**
* sp转px的方法。
*/
public int sp2px(float spValue) {
final float fontScale = getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
@Override
protected void onPause() {
super.onPause();
if (danmakuView != null && danmakuView.isPrepared()) {
danmakuView.pause();
}
}
@Override
protected void onResume() {
super.onResume();
if (danmakuView != null && danmakuView.isPrepared() && danmakuView.isPaused()) {
danmakuView.resume();
}
}
// 退出时释放资源
@Override
protected void onDestroy() {
super.onDestroy();
showDanmaku = false;
if (danmakuView != null) {
danmakuView.release();
danmakuView = null;
}
}
// 设置界面为沉浸式
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus && Build.VERSION.SDK_INT >= 19) {
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
}
@Override
public void onClick(View v) {
// 弹幕view不为空,且弹幕view
if(danmakuView != null && danmakuView.isPrepared()){
switch (v.getId()){
case R.id.btnHide:
// 隐藏弹幕
danmakuView.hide();
break;
case R.id.btnShow:
// 显示弹幕
danmakuView.show();
break;
case R.id.btnSend:
String content = edtText.getText().toString();
if(!TextUtils.isEmpty(content)){
addDanmaku(content,true);//发送自己的弹幕,true为自己发送的弹幕,可以根据此标记设置字体颜色及边框
edtText.setText("");//让输入框为空
}
//getCurrentFocus()是获取当前activity中获得焦点的view
View v1 = getCurrentFocus();
if(v1 != null){
//隐藏软键盘
((InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(v.getWindowToken(),InputMethodManager.HIDE_NOT_ALWAYS);
}
break;
}
}
}
}