安卓弹幕滚幕效果自定义View之BarrageView|支持点击事件|隐藏不滞留|颜色随机|大小速度范围随机

1、简介

项目地址: https://github.com/tpnet/BarrageView-tpnet-master

弹幕、滚屏 的自定义View,字体大小在一个范围随机,颜色随机,滚动速度范围随机,支持点击回调,隐藏后恢复不会有停滞,原理是在一个RelativeLayout里面随机生成TextView进行属性动画

2、代码解析

两个源文件:

1、 BarrgeItem.java
每个item就是一个x轴移动的TextView,包含属性

package com.example.tpnet.barrageview_tpnet_master;
import android.widget.TextView;
/*** Created by tpnet* 2016\4\16*/
public class BarrageItem {public TextView textView;public int textColor;public String text;public int textSize;public int moveSpeed;//移动速度public int verticalPos;//垂直方向显示的位置public int textMeasuredWidth;//字体显示占据的宽度
}

2、BarrageView
自定义View,修改RelativeLayout的属性,包涵代码解析

package com.example.tpnet.barrageview_tpnet_master;import android.animation.Animator;
import android.animation.ObjectAnimator;
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.View;
import android.view.animation.DecelerateInterpolator;
import android.widget.RelativeLayout;
import android.widget.TextView;import java.util.ArrayList;
import java.util.List;
import java.util.Random;/*** Created by tpnet* 16/4/14*/
public class BarrageView extends RelativeLayout {private OnClickActionListener mClick = null;// 为接口设置监听器public void setOnClickActionListener(OnClickActionListener down) {mClick = down;}//定义接口public interface OnClickActionListener {void onClick(String str);}private Context mContext;private BarrageHandler mHandler = new BarrageHandler();private Random random = new Random(System.currentTimeMillis());   //获取自1970年1月1日0时起到现在的毫秒数private static final long BARRAGE_GAP_MIN_DURATION = 1000;//两个弹幕的最小间隔时间private static final long BARRAGE_GAP_MAX_DURATION = 2000;//两个弹幕的最大间隔时间private int maxSpeed = 10000;   // 最小速度,ms,越大越慢private int minSpeed = 6000;    //  最快速度,ms,越大越慢private int maxSize = 30;       //最大字体文字,dpprivate int minSize = 15;       //最小文字大小,dpprivate int totalHeight = 0;    //总高度private int lineHeight = 0;     //每一行弹幕的高度private int totalLine = 0;      //弹幕的行数private List<String> itemText = new ArrayList<>();  //内容listprivate int textCount;   //条目的数量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;initData();init();}private void init() {//初始化条目textCount = itemText.size();}private void generateItem() {BarrageItem item = new BarrageItem();//String tx = itemText[(int) (Math.random() * textCount)];//随机获取条目String tx;tx = itemText.get((int) (Math.random() * textCount));//范围随机获取大小int sz = (int) (minSize + (maxSize - minSize) * Math.random());//创建textView 控件item.textView = new TextView(mContext);//设置文本属性item.textView.setText(tx);item.textView.setTextSize(sz);//item.textView.setBackgroundColor(R.color.black);item.textView.setTextColor(Color.rgb(random.nextInt(256), random.nextInt(256), random.nextInt(256)));//获取滚动TextView的宽度item.textMeasuredWidth = (int) getTextWidth(item, tx, sz);//设置随机移动速度item.moveSpeed = (int) (minSpeed + (maxSpeed - minSpeed) * Math.random());//为0则,初始化if (totalLine == 0) {//获取当前View的实际高度totalHeight = getMeasuredHeight();//获取行高lineHeight = getLineHeight();//获取总行数totalLine = totalHeight / lineHeight;}//垂直方向显示位置,行数的随机一行,nextInt(n) 返回一个大于等于0小于n的随机数System.out.println(totalLine+" "+lineHeight);item.verticalPos = random.nextInt(totalLine) * lineHeight;//显示滚屏showBarrageItem(item);}/*** 显示TextView 的动画效果* @param item*/private void showBarrageItem(final BarrageItem item) {//屏幕宽度 像素int leftMargin = this.getRight() - this.getLeft() - this.getPaddingLeft();//System.out.println(item.textView.getText()+(leftMargin+""));//显示的TextView 的位置,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);//设置回调回调点击final String temp = item.textView.getText().toString();item.textView.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {mClick.onClick(temp);}});//使用属性动画,确保控件位置不固定transAnimRun(item, leftMargin);}private void transAnimRun(final BarrageItem item, int leftMargin){ObjectAnimator objAnim =ObjectAnimator//滑动位置是x方向滑动,从屏幕宽度+View的长度到左边0-View的长度.ofFloat(item.textView,"translationX" , leftMargin, -item.textMeasuredWidth).setDuration(item.moveSpeed);//设置移动的过程速度,开始快之后满objAnim.setInterpolator(new DecelerateInterpolator());//开始动画objAnim.start();objAnim.addListener(new Animator.AnimatorListener() {@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {//动画执行完毕,清除动画,删除view,item.textView.clearAnimation();BarrageView.this.removeView(item.textView);}@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationRepeat(Animator animation) {}});}/*** 计算TextView中字符串的长度** @param text 要计算的字符串* @param Size 字体大小* @return TextView中字符串的长度*/public float getTextWidth(BarrageItem item, String text, float Size) {//Rect表示一个矩形,由四条边的坐标组成Rect bounds = new Rect();TextPaint paint;paint = item.textView.getPaint();paint.getTextBounds(text, 0, text.length(), bounds);//System.out.println(item.textView.getText()+(bounds.width()+"")+"宽度");return bounds.width();}/*** 获得每一行弹幕的最大高度** @return*/private int getLineHeight() {BarrageItem item = new BarrageItem();String tx;tx = itemText.get(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);//每个弹幕产生的间隔时间随机int duration = (int) ((BARRAGE_GAP_MAX_DURATION - BARRAGE_GAP_MIN_DURATION) * Math.random());generateItem();this.sendEmptyMessageDelayed(0, duration);}}/*** 当view显示在窗口的时候,回调的visibility等于View.VISIBLE。。当view不显示在窗口时,回调的visibility等于View.GONE** 窗口隐藏了,把内容全部清空,防止onPause时候内容停滞** **/@Overrideprotected void onWindowVisibilityChanged(int visibility) {super.onWindowVisibilityChanged(visibility);if(visibility == View.GONE){mHandler.removeMessages(0);}else if(visibility == View.VISIBLE){mHandler.sendEmptyMessage(0);}}/**** 初始化数据** **/private void initData(){itemText.add("疯狂动物城");itemText.add("师父");itemText.add("我的特工爷爷");itemText.add("风之谷");itemText.add("美人鱼");itemText.add("唐人街探案");itemText.add("西游记之孙悟空三打白骨精");itemText.add("解救吾先生");}
}

3、使用方法

在需要滚屏的方引入 BarrageView

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><!-- 自定义View 的路径 -->    <com.example.tpnet.barrageview_tpnet_master.BarrageView
        android:id="@+id/bv_text"android:layout_width="match_parent"android:layout_height="match_parent" />
</RelativeLayout>

4、回调点击事件

在BarrageView 的Activity 中,为BarrageView setOnClickActionListener 就行了,

package com.example.tpnet.barrageview_tpnet_master;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;public class MainActivity extends AppCompatActivity {private BarrageView bvText;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);bvText = (BarrageView) findViewById(R.id.bv_text);bvText.setOnClickActionListener(new BarrageView.OnClickActionListener() {@Overridepublic void onClick(String str) {Toast.makeText(MainActivity.this,str,Toast.LENGTH_SHORT).show();}});}
}

[安卓开发]弹幕滚幕效果自定义View之BarrageView|支持点击事件|隐藏不滞留|颜色随机|大小速度范围随机相关推荐

  1. android 微博字体高亮,安卓开发札记——高仿新浪微博文字处理(实现关键字高亮,自定义表情替换并加入点击事件实现)...

    安卓开发笔记--高仿新浪微博文字处理(实现关键字高亮,自定义表情替换并加入点击事件实现) 先让大家看下效果图,这个是我自己在闲暇时间仿写的新浪微博客户端: 今天来讲讲如何实现上图的效果,这里需要用到S ...

  2. Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ...

  3. Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习...

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ...

  4. Android 雪花飘落动画效果 自定义View

    在码农的世界里,优美的应用体验,来源于程序员对细节的处理以及自我要求的境界,年轻人也是忙忙碌碌的码农中一员,每天.每周,都会留下一些脚印,就是这些创作的内容,有一种执着,就是不知为什么,如果你迷茫,不 ...

  5. 安卓仿苹果音量调节_android自定义view仿照MIUI中音量控制效果

    先看效果图: 这就是miui中的音量效果图,实现思路是自定义视图,绘制圆环,然后设置进度显示. 核心代码在onDraw中实现如下: @Override protected void onDraw(Ca ...

  6. android歌词效果,自定义View:Android歌词控件

    TicktockMusic 音乐播放器项目相关文章汇总: 简介 之前做 TicktockMusic 音乐播放器,一个必要的需求肯定是歌词,在 github 上找了几个,发现或多或少都有点不满足需求,所 ...

  7. 一个炫酷的仿雷达扫描和扩散效果——自定义View就是这么简单

    高仿雷达扫描效果和仿水波纹中心扩散效果,手把手教你撸一个炫酷的自定义view. 于亚豪的博客地址: blog.csdn.net/androidstar- 我们先看效果图吧 Markdown Markd ...

  8. Android自定义View 开发流程综合简述 Android自定义View(三)

    本文简述一下自定义View中常用方法 1 简述 自定义View可以认为是继承自View或者ViewGroup Android中的任何一个布局.任何一个控件其实都是直接或间接继承自View的,如Text ...

  9. Android自定义View如此简单 实现点击动画+进度刷新的提交/下载按钮(填坑面试题)

    SubmitButton 背景 实现思路 继承View 面试题:构造方法如何选择 自定义属性 面试题:styleable.AttributeSet.TypedArray的关系 测量宽高 面试题:UNS ...

最新文章

  1. StereoDRNet:基于stereo的三维重建网络
  2. zz为什么人人都该学点心理学
  3. ORA-01555 snapshot too old
  4. keil obj 文件 结构_keil下的STM32程序开发部署(一)
  5. Java实现冒泡排序及其优化
  6. springboot+springsecurity+mybatis plus之用户认证
  7. 设计模式之-命令模式(Command Pattern)
  8. uvm 形式验证_UVM基础
  9. 使用 Finder预览功能,让你可以快速浏览多个文件
  10. python映射的主要特点_30 个 Python 语言的特点技巧
  11. vue入门:(组件)
  12. Spring中利用配置文件和 value注入属性值
  13. 全网首发:linux任务栏分组的研究
  14. Java基础——常用对象API(4):集合框架5:Map集合
  15. c语言 设圆的半径,【c语言】设圆半径r = 1.5,圆柱高h = 3,求圆周长,圆面积,圆球表面积,圆球体积,圆柱体积...
  16. 惠惠软件|CSDN笔耕不辍Lv1
  17. hdu5285 wyh2000 and pupil
  18. Python爬虫实例--新浪热搜榜[正则表达式]
  19. 最安全的微信群管理工具推荐
  20. android add fragment,Android中使用FragmentTransaction对象的add方法后应用闪退

热门文章

  1. 图像特征提取(纹理特征)
  2. python图像纹理提取_提取图像的颜色、纹理特征(传统算法)
  3. Yansongda\Pay 支付宝返回值封装
  4. 计算机视觉毕业后找不到工作怎么办?
  5. 介绍当前计算机软件应用发展状况,简要介绍我国当前税收征管软件的应用状况...
  6. 初学python找不到的类都到这儿来
  7. 昼短苦夜长,何不秉烛游
  8. 课程设计 学生选课管理 王杰 孙乾 蔚晓青
  9. pyqt-窗口最大化
  10. android 对话框大全,Android 对话框(Dialog)大全