android 直播弹幕,在使用之前,如果有人对DanmakuFlameMaster还不了解怎么用的话,可以参考郭霖的这个博客郭霖的弹幕功能实现的博客.
但是在这里我还是建议大家直接看DanmakuFlameMaster的官方Demo,因为版本的迭代,而上面这篇博客某些地方Api已经过时.
- 下面借助郭大神博客的一张图:
- 在这样图中我们可以看到VoideView在最底层 -> 弹幕VIew -操作View
- VoideView :只有播放视频的api,毫无交互操作
- 弹幕View : 显示弹幕view, 弹幕有可能需要点击效果
- 操作View : 双击:播放/暂停 , 单点:显示/隐藏 整个操作的VIew , 左上滑 +亮度 , 左滑 +声音.
那么问题来了,弹幕需要点击,那么就会拦截按下, 操作View也需要点击和双击,也会拦截按下.
下面就是解决这个问题的方法: 思路:既然两个都需要拦截点击事件,那么就直接让两个View的setOnTouchListener合并成一个setOnTouchListener,但是这里有两个问题:
- 合并到谁: 合并到DanmakuFlameMaster库的DanmakuView
- DanmakuFlameMaster是用implementation'com.github.ctiao:DanmakuFlameMaster:0.9.25'依赖的,怎么样来解决框架内部的setOnTouchListener事件呢? 答案:反射.
/*
master.flame.danmaku.ui.widget.DanmakuView 的源码,可以看到使用自定义TouchHelper,源码里面直接拦截了
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean isEventConsumed = mTouchHelper.onTouchEvent(event);
if (!isEventConsumed) {
return super.onTouchEvent(event);
}
return isEventConsumed;
}
/*master.flame.danmaku.ui.widget.DanmakuTouchHelper,可以看到源码里面onDown方法只要设置OnDanmakuClickListener
,那么就返回true,这样是有问题的,不管是把DanmakuView覆盖在VoideControlBox上,还是在VoideControlBox
下都被令另外一个View 的事件出问题.*/
private final android.view.GestureDetector.OnGestureListener mOnGestureListener = new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDown(MotionEvent event) {
if (danmakuView != null) {
IDanmakuView.OnDanmakuClickListener onDanmakuClickListener = danmakuView.getOnDanmakuClickListener();
if (onDanmakuClickListener != null) {
mXOff = danmakuView.getXOff();
mYOff = danmakuView.getYOff();
return true;
}
}
return false;
}
//....省略了部分代码
};
/**
解决办法,反射获取mTouchHelper,模拟onTouchEvent();
然后把自己的VoideControlBox的一些事件也交给setOnTouchListener来处理,下面请看代码
*/
DanmakuTouchHelper mTouchHelper;
try {
Field field = mPlayDanmakuView.getClass().getDeclaredField("mTouchHelper");
field.setAccessible(true);
Object obj = field.get(mPlayDanmakuView);
if (obj instanceof DanmakuTouchHelper) {
mTouchHelper = (DanmakuTouchHelper) obj;
}
} catch (Exception e) {
e.printStackTrace();
}
//mPlayDanmakuView 这是弹幕View 的对象.
mPlayDanmakuView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
//ControlBox 的事件处理返回
boolean isEvent = mPlayerHelper.mGestureDetector.onTouchEvent(event);
boolean isEventConsumed = false;
// 如果反射拿到了mTouchHelper ,执行onTouchEvent方法.
if (mTouchHelper != null) {
isEventConsumed = mTouchHelper.onTouchEvent(event);
}
//如果是ControlBox返回为true 或者是弹幕事件返回为true, 消费该事件
if (isEvent || isEventConsumed) {
return true;
}
// 处理手势结束, 取消一些如音量View,亮度View
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_UP:
mPlayerHelper.endGesture();
break;
}
return true;
}
});
- 好了,如果有朋友没懂的可以加我QQ 97149859咨询.
复制代码