制作视频弹幕:DanmakuFlameMaster
现在在各大视频软件和直播平台上弹幕随处可见,也是必不可少的东西。所有我们就来制作一下简单的视频弹幕吧
基本功能:随机生成弹幕,可自定义发送弹幕,弹幕的颜色随机,透明度,大小随机,速度随机,弹幕可关闭可打开
如果有不好的地方请大佬们指教。希望能够帮助到你们哦
先看效果图吧:


  1. 一:先修改布局文件activity_main.xml
    基本实现的关键步骤:
    (1)弹幕界面主要控件是:显示视频播放(VideoView控件),弹幕文本信息(DanmakuFlameMaster库),弹幕输入框(EditText控件),弹幕的发送按钮(Button控件)
    (2)布局为相对布局,DanmakuFlameMaster库的添加:在build.gradle文件里添加依赖:compile ‘com.github.ctiao:DanmakuFlameMaster:0.9.25’
    (3)DanmakuView可见性设置为不可见
    (4)弹幕的输入框和发送按钮用一个线性布局,输入框的长度使用权重:android:layout_width=“0dp” android:layout_weight=“1” ,使它100%填充。
    在build.gradle文件里添加依赖:
implementation 'com.github.ctiao:DanmakuFlameMaster:0.9.25'
activity_main.xml的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="#000"><VideoViewandroid:id="@+id/videoview"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_centerInParent="true" /><master.flame.danmaku.ui.widget.DanmakuViewandroid:id="@+id/danmaku"android:layout_width="match_parent"android:layout_height="match_parent" /><LinearLayoutandroid:id="@+id/ly_send"android:layout_width="match_parent"android:layout_height="60dp"android:layout_alignParentBottom="true"android:background="#fff"android:visibility="gone"><Switchandroid:id="@+id/open"android:layout_width="wrap_content"android:layout_height="match_parent"android:textOff="关"android:textOn="开"android:checked="true"/><EditTextandroid:id="@+id/et_text"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1" /><Buttonandroid:id="@+id/btn_send"android:layout_width="wrap_content"android:layout_height="match_parent"android:text="发送" /></LinearLayout>
</RelativeLayout>
  1. 二:编写业务逻辑代码MainActivity.java
    (1)获取界面控件:initView()方法获取界面控件的实例,初始化界面控件。
    (2)播放视频:playVideo()方法:获取视频的uri(路径);如果uri不为空,解析该视频,将String类型解析为uri类型,start开始播放,setAlpha():设置透明度
    (3)随机生成与添加弹幕:generateDanmakus()方法生成弹幕:添加线程:开子线程,重写run()方法,生成0-299的正整数添加到内容,中,addDanmaku(content, false)添加到屏幕,不显示边框;addDanmaku()方法添加弹幕:创建弹幕对象; TYPE_SCROLL_RL:表示从右向左滚动的弹幕;设置弹幕的内容,内边距,字体大小,颜色,设置时间为当时时间;判断弹幕是否有边框,如果有边框就设置边框颜色,最后将该条弹幕显示在屏幕上。
    (4)创建弹幕解析器:全局的BaseDanmakuParser。
    (5)初始化弹幕:调用了setCallback()方法来设置回调函数,prepared()方法:显示弹幕,调用start()和generateDanmakus()方法开始随机生成弹幕并显示;调用DanmakuContext.create()方法创建了一个DanmakuContext的实例,DanmakuContext可以用于对弹幕的各种全局配置进行设定,如设置字体、设置最大显示行;调用了enableDanmakuDrawingCache()方法来提升绘制效率;调用DanmakuView的prepare()方法进行弹幕准备;给DanmakuView设置了一个点击事件,当点击屏幕时就会触发这个点击事件。然后进行判断,如果操作界面是隐藏的就将它显示出来,如果操作界面是显示的就将它隐藏掉;给发送按钮注册了一个点击事件,当点击发送时,获取EditText中的输入内容,然后调用addDanmaku()方法将这条消息添加到DanmakuView上。另外,这条弹幕是由我们自己发送的,因此addDanmaku()方法的第二个参数要传入true。 附加功能的实现逻辑:
    1.弹幕的开关:首先在布局文件中加入Switch控件,默认状态为开启状态;在MainActivity中:在initDanmaku()方法中设置开关监控回调:实现CompoundButton.OnCheckedChangeListener接口,并实现其内部的onCheckedChanged方法;if语句判断开关的状态:danmakuView.show()方法//打开弹幕,danmakuView.hide()//关闭弹幕;
    2.多种颜色的弹幕:在MainActivity中:修改addDanmaku方法中的字体颜色的设置:实例化Random的对象;设置颜色值为Color.rgb(random.nextInt(256),random.nextInt(256), random.nextInt(256)) //rgb的值在0-255之间,三个值分别为红,绿,蓝的数值;
    3.弹幕透明度:在上一条上面修改:danmaku.textColor = Color.argb(random.nextInt(256),random.nextInt(256),random.nextInt(256), random.nextInt(256));
    4.弹幕的字体大小不同:danmaku.textSize =(random.nextInt(15) + 35)生成15-35的随机数;
    5.速度随机:danmaku.duration.setFactor((float)Math.random()*5);//滚动系数越小越快

    MainActivity.java代码如下:

package com.example.barrage;import androidx.appcompat.app.AppCompatActivity;import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Switch;
import android.widget.VideoView;import java.util.Random;import master.flame.danmaku.controller.DrawHandler;
import master.flame.danmaku.danmaku.model.BaseDanmaku;
import master.flame.danmaku.danmaku.model.DanmakuTimer;
import master.flame.danmaku.danmaku.model.IDanmakus;
import master.flame.danmaku.danmaku.model.android.DanmakuContext;
import master.flame.danmaku.danmaku.model.android.Danmakus;
import master.flame.danmaku.danmaku.parser.BaseDanmakuParser;
import master.flame.danmaku.ui.widget.DanmakuView;public class MainActivity extends AppCompatActivity {/*** 定义成员变量  (文档注释)*/private boolean showDanmaku;private DanmakuView danmakuView;private DanmakuContext danmakuContext; // (Context:上下文,运行的环境)private Button sendButton;private LinearLayout sendLayout;private EditText editText;private VideoView videoView;private Switch open;@Overrideprotected 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);open=(Switch) findViewById(R.id.open);}/*** 播放视频*/private void playVideo() {//视频地址String uri = "android.resource://" + getPackageName() + "/" + R.raw.yuan;if (uri != null) {videoView.setVideoURI(Uri.parse(uri)); //解析视频videoView.start();  //播放视频} else {videoView.getBackground().setAlpha(0);//将背景设为透明,透明度:0-255}}/*** 创建弹幕解析器*/private BaseDanmakuParser parser = new BaseDanmakuParser() {@Overrideprotected IDanmakus parse() {return new Danmakus();}};/*** 初始化弹幕*/private void initDanmaku() {danmakuView.setCallback(new DrawHandler.Callback() {//设置回调函数@Overridepublic void prepared() {showDanmaku = true;danmakuView.start(); //开始弹幕generateDanmakus();  //调用随机生成弹幕方法}@Overridepublic void updateTimer(DanmakuTimer timer) {}@Overridepublic void danmakuShown(BaseDanmaku danmaku) {}@Overridepublic void drawingFinished() {}});danmakuContext = DanmakuContext.create();danmakuView.enableDanmakuDrawingCache(true);//提升屏幕绘制效率(Cache:缓存)danmakuView.prepare(parser, danmakuContext);//进行弹幕准备(parser:解析器)//为danmakuView设置点击事件danmakuView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {if (sendLayout.getVisibility() == View.GONE) {sendLayout.setVisibility(View.VISIBLE);//显示布局} else {sendLayout.setVisibility(View.GONE);   //隐藏布局}}});//为发送按钮设置点击事件sendButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {String content = editText.getText().toString();if (!TextUtils.isEmpty(content)) {addDanmaku(content, true);//添加一条弹幕editText.setText("");}}});//        弹幕的开关open.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {// TODO Auto-generated method stubif (isChecked) {danmakuView.show();//打开弹幕} else {danmakuView.hide();// 关闭弹幕}}});}/*** 添加一条弹幕** @param content    弹幕的具体内容* @param border     弹幕是否有边框*/private void addDanmaku(String content, boolean border) {//创建弹幕对象,TYPE_SCROLL_RL表示从右向左滚动的弹幕  TYPE_SCROLL_LR:从左向右(context上下文)BaseDanmaku danmaku = danmakuContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_LR);danmaku.text = content;danmaku.padding = 6;Random random = new Random();danmaku.textSize =(random.nextInt(15) + 35);danmaku.textColor = Color.argb(random.nextInt(256),random.nextInt(256),random.nextInt(256), random.nextInt(256));
//        danmaku.textColor = Color.rgb(random.nextInt(256),random.nextInt(256), random.nextInt(256));//弹幕文字的颜色
//      速度
//        danmaku.duration.setFactor((float)Math.random()*5);//滚动系数越小越快danmaku.setTime(danmakuView.getCurrentTime());  //设置时间为当前时间if (border) {danmaku.borderColor = Color.RED;//弹幕文字边框的颜色}danmakuView.addDanmaku(danmaku);     //添加一条弹幕}/*** 随机生成一些弹幕内容*/private void generateDanmakus() {   //generate 生成new Thread(new Runnable() {  //子线程@Overridepublic void run() {while (showDanmaku) {int num = new Random().nextInt(300); //生成0-299的正整数String content = "" + num;addDanmaku(content, false);try {Thread.sleep(num);  //休眠299毫秒} catch (InterruptedException e) {e.printStackTrace();}}}}).start();}@Overrideprotected void onPause() {super.onPause();if (danmakuView != null && danmakuView.isPrepared()) {danmakuView.pause();}}@Overrideprotected void onResume() {super.onResume();if (danmakuView != null && danmakuView.isPrepared() &&danmakuView.isPaused()) {danmakuView.resume();}}@Overrideprotected void onDestroy() {super.onDestroy();showDanmaku = false;if (danmakuView != null) {danmakuView.release();danmakuView = null;}}
}

自定义APP图标和视频横屏播放在AndroidMainfast.xml

android:icon="@mipmap/barrage_icon"
<activity android:name=".MainActivity" **android:screenOrientation="landscape"**>

参考以下文献

https://blog.csdn.net/benhuo931115/article/details/51056646
https://blog.csdn.net/qq_43249816/article/details/88789064?utm_source=app
传智播客Android企业级项目实战教程

制作视频弹幕:DanmakuFlameMaster相关推荐

  1. 用jQuery制作视频弹幕

    效果图: 左侧视频画面上显示弹幕,右侧评论区显示各用户发表过的评论,自己发表的评论也可显示在弹幕上. 基本布局 HTML: <div id="myvideo">< ...

  2. 谁能给我讲讲原理——视频弹幕游戏!!

    舍友在一个叫BliBli的视频网站上找到这样一个视频弹幕游戏,说实话我当时一看真的惊呆了. 从来没有见过这种能够互动的.充满游戏性的视频,用户WASD可以控制飞机移动躲避字幕,撞到字幕左上角死亡次数还 ...

  3. CSS奇思妙想—使用 mask 实现视频弹幕人物遮罩过滤

    使用 mask 实现视频弹幕人物遮罩过滤 经常看一些 LOL 比赛直播的小伙伴,肯定都知道,在一些弹幕网站(Bilibili.虎牙)中,当人物与弹幕出现在一起的时候,弹幕会"巧妙" ...

  4. 爬取钉钉在B站卑微道歉视频弹幕,做成词云

    爬取钉钉在B站卑微道歉视频弹幕,做成词云|钉~ 听这美妙的声音 先看用户老爷们给出得评价 B弹幕爬取的方法 打开钉钉下跪视频 B站链接 然后进入控制台如图查看,打开控制台刷新下页面. 你就会在控制台看 ...

  5. 英雄联盟《双城之战》视频弹幕爬取并分析输出词云

    目前,拳头制作的英雄联盟首部动画作品<双城之战>在腾讯视频独家播出.而事实再次证明,拳头是一家被游戏耽误的动画公司,<双城之战>首映非常成功,豆瓣评分9.2,5星评价占67.5 ...

  6. 使用CSS - mask 实现视频弹幕人物遮罩过滤

    经常看一些 LOL 比赛直播的小伙伴,肯定都知道,在一些弹幕网站(Bilibili.虎牙)中,当人物与弹幕出现在一起的时候,弹幕会"巧妙"的躲到人物的下面,看着非常的智能. 简单的 ...

  7. 使用Movie Maker制作视频相册

    国庆长假,大家或远足或近游,所到之处见到美景佳人难免用相机"咔嚓"几下留个念,假期归来也积攒个几十张照片,小白也不例外,想起上次师兄老黑教的用PowerPoint制作电子相册,虽然 ...

  8. python爬虫bilibili_Python爬虫 bilibili视频弹幕提取过程详解

    两个重要点 1.获取弹幕的url是以 .xml 结尾 2.弹幕url的所需参数在视频url响应的 javascript 中 先看代码 import requests from lxml import ...

  9. matlab如何使音频文件声音变大_如何制作视频课程

    1 制作课件 这个就不说了 2 修改课件 2.1 幻灯片大小统一 长宽比例为16:9 2.2 添加参考线 在keynote工具栏的显示-显示参考线中选择显示参考线 在幻灯片缩略图区域,右键任意一张幻灯 ...

最新文章

  1. onnxruntime c++ 工程实例
  2. 消控中心人员配置_关于2018年度环创中心楼宇物业综合管理考评情况的通报
  3. 爱普生SCARA机器人参考文档列表
  4. 机器学习数据预处理代码汇总(最新更新20年3月1日)
  5. 树莓派 cuda加速_用树莓派4b构建深度学习应用(四)PyTorch篇
  6. P3089 [USACO13NOV]POGO的牛Pogo-Cow
  7. 万能遥控器小制作(五)
  8. 硬盘克隆 计算机更换硬盘,换硬盘数据怎么办 看一招本地磁盘对拷
  9. 一个基于 Java 编写的物联网开源平台
  10. acwing 合唱队形
  11. JSON在线编辑器V2.0
  12. 阿里云镜像下载docker
  13. 用python给pdf批量添加水印,并给pdf加密
  14. 关于@Autowired属性飘红
  15. JAVA数据结构--Arraylist
  16. 《Journal of Solar Energy Engineering》期刊介绍(SCI 4区)
  17. 开启hadoop报错:localhost: Permission denied(publickey,gssapi-keyex,gssapi-with-mic,password).
  18. python3通过itchat登录微信给好友发送消息
  19. Python实现平方根倒数速算法
  20. 电子信息工程专业打工人的蓝桥杯单片机竞赛时记

热门文章

  1. Unity UGUI无限列表(Infinite List)
  2. Matlab联合Vissim协同仿真时报错“创建服务器失败”——问题解决方案
  3. android盒子定时重启,这才是电视、安卓盒子正确的关机方法!延长3年使用寿命...
  4. Python 爬取起点的小说(非vip)
  5. Opportunity
  6. Passware Kit 11.7可以即时解密PGP和Office 2010加密数据,并将此功能集成到Encase中
  7. Java单元测试典型案例集锦
  8. 设计模式之禅(第2版)
  9. 设计模式之禅-策略模式
  10. 基于STM32采用CS创世 SD NAND(贴片SD卡)完成FATFS文件系统移植与测试(中篇)