在程序开发中, 弹幕用的最多的地方就是直播平台, 例如常见的斗鱼. 在观看视频直播时, 通常在屏幕底部会有一个输入框, 专门用于输入屏幕. 弹幕其实很像人们发送的即时消息, 只不过是显示在直播界面上.
弹幕程序
任务综述
弹幕界面注意显示视频播放, 弹幕文本信息, 弹幕输入框以及弹幕的 "发送" 按钮, 当点击弹幕界面上的任意地方时, 界面底部会弹出一个输入框和一个 "发送" 按钮, 此时可以输入文字并发送. 当再次单击弹幕界面上的任意地方时, 界面底部的输入框和 "发送" 按钮便会消失. 为了与他人发送的弹幕有所区别, 本机发送的弹幕会添加一个蓝色的边框.
1. 弹幕界面
任务分析:
弹幕界面主要显示视频播放, 弹幕文本信息, 弹幕输入框以及弹幕的 "发送" 按钮, 界面效果如图所示.
弹幕界面
任务实施:
(1) 创建项目: Barrage.
(2) 导入视频文件. 在程序的 res 中创建 raw 目录, 将视频文件 sun.mp4 导入该目录.
(3) 添加 DanmakuFlamMaster 库. 由于弹幕界面中用到了 DanmakuFlameMaster 库, 因此将其库导入本项目中. 在 AS 中, 右键选择 Open Module Settings 选项然后选择 Dependencies 选项卡, 单击 "+" 选择 Library dependency, 把 com.GitHub.ctiao:DanmakuFlameMaster:0.5.3 库加入项目.
注意:
如果 Library dependency 选项中找不到该库, 则可以直接在该项目的 build.gradle 文件中添加如下代码.
compile 'com.github.ctiao:DanmakuFlameMaster:0.5.3'
(4) 放置界面控件.
一个 VideoView 控件用于播放视频,
一个 DanmakuView 控件用于显示弹幕,
一个 EditText 控件用于输入弹幕文本,
一个 Button 控件用于显示发送弹幕的按钮.
activity_main.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:Android="http://schemas.android.com/apk/res/android"
- Android:id="@+id/activity_main"
- Android:layout_width="match_parent"
- Android:layout_height="match_parent"
- Android:background="#000">
- <VideoView
- Android:id="@+id/videoview"
- Android:layout_width="match_parent"
- Android:layout_height="wrap_content"
- Android:layout_centerInParent="true" />
- <master.flame.danmaku.ui.widget.DanmakuView
- Android:id="@+id/danmaku"
- Android:layout_width="match_parent"
- Android:layout_height="match_parent" />
- <LinearLayout
- Android:id="@+id/ly_send"
- Android:layout_width="match_parent"
- Android:layout_height="60dp"
- Android:layout_alignParentBottom="true"
- Android:background="#fff"
- Android:visibility="gone">
- <EditText
- Android:id="@+id/et_text"
- Android:layout_width="0dp"
- Android:layout_height="match_parent"
- Android:layout_weight="1" />
- <Button
- Android:id="@+id/btn_send"
- Android:layout_width="wrap_content"
- Android:layout_height="match_parent"
- Android:text="发送" />
- </LinearLayout>
- </RelativeLayout>
2. 弹幕界面逻辑代码
任务分析:
当点击弹幕界面时, 界面底部会弹出一个输入框和一个 "发送" 按钮, 当输入文字并点击 "发送" 按钮后, 弹幕会出现一个蓝色框, 框中显示刚刚发送的文字; 当再次点击弹幕界面时, 界面底部的输入框和 "发送" 按钮消失.
(1) 获取界面控件. 创建 initView() 方法, 用于获取弹幕界面上所要用到的控件.
(2) 播放视频. 在 MainActivity 中创建一个 playVideo() 方法, 在该方法中获取 res/raw 文件夹中的 sun.mp4 视频文件的 uri, 并调用色图 VideoURI() 方法设置 uri, 然后调用 start() 方法播放视频.
(3) 初始化弹幕. 创建一个 initDanmaku() 方法, 用于初始化弹幕并调用弹幕的随机生成与添加方法.
(4) 随机生成有添加弹幕. 创建 generateDanmakus() 与 addDanmaku() 方法, 分别用于随机生成弹幕文字与添加弹幕到屏幕上.
MainActivity.xml
- public class MainActivity extends AppCompatActivity {
- private boolean showDanmaku;
- private DanmakuView danmakuView;
- private DanmakuContext danmakuContext;
- private Button sendButton;
- private LinearLayout sendLayout;
- private EditText editText;
- private VideoView videoView;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- initView();
- playVideo();
- initDanmaku();
- }
- /**
- * 初始化界面控件
- */
- private void initView() {
- videoView = (VideoView) findViewById(R.id.videoview);
- sendLayout = (LinearLayout) findViewById(R.id.ly_send);
- sendButton = (Button) findViewById(R.id.btn_send);
- editText = (EditText) findViewById(R.id.et_text);
- danmakuView = (DanmakuView) findViewById(R.id.danmaku);
- }
- /**
- * 播放视频
- */
- private void playVideo() {
- String uri = "android.resource://" + getPackageName() + "/" + R.raw.sun;
- if (uri != null) {
- videoView.setVideoURI(Uri.parse(uri));
- videoView.start();
- } else {
- videoView.getBackground().setAlpha(0);// 将背景设为透明
- }
- }
- /**
- * 创建弹幕解析器
- */
- private BaseDanmakuParser parser = new BaseDanmakuParser() {
- @Override
- protected IDanmakus parse() {
- return new Danmakus();
- }
- };
- /**
- * 初始化弹幕
- */
- private void initDanmaku() {
- danmakuView.setCallback(new DrawHandler.Callback() {// 设置回调函数
- @Override
- public void prepared() {
- showDanmaku = true;
- danmakuView.start(); // 开始弹幕
- generateDanmakus(); // 调用随机生成弹幕方法
- }
- @Override
- public void updateTimer(DanmakuTimer timer) {
- }
- @Override
- public void danmakuShown(BaseDanmaku danmaku) {
- }
- @Override
- public void drawingFinished() {
- }
- });
- danmakuContext = DanmakuContext.create();
- danmakuView.enableDanmakuDrawingCache(true);// 提升屏幕绘制效率
- danmakuView.prepare(parser, danmakuContext);// 进行弹幕准备
- // 为 danmakuView 设置点击事件
- danmakuView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (sendLayout.getVisibility() == View.GONE) {
- sendLayout.setVisibility(View.VISIBLE);// 显示布局
- } else {
- sendLayout.setVisibility(View.GONE); // 隐藏布局
- }
- }
- });
- // 为发送按钮设置点击事件
- sendButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- String content = editText.getText().toString();
- if (!TextUtils.isEmpty(content)) {
- addDanmaku(content, true);// 添加一条弹幕
- editText.setText("");
- }
- }
- });
- }
- /**
- * 添加一条弹幕
- *
- * @param content 弹幕的具体内容
- * @param border 弹幕是否有边框
- */
- private void addDanmaku(String content, boolean border) {
- // 创建弹幕对象, TYPE_SCROLL_RL 表示从右向左滚动的弹幕
- BaseDanmaku danmaku = danmakuContext.mDanmakuFactory.createDanmaku(
- BaseDanmaku.TYPE_SCROLL_RL);
- danmaku.text = content;
- danmaku.padding = 6;
- danmaku.textSize = 30;
- danmaku.textColor = Color.WHITE;// 弹幕文字的颜色
- danmaku.setTime(danmakuView.getCurrentTime());
- if (border) {
- danmaku.borderColor = Color.BLUE;// 弹幕文字边框的颜色
- }
- danmakuView.addDanmaku(danmaku); // 添加一条弹幕
- }
- /**
- * 随机生成一些弹幕内容
- */
- private void generateDanmakus() {
- new Thread(new Runnable() {
- @Override
- public void run() {
- while (showDanmaku) {
- int num = new Random().nextInt(300);
- String content = "" + num;
- addDanmaku(content, false);
- try {
- Thread.sleep(num);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }).start();
- }
- @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;
- }
- }
- }
(5) 修改清单文件. 由于在项目中需要使用自己的图标, 并且在项目创建时默认带有的标题栏不够美观, 因此需要修改清单文件中 < application > 标签中的 icon 与 theme 属性.
Android:icon="@mipmap/barrage_icon" Android:theme="@style/Theme.AppCompat.Light.NoActionBar"
由于只有视频播放界面处于横屏时视频与弹幕才会更加清晰, 因此需要设置 MainActivity 对应的 < activity > 标签中的 screenOrientation 属性为横屏.
<activity Android:name=".MainActivity" Android:screenOrientation="landscape">
来源: http://www.jianshu.com/p/4edc7f44e06e