一、OpenDanmaku简介
1.OpenDanmaku介绍
OpenDanmaku是Android中第三方的弹幕控件,在播放视频和直播软件中过程中弹出用户的评论,并且以滚动的方式显示。
2.下载地址
https://github.com/linsea/OpenDanmaku
3.项目依赖
Gradle
dependencies {
compile 'com.linsea:opendanmaku:1.0.0@aar'
}
//或者引用本地lib
compile project(':opendanmaku')
二、OpenDanmaku使用步骤
1.布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/default_bg"
android:orientation="vertical"
tools:context=".MainActivity">
<include layout="@layout/titlebar"/>
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="200dp"
android:background="@color/default_bg">
<!-- put a VideoView/SurfaceView here if you want show Danmaku on top of video-->
<VideoView
android:id="@+id/videoView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/bg_color" />
<com.opendanmaku.DanmakuView
android:id="@+id/danmakuView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
app:end_Y_offset="0.8"
app:max_row="4"
app:max_running_per_row="2"
app:pick_interval="1000"
app:show_debug="false"
app:start_Y_offset="0.2" />
</FrameLayout>
<Button
android:id="@+id/switcher"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="10dp"
android:text="@string/hide" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp">
<EditText
android:id="@+id/text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="1"
android:hint="@string/text_hint" />
<Button
android:id="@+id/send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="@string/send" />
</LinearLayout>
</LinearLayout>
2.弹幕逻辑代码
import com.opendanmaku.DanmakuItem;
import com.opendanmaku.DanmakuView;
import com.opendanmaku.IDanmakuItem;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class OpendanmakuMainActivity extends AppCompatActivity implements View.OnClickListener{
private DanmakuView mDanmakuView;
private Button switcherBtn;
private Button sendBtn;
private EditText textEditText;
private TextView tv_title;
private VideoView videoView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_opendanmaku_main);
tv_title = (TextView) findViewById(R.id.tv_title);
tv_title.setText("Opendanmaku弹幕");
//实例化控件
mDanmakuView = (DanmakuView) findViewById(R.id.danmakuView);
switcherBtn = (Button) findViewById(R.id.switcher);
sendBtn = (Button) findViewById(R.id.send);
textEditText = (EditText) findViewById(R.id.text);
videoView = (VideoView) findViewById(R.id.videoView);
setVideoView();
//添加弹幕集合数据
List<IDanmakuItem> list = initItems();
//把数据进行随机排列
Collections.shuffle(list);
//添加到弹幕控件上
mDanmakuView.addItem(list, true);
switcherBtn.setOnClickListener(this);
sendBtn.setOnClickListener(this);
}
private void setVideoView() {
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
videoView.start();
}
});
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
videoView.start();
}
});
// videoView.setVideoPath("http://10.0.2.2:8080/mp4/161122105613271790_480.mp4");
videoView.setVideoPath("http://10.0.2.2:8080/oppo.mp4");
videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Toast.makeText(OpendanmakuMainActivity.this, "您的手机不支持播放该视频", Toast.LENGTH_SHORT).show();
return true;
}
});
videoView.setMediaController(new MediaController(this));
}
private List<IDanmakuItem> initItems() {
List<IDanmakuItem> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
IDanmakuItem item = new DanmakuItem(this, i + " : plain text danmuku", mDanmakuView.getWidth());
list.add(item);
}
String msg = " : text with image ";
for (int i = 0; i < 100; i++) {
ImageSpan imageSpan = new ImageSpan(this, R.drawable.em);
SpannableString spannableString = new SpannableString(i + msg);
spannableString.setSpan(imageSpan, spannableString.length() - 2, spannableString.length() - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
IDanmakuItem item = new DanmakuItem(this, spannableString, mDanmakuView.getWidth(), 0, 0, 0, 1.5f);
list.add(item);
}
return list;
}
@Override
protected void onResume() {
super.onResume();
mDanmakuView.show();
}
@Override
protected void onPause() {
super.onPause();
//隐藏
mDanmakuView.hide();
}
@Override
protected void onDestroy() {
super.onDestroy();
//清除
mDanmakuView.clear();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.switcher:
if (mDanmakuView.isPaused()) {
switcherBtn.setText(R.string.hide);
mDanmakuView.show();
} else {
switcherBtn.setText(R.string.show);
mDanmakuView.hide();
}
break;
case R.id.send:
String input = textEditText.getText().toString();
if (TextUtils.isEmpty(input)) {
Toast.makeText(OpendanmakuMainActivity.this, R.string.empty_prompt, Toast.LENGTH_SHORT).show();
} else {
IDanmakuItem item = new DanmakuItem(this, new SpannableString(input), mDanmakuView.getWidth(),0,R.color.my_item_color,0,1);
// IDanmakuItem item = new DanmakuItem(this, input, mDanmakuView.getWidth());
// item.setTextColor(getResources().getColor(R.color.my_item_color));
// item.setTextSize(14);
// item.setTextColor(textColor);
mDanmakuView.addItemToHead(item);
}
textEditText.setText("");
break;
}
}
}
3.在视频上用OpenDanmaku显示弹幕
设置视频路径:http://api.m.mtime.cn/PageSubArea/TrailerList.api
4.解决弹幕把视频遮挡的问题
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (status == STATUS_RUNNING) {
try {
// canvas.drawColor(Color.TRANSPARENT);
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
//先绘制正在播放的弹幕
for (int i = 0; i < mChannelMap.size(); i++) {
ArrayList<IDanmakuItem> list = mChannelMap.get(i);
for (Iterator<IDanmakuItem> it = list.iterator(); it.hasNext(); ) {
IDanmakuItem item = it.next();
if (item.isOut()) {
it.remove();
} else {
item.doDraw(canvas);
}
}
}
//检查是否需要加载播放下一个弹幕
if (System.currentTimeMillis() - previousTime > mPickItemInterval) {
previousTime = System.currentTimeMillis();
// Log.d(TAG, "start pick new item..");
IDanmakuItem di = mWaitingItems.pollFirst();
if (di != null) {
int indexY = findVacant(di);
if (indexY >= 0) {
// Log.d(TAG, "find vacant channel");
di.setStartPosition(canvas.getWidth() - 2, mChannelY[indexY]);
// Log.d(TAG, "draw new, text:" + di.getText());
//Log.d(TAG, String.format("doDraw, position,x=%s,y=%s", c.getWidth() - 1, mChannelY[indexY]));
di.doDraw(canvas);
mChannelMap.get(indexY).add(di);//不要忘记加入正运行的维护的列表中
} else {
// Log.d(TAG, "Not find vacant channel, add it back");
addItemToHead(di);//找不到可以播放的弹道,则把它放回列表中
}
} else {
//no item 弹幕播放完毕,
}
}
if (mShowDebug) {
int fps = (int) fps();
canvas.drawText("FPS:" + fps, 5f, 20f, fpsPaint);
for (float yp : lines) {
canvas.drawLine(0f, yp, getWidth(), yp, fpsPaint);
}
}
} catch (Exception e) {
e.printStackTrace();
}
invalidate();
} else {//暂停或停止,隐藏弹幕内容
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
}
}
看到此,是不是接的OpenDanmaku的简单使用是不是很简单,谢谢浏览!