浅谈DanmakuView
今天简单介绍一下开源的弹幕引擎---danmakuView
使用之前在build.gradle里面添加下面这一条(目前我使用的工具是AndroidStudio 3.1.2)
implementation 'com.github.ctiao:DanmakuFlameMaster:0.3.8'
库导入完成之后一定不要忘记 Sync now (emmmm,相信你应该不会忘)
1.设计布局
首先设计布局,布局文件就很好理解了,采用了谷歌最新的ConstraintLayout布局,简单实用,内部放置一个VideoView用来播放视频,EditText用来输入弹幕,Button用来发送弹幕,介绍Over
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
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:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000"
tools:context=".MainActivity">
<VideoView
android:id="@+id/videoview"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<master.flame.danmaku.ui.widget.DanmakuView
android:id="@+id/danmaku"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/ly_send"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#FFF"
android:orientation="horizontal"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent">
<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>
</android.support.constraint.ConstraintLayout>
2.界面逻辑
点击屏幕,底部会显示一个输入框和一个发送按钮,当输入文字并点击发送之后,屏幕上会出现一个蓝色框,里面是刚刚输入的文字,再次点击屏幕,底部的输入框和发送按钮消失。Over
package com.project.software.company;
import android.graphics.Color;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.VideoView;
import org.w3c.dom.Text;
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;
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 = findViewById(R.id.videoview);
sendLayout = findViewById(R.id.ly_send);
sendButton = findViewById(R.id.btn_send);
editText = findViewById(R.id.et_text);
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 drawingFinished() {
}
});
danmakuContext = danmakuContext.create();
danmakuView.enableDanmakuDrawingCache(true); //提升屏幕绘制效率
danmakuView.prepare(parser,danmakuContext); //进行弹幕准备
//为danmakuView设置点击事件
danmakuView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(sendLayout.getVisibility() == View.GONE){
sendLayout.setVisibility(View.VISIBLE); //显示布局
} else {
sendLayout.setVisibility(View.GONE); //隐藏布局
}
}
});
//为“发送”按钮设置点击事件
sendButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String content = editText.getText().toString();
if(!TextUtils.isEmpty(content)){
addDanmaku(content,true); //添加一条弹幕
editText.setText("");
}
}
});
}
//添加一条弹幕
//content 弹幕的具体内容
//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.time = 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();
}
protected void onPause() {
super.onPause();
if(danmakuView != null && danmakuView.isPrepared()){
danmakuView.pause();
}
}
protected void onResume() {
super.onResume();
if(danmakuView !=null && danmakuView.isPrepared() && danmakuView.isPaused()){
danmakuView.resume();
}
}
protected void onDestroy() {
super.onDestroy();
showDanmaku = false;
if(danmakuView != null){
danmakuView.release();
danmakuView = null;
}
}
}
下面简单解释一下代码,在onCreate()方法中调用了三个初始化函数:
1.initView()用来初始化界面控件
2.playVideo()用来播放视频(将视频名称为run的视频放入raw文件夹下面)
3.initDanmaku()用来初始化屏幕
接下来是添加弹幕,在发送按钮的点击事件中调用了addDanmaku(content,true)函数,将输入的内容传递过来,并在该函数中设置弹幕的一些属性
当然,光有自己输入的弹幕是不美观的,还要添加一些别人输入的弹幕,这样显得更真实一些,generateDanmakus()函数就做到了这一点,不过这里选择的是随机生成一些数字
剩下的onPause(),onResume(),onDestroy()方法就比较简单,我就不一一介绍了
最后,如果你觉得竖屏和标题栏不好看,可以在MainActivity的《activity》标签(这里我不得不用中文符号,英文符号会出错)中加入下面这一句,使之横屏:
android:screenOrientation="landscape"
在《application》标签(这里也是同样的问题)中下入下面这一句,去掉标题栏:
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
最最最后,贴图看效果
此文Over
浅谈DanmakuView的更多相关文章
- 浅谈 Fragment 生命周期
版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...
- 浅谈 LayoutInflater
浅谈 LayoutInflater 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/View 文中如有纰漏,欢迎大家留言指出. 在 Android 的 ...
- 浅谈Java的throw与throws
转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...
- 浅谈SQL注入风险 - 一个Login拿下Server
前两天,带着学生们学习了简单的ASP.NET MVC,通过ADO.NET方式连接数据库,实现增删改查. 可能有一部分学生提前预习过,在我写登录SQL的时候,他们鄙视我说:“老师你这SQL有注入,随便都 ...
- 浅谈WebService的版本兼容性设计
在现在大型的项目或者软件开发中,一般都会有很多种终端, PC端比如Winform.WebForm,移动端,比如各种Native客户端(iOS, Android, WP),Html5等,我们要满足以上所 ...
- 浅谈angular2+ionic2
浅谈angular2+ionic2 前言: 不要用angular的语法去写angular2,有人说二者就像Java和JavaScript的区别. 1. 项目所用:angular2+ionic2 ...
- iOS开发之浅谈MVVM的架构设计与团队协作
今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...
- Linux特殊符号浅谈
Linux特殊字符浅谈 我们经常跟键盘上面那些特殊符号比如(?.!.~...)打交道,其实在Linux有其独特的含义,大致可以分为三类:Linux特殊符号.通配符.正则表达式. Linux特殊符号又可 ...
- 浅谈Angular的 $q, defer, promise
浅谈Angular的 $q, defer, promise 时间 2016-01-13 00:28:00 博客园-原创精华区 原文 http://www.cnblogs.com/big-snow/ ...
随机推荐
- 中间件增强框架之InterceptFramework
本文讲解MOF中的InterceptFramework框架.该框架可以在应用启动过程中获取画像信息,实现应用画像数据采集和存储. 一.前言 在智能运维中,应用服务所使用的组件及JAR包等相关信息非常重 ...
- 最短路径Dijkstra算法模板题---洛谷P3371 【模板】单源最短路径(弱化版)
题目背景 本题测试数据为随机数据,在考试中可能会出现构造数据让SPFA不通过,如有需要请移步 P4779. 题目描述 如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 输入格式 第一行 ...
- python小白手册之字符串的私有方法和公用方法
#字符串方法. name=input('1111') if name.isalnum(): print(是否由数字字母) isdigit isdecimal判断数字 strip去空格或者其他 name ...
- Java连载19-用户输入和大括号省略
一.联系一个if语句 public class d19_{ public static void main(String[] args) { double a = 20.2; if(a>100 ...
- css3弹性盒子 flex布局
CSS3 弹性盒 1.display:flex 说明: 设置为弹性盒(父元素添加) 2.flex-direction(主轴排列方式) 说明: 顺序指定了弹性子元素在父容器中的位置 row 默认在一行内 ...
- AntV F2+vue-cli构建移动端可视化视图
AntV F2是蚂蚁金服旗下的一个专注于移动,开箱即用的可视化解决方案,完美支持 H5 环境同时兼容多种环境(Node, 小程序,Weex), 完备的图形语法理论,满足你的各种可视化需求,专业的移动设 ...
- Codeforces 814D
题意略. 思路: 由于不重合这个性质,我们可以将每一个堆叠的圆圈单独拿出来考虑,而不用去考虑其他并列在同一层的存在, 在贪心解法下,发现,被嵌套了偶数层的圆圈永远是要被减去的,而奇数层的圆圈是要加上的 ...
- Ajax数据解析格式
Ajax数据解析格式 一.前言 在服务器端 AJAX 是一门与语言无关的技术.在业务逻辑层使用何种服务器端语言都可以. 从服务器端接收数据的时候,那些数据必须以浏览器能够理解的格式来发送.服务器端的编 ...
- 【阿里云IoT+YF3300】5. Alink物模型之服务下发
名词解释: 服务:设备的功能模型之一,设备可被外部调用的能力或方法,可设置输入参数和输出参数.相比于属性,服务可通过一条指令实现更复杂的业务逻辑,如执行某项特定的任务. -摘自阿里云物联网产品文 ...
- 解决npm报错:Module build failed: TypeError: this.getResolve is not a function
1.sass-loader的版本过高导致的编译错误,当前最高版本是8.x,需要退回到7.3.1 运行: npm uninstall sass-loader --save-dev(卸载当前版本) npm ...