在bibibi推出弹幕功能,我也爱上了边看视频边看吐槽了,现在让我们也来实现这一个功能吧。

首先我们要整理一下思绪我们大概需要实现哪个细节板块呢。

我们最直观的看来,弹幕就是总右往左出现到消失。我们要实现这个动画,弹幕的大小,颜色,出现方式,加速,弹幕的不重叠(这个我想了好久还没有实现,有实现方法可以联系下我)。

我们先来了解一下等会程序里面会用到的相关知识点,等会看代码会更轻松一点。

/*getHeight跟getMeasureHeight的区别* 实际上在当屏幕可以包裹内容的时候,他们的值相等,只有当view超出屏幕后,才能看出他们的区别:* getMeasuredHeight()是实际View的大小,与屏幕无关,而getHeight的大小此时则是屏幕的大小。* 当超出屏幕后, getMeasuredHeight() 等于 getHeight()加上屏幕之外没有显示的大小 * * */
/Activity生命周期中,onStart, onResume, onCreate都不是真正visible的时间点,真正的visible时间点是onWindowFocusChanged()函数被执行时。//当你屏幕的焦点发生变化时候,想要操作什么也完全可以在这个方法里面执行// Interpolator 被用来修饰动画效果,定义动画的变化率,可以使存在的动画效果accelerated(加速),decelerated(减速),repeated(重复),bounced(弹跳)等。/** AccelerateDecelerateInterpolator 在动画开始与结束的地方速率改变比较慢,在中间的时候加速AccelerateInterpolator  在动画开始的地方速率改变比较慢,然后开始加速AnticipateInterpolator 开始的时候向后然后向前甩AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值BounceInterpolator   动画结束的时候弹起CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线DecelerateInterpolator 在动画开始的地方快然后慢LinearInterpolator   以常量速率改变OvershootInterpolator    向前甩一定值后再回到原来位置
         * fillBefore是指动画结束时画面停留在此动画的第一帧;fillAfter是指动画结束是画面停留在此动画的最后一帧。Java代码设置如下:/*****动画结束时,停留在最后一帧*********setFillAfter(true);setFillBefore(false);  /*****动画结束时,停留在第一帧*********setFillAfter(false);setFillBefore(true);  *

下面我们就来看一下弹幕实现的效果。

弹幕会出现重叠,这个问题还未解决

让我们开始看代码结构吧。

我们字体颜色的xml都写在了colors.xml中了,BarrageItem里面存放着我们的一些变量,而核心代码都在View中

BraagetItem.java

package com.example.bibibibibibibibi;import android.widget.TextView;import android.widget.TextView;/*** Created by lixueyong on 16/2/19.*/
public class BarrageItem {public TextView textView;//文本框public int textColor;//文本颜色public String text;//文本对象public int textSize;//文本的大小public int moveSpeed;//移动速度public int verticalPos;//垂直方向显示的位置public int textMeasuredWidth;//字体显示占据的宽度
}

在BarrageItem里面处理了弹幕的速度,大小,颜色,动画,等事件 在这个文件中 我注释的内容是我对弹幕重叠的操作代码,但是除了问题,有兴趣的可以看一下

package com.example.bibibibibibibibi;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import com.example.bibibibibibibibi.R.integer;
/*** Created by nzx on 16/5/30.*/
public class BarrageView extends RelativeLayout {private Context mContext;private BarrageHandler mHandler = new BarrageHandler();private Random random = new Random(System.currentTimeMillis());//System.currentTimeMillis()产生一个当前的毫秒private static final long BARRAGE_GAP_MIN_DURATION = 1000;//两个弹幕的最小间隔时间private static final long BARRAGE_GAP_MAX_DURATION = 2000;//两个弹幕的最大间隔时间private int maxSpeed = 10000;//速度,msprivate int minSpeed = 5000;//速度,msprivate int maxSize = 30;//文字大小,dpprivate int minSize = 15;//文字大小,dpprivate int totalHeight = 0;//整个的高度private int lineHeight = 0;//每一行弹幕的高度private int totalLine = 0;//弹幕的行数private String[] itemText = {"大头死变态", "老圩人最屌了", "唉这把中单是火男,难玩了", "大头是傻子", "世界上最长的路是套路", "英雄联盟最强的是补丁","我不会轻易的go die", "嘿嘿", "加班加班"};private int textCount;//文本的组数//private  RelativeLayout Rparams;
//    private List<BarrageItem> itemList = new ArrayList<BarrageItem>();
//实现RelativeLayout的重写的构造方法。/** //content 上下文 //AttributeSet 属性集//defStyleAttr 预设样式属性集//defStyleRes 预设样式资源属性集* * */public BarrageView(Context context) {this(context, null);}public BarrageView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public BarrageView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);mContext = context;init();}private void init() {textCount = itemText.length;int duration = (int) ((BARRAGE_GAP_MAX_DURATION - BARRAGE_GAP_MIN_DURATION) * Math.random());mHandler.sendEmptyMessageDelayed(0, duration);}@Override//Activity生命周期中,onStart, onResume, onCreate都不是真正visible的时间点,真正的visible时间点是onWindowFocusChanged()函数被执行时。//当你屏幕的焦点发生变化时候,想要操作什么也完全可以在这个方法里面执行。public void onWindowFocusChanged(boolean hasWindowFocus) {super.onWindowFocusChanged(hasWindowFocus);totalHeight = getMeasuredHeight();/*getHeight跟getMeasureHeight的区别* 实际上在当屏幕可以包裹内容的时候,他们的值相等,只有当view超出屏幕后,才能看出他们的区别:* getMeasuredHeight()是实际View的大小,与屏幕无关,而getHeight的大小此时则是屏幕的大小。* 当超出屏幕后, getMeasuredHeight() 等于 getHeight()加上屏幕之外没有显示的大小 * * *///获取每一行弹幕的最大高度lineHeight = getLineHeight();//我们整个弹幕的高度view/每一行的最大弹幕高度=totalLine = totalHeight / lineHeight;}private void generateItem() {BarrageItem item = new BarrageItem();//把我们的每行弹幕的行数顺序跟弹幕进行一个随机String tx = itemText[(int) (Math.random() * textCount)];//随机弹幕大小int sz = (int) (minSize + (maxSize - minSize) * Math.random());item.textView = new TextView(mContext);item.textView.setText(tx);item.textView.setTextSize(sz);item.textView.setTextColor(Color.rgb(random.nextInt(256), random.nextInt(256), random.nextInt(256)));//这里我们需要传入三个参数 文本对象,文字行数跟大小item.textMeasuredWidth=(int) getTextWidth(item, tx, sz);//这是设置弹幕移动速度,实现有快有慢的感觉item.moveSpeed = (int) (minSpeed + (maxSpeed - minSpeed) * Math.random());//这里为了实现一个弹幕循环播放的项目,在我们实际中看情况而定if (totalLine == 0) {totalHeight = getMeasuredHeight();lineHeight = getLineHeight();totalLine = totalHeight / lineHeight;}//弹幕在y轴上出现的位置item.verticalPos = random.nextInt(totalLine) * lineHeight;
//        itemList.add(item);showBarrageItem(item);}private void showBarrageItem(final BarrageItem item) {
//paddingLeft是设置布局里面的内容左边的距离,这样我们这就可以让这个弹幕的textview完全消失int leftMargin = this.getRight() - this.getLeft() - this.getPaddingLeft();
//这里我们通过动态的方式去设置一些我们布局的属性。
//        int verticalMargin = getRandomTopMargin();
//        item.textView.setTag(verticalMargin);LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);params.addRule(RelativeLayout.ALIGN_PARENT_TOP);params.topMargin = item.verticalPos;this.addView(item.textView, params);Animation anim = generateTranslateAnim(item, leftMargin);anim.setAnimationListener(new Animation.AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Override//当我们动画结束的时候,清除该条弹幕public void onAnimationEnd(Animation animation) {item.textView.clearAnimation();BarrageView.this.removeView(item.textView);}@Override//动画被取消的时候出发public void onAnimationRepeat(Animation animation) {}});item.textView.startAnimation(anim);}//private TranslateAnimation generateTranslateAnim(BarrageItem item, int leftMargin) {//这里我们有四个参数(动画开始的x点,结束点,开始y轴点,结束的y点)TranslateAnimation anim = new TranslateAnimation(leftMargin, -item.textMeasuredWidth, 0, 0);//我们设置动画的持续时间,弹幕移动多久,我们就持续多久动画anim.setDuration(item.moveSpeed);// Interpolator 被用来修饰动画效果,定义动画的变化率,可以使存在的动画效果accelerated(加速),decelerated(减速),repeated(重复),bounced(弹跳)等。/** AccelerateDecelerateInterpolator 在动画开始与结束的地方速率改变比较慢,在中间的时候加速AccelerateInterpolator  在动画开始的地方速率改变比较慢,然后开始加速AnticipateInterpolator 开始的时候向后然后向前甩AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值BounceInterpolator   动画结束的时候弹起CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线DecelerateInterpolator 在动画开始的地方快然后慢LinearInterpolator   以常量速率改变OvershootInterpolator    向前甩一定值后再回到原来位置* */anim.setInterpolator(new AccelerateDecelerateInterpolator());/** fillBefore是指动画结束时画面停留在此动画的第一帧;fillAfter是指动画结束是画面停留在此动画的最后一帧。Java代码设置如下:/*****动画结束时,停留在最后一帧*********setFillAfter(true);setFillBefore(false);  /*****动画结束时,停留在第一帧*********setFillAfter(false);setFillBefore(true);  * * */anim.setFillAfter(true);return anim;}/*** 计算TextView中字符串的长度** @param text 要计算的字符串* @param Size 字体大小* @return TextView中字符串的长度*///因为我们的弹幕包裹在一个矩形中public float getTextWidth(BarrageItem item, String text, float Size) {Rect bounds = new Rect();TextPaint paint;paint = item.textView.getPaint();//这里参数是获取文本对象,开始的长度,结束的长度,我们绘制好的矩形框paint.getTextBounds(text, 0, text.length(), bounds);return bounds.width();}/*** 获得每一行弹幕的最大高度** @return*/private int getLineHeight() {BarrageItem item = new BarrageItem();String tx = itemText[0];item.textView = new TextView(mContext);item.textView.setText(tx);item.textView.setTextSize(maxSize);Rect bounds = new Rect();TextPaint paint;paint = item.textView.getPaint();paint.getTextBounds(tx, 0, tx.length(), bounds);return bounds.height();}class BarrageHandler extends Handler {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);generateItem();//每个弹幕产生的间隔时间随机int duration = (int) ((BARRAGE_GAP_MAX_DURATION - BARRAGE_GAP_MIN_DURATION) * Math.random());//多个消息可以使用同一个handler, 通过what不同区分不同的消息来源, 从而获取消息内容this.sendEmptyMessageDelayed(0, duration);}}//记录一下当前在显示弹幕的高度,避免弹幕出现重叠private Set<integer> existMarginValues = new HashSet<>();private int linesCount;
//    private int getRandomTopMargin()
//    {
//      //计算弹幕的空间高度
//      if(totalLine==0)
//      {
//          totalLine=Rparams.getBottom()-Rparams.getTop()-Rparams.getPaddingTop()
//                  -Rparams.getPaddingBottom();
//          if (totalHeight==0) {
//               totalHeight = getMeasuredHeight();
//                  lineHeight = getLineHeight();
//                  totalLine = totalHeight / lineHeight;
//          }
//          //检查重叠
//            while (true) {
//                int randomIndex =  (int) (Math.random() * linesCount);
//                int marginValue = (int) (randomIndex * (totalLine / linesCount));
//
//                if (!existMarginValues.contains(marginValue)) {
//                    existMarginValues.add(marginValue);
//                    return marginValue;
//                }
//            }
//
//          // }}

BarrageActivity.java

在这个类里面我们可以去进行一些事件,但是我这里没有去处理,大家按自己的需求来。

package com.example.bibibibibibibibi;import android.app.Activity;
import android.os.Bundle;/*** Created by lixueyong on 16/2/19.*/
public class BarrageActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_barrage);}}

还有一些关于颜色的xml 大家可以通过demo去看下了,这样我们就实现了类似于bibibi弹幕的功能,是不是很简单(ps:哪里简单了(手动蔑视))。

等我把弹幕重叠的bug解决,我在博客上也会更新的。

demo下载地址:http://download.csdn.net/detail/ningzhouxu/9535392

今后我会更新更多有趣好玩的博客的。

教你一步步实现bibibi弹幕功能。相关推荐

  1. Android弹幕功能实现,模仿斗鱼直播的弹幕效果

    转载请注明出处:http://blog.csdn.net/sinyu890807/article/details/51933728 本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 郭 ...

  2. 教你一步步搞定 Handoff

    Yosemite 已经正式上线,相信很多筒子已经试过了其中最让人兴奋的 Continuity 功能."Continuity"功能包含了能跨平台兼容的AirDrop.可在iPad和M ...

  3. 年会弹幕文字_活动现场互动弹幕_教你大屏幕上的弹幕怎么做

    学校举办民谣比赛.主持人大赛.元旦晚会.迎新晚会.毕业晚会之类的校园活动时候,参与的学生人数那叫一个多,这也给活动主办方带来了不小的困扰:年年都是那些花样儿,不来点新鲜点子很难吸引到学生们.活动现场要 ...

  4. 填充图片颜色计算机,教你一步步(电脑软件)绘制款式图+上色填充面料

    原标题:教你一步步(电脑软件)绘制款式图+上色填充面料 软件ps(Adobe PhotoShop) 电脑+鼠标+键盘 使用钢笔工具绘制款式图 1.扫描:将人体草稿写进电脑,保存. 2.然后用Illus ...

  5. 隐藏esp_仅需一分钟教你看懂汽车内的隐藏功能,哪些功能是你不知道的?

    车内的按键多种多样,而且越高档的车,按键就越多.除了少数国产车,绝大部分车辆的按键标识都是用英文字母表示,从而导致不少车主只能通过查看说明书才知道是什么意思. 今天小编整理了车内各种按键标识,不是很清 ...

  6. JavaScript css3模拟简单的视频弹幕功能

    最近相对比较空闲,想写一些东西写着玩.就尝试写了一个demo模拟了最简单的视频弹幕功能~~. 思路: 设置一个<div>和所播放的video的大小一致,把这个div标签蒙在video上面用 ...

  7. 因弹幕系统技术升级 B站即日起至6月6日关闭弹幕功能

    昨日晚间,B站官方微博发布声明称,因弹幕系统技术升级,从即日起至6月6日网站将暂时关闭弹幕功能. 在日前的第七届网络视听大会上,B站董事长兼CEO陈睿透露,2019年至今,已有2027万人在这家名为哔 ...

  8. html段落自动删除,利用JS代码自动删除稿件的普通弹幕功能

    事情的起因是在b站投稿了一个高级弹幕测试的视频(av9940487),但是由于b站的弹幕池机制是新的弹幕顶掉旧的弹幕,所以导致一些人发的高级弹幕很快就被顶掉了. 所以就想着写个脚本来自动删除属性为普通 ...

  9. 用python turtle画龙猫_【跟着弹簧学画画】教你一步步画出一只超萌的龙猫来!...

    原标题:[跟着弹簧学画画]教你一步步画出一只超萌的龙猫来! 龙猫,日文音译过来是豆豆龙,今天咱们就来画一个吧! 照旧先来感受下动态图↓ 1.先画耳朵,然后画出头部和身体,因为龙猫是圆滚滚的一只 画出胳 ...

  10. php怎么实现弹幕,HTML如何利用canvas实现弹幕功能

    本篇文章主要介绍HTML如何利用canvas实现弹幕功能,感兴趣的朋友参考下,希望对大家有所帮助. 简介 最近在做大作业的时候需要做一个弹幕播放器.借鉴了一下别人的源码自己重新实现了一个,演示如下 主 ...

最新文章

  1. android 首页6个碎片,Android 单帧碎片
  2. Spring Security OAuth2源码解析(一)
  3. 利用SOS扩展库进入高阶.NET6程序的调试
  4. JavaScript时间事件:setTimeout和setInterval
  5. M1兼容性怎么样?关于M1版MacBook兼容软件的测试方法
  6. mysql currentuser_MySQL中DATABASE()和CURRENT_USER()函数的示例详解
  7. vmware虚拟化服务器cpu超线程,VMware vSphere的配置方法最佳方案从而提高性能
  8. 天池学习赛:工业蒸汽量预测2——特征工程
  9. 【iOS QR Code】集成ZXingWidget(XCode Version 4.5.2,iOS 6.0 SDK)
  10. 《Android游戏开发详解》——第2章,第2.13节调用对象的行为
  11. Linux中inode值是什么?
  12. android多个网络请求如何依次执行,Android 并发和串行网络请求
  13. Python分析王者峡谷中英雄信息
  14. origin 2018安装教程与安装包
  15. 深扒Mobileye—与特斯拉分手,被英特尔收购,现在又成了蔚来的救星?
  16. Inverting Convolutional Networks with Convolutional Networks 论文理解
  17. linux命令scp(复制文件和目录)详解及cp和scp命令的使用方法
  18. 日本战国武将绰号与称号一览表
  19. Python-Selenium-OSError: [WinError 6] 句柄无效
  20. ISO26262功能安全 安全等级和量化指标

热门文章

  1. MacOS Big Sur 11.2.1 (20D75) 纯净恢复版黑苹果镜像下载
  2. MacOS Ventura 13.0.1 (22A400) 正式版带 OC 0.8.6 and winPE 双分区原版黑苹果镜像
  3. MacOS Big Sur 11.5.2 (20G95) OC 0.7.2 / Cl 5138 / PE 三分区原版黑苹果镜像
  4. 量子计算机慕课,计算机组成原理-中国大学mooc-题库零氪
  5. inter Fortran安装匹配VS2012
  6. 美媒:马斯克已掌管推特 立即开除CEO、CFO,新CEO据传是曾经卖牛肉的中国人
  7. pe_xscan做了几个改动
  8. HTML5期末大作业:小说网页设计——在线阅读7页(代码质量好) 学生DW网页设计作业源码 web课程设计网页规划与设计
  9. php flea,FleaPHP - 开发框架 - PHP开源网(PHP-OPEN.ORG)
  10. css滑动门技术的应用,CSS滑动门技术