android 中的弹幕效果
android 弹幕评论效果
纯粹按照自己的想法仿照b站的弹幕写的一个demo,不知道正确的姿势怎么样的。
demo下载地址
首先,一条弹幕就是一个textview
- public abstract class Danmu extends TextView{
- private Context context;
- private int position;//弹幕的位置,在屏幕哪一行
- public Danmu(Context context) {
- super(context);
- this.context=context;
- setSingleLine();
- }
- public int getPosition() {
- return position;
- }
- public void setPosition(int position) {
- this.position = position;
- }
- public abstract void send();
- }
将弹幕放在一个相对布局容器中
- <RelativeLayout
- android:id="@+id/danmuContainer"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="3" />
当字数很多时,会放不下所有文字,所以手动设置了容器的宽度
容器设置足够大就好
- ViewGroup.LayoutParams lp=container.getLayoutParams();
- lp.width=DensityUtils.sp2px(this,15)*100;
- container.setLayoutParams(lp);
弹幕分为好几种这里做了普通的从右到左的,逆向的,还有在顶部和底部的
普通弹幕由两个TranslateAnimation完成,第一个是当弹幕移动后空出足够多空间时通知其他弹幕可以跟在它后面,第二个动画完成接下来的移出屏幕
- public class NormalDanmu extends Danmu {
- private Animation animation0,animation1;
- private int fx0,tx0,fx1,tx1;
- private int duration0,duration1;
- private OnAnimationEndListener onAnimationEndListener;
- public interface OnAnimationEndListener
- {
- public void clearPosition();//第一个动画结束,将当前行设置为可以发送弹幕
- public void animationEnd();//弹幕完全移出屏幕
- }
- public NormalDanmu(Context context,int fx,int tx)
- {
- super(context);
- this.fx0=fx;
- this.tx0=Math.abs(fx)-Math.abs(tx)-100;//第一个动画结束位置,当尾部空出100像素时就可以通知其他弹幕跟上了
- this.fx1=tx0;
- this.tx1=tx;
- duration0=2000*(Math.abs(tx0-fx0))/DensityUtils.getScreenW(context);
- duration1=2000*(Math.abs(tx1-fx1))/DensityUtils.getScreenW(context);
- initAnimation();
- }
- private void initAnimation()
- {
- animation0=new TranslateAnimation(fx0,tx0,0,0);
- animation1=new TranslateAnimation(fx1,tx1,0,0);
- animation0.setAnimationListener(new Animation.AnimationListener() {
- @Override
- public void onAnimationStart(Animation animation) {
- }
- @Override
- public void onAnimationEnd(Animation animation) {
- clearAnimation();
- startAnimation(animation1);
- if (onAnimationEndListener!=null)
- {
- onAnimationEndListener.clearPosition();
- }
- }
- @Override
- public void onAnimationRepeat(Animation animation) {
- }
- });
- animation0.setFillAfter(true);
- animation0.setDuration(duration0);
- animation0.setInterpolator(new AccelerateInterpolator());
- animation1.setAnimationListener(new Animation.AnimationListener() {
- @Override
- public void onAnimationStart(Animation animation) {
- }
- @Override
- public void onAnimationEnd(Animation animation) {
- if(onAnimationEndListener!=null)
- {
- onAnimationEndListener.animationEnd();
- }
- }
- @Override
- public void onAnimationRepeat(Animation animation) {
- }
- });
- animation1.setFillAfter(true);
- animation1.setDuration(duration1);
- animation1.setInterpolator(new DecelerateInterpolator());
- }
- public void setOnAnimationEndListener(OnAnimationEndListener onAnimationEndListener)
- {
- this.onAnimationEndListener=onAnimationEndListener;
- }
- @Override
- public void send() {
- startAnimation(animation0);
- }
- }
然后发送弹幕 final NormalDanmu danmu=new NormalDanmu(this,sWidth,(int) -paint.measureText(str));
swidth表示屏幕宽度,paint.measureText(str)是textview宽度,表示从最右端移动到左边完全移出屏幕
lp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
lp.topMargin=i*danmuHeight;
danmuHeight是一个textview的高度,这里设置放在容器的第i行
- private void setDanmu()
- {
- String ss="按是按时按是android.os.BinderProx按是";
- int ll=ss.length()*DensityUtils.sp2px(this,15);
- int ran= new Random().nextInt(ss.length());
- String str=ss.substring(ran);
- final NormalDanmu danmu=new NormalDanmu(this,sWidth,(int) -paint.measureText(str));
- danmu.setTextSize(15);
- danmu.setText(str);
- danmu.setOnAnimationEndListener(new NormalDanmu.OnAnimationEndListener() {
- @Override
- public void clearPosition() {
- sendPosition.put(danmu.getPosition(), false);
- }
- @Override
- public void animationEnd() {
- container.removeView(danmu);
- }
- });
- for(int i=0;i<count;i++)
- {
- if(sendPosition.get(i)==false)
- {
- danmu.setPosition(i);
- RelativeLayout.LayoutParams lp=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, danmuHeight);
- lp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
- lp.topMargin=i*danmuHeight;
- danmu.setGravity(Gravity.CENTER);
- container.addView(danmu, lp);
- danmu.send();
- sendPosition.put(i,true);
- break;
- }
- }
- }
逆向弹幕就是和普通弹幕移动方向不同其他完全一样
顶部和底部的弹幕主要就是显示几秒后再消失就行了比较简单
- public class TopDanmu extends Danmu {
- private OnDisappearListener onDisappearListener;
- private int duration;
- private Handler handler=new Handler()
- {
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- if(msg.what==1)
- {
- if(onDisappearListener!=null)
- {
- onDisappearListener.disappear();
- }
- }
- }
- };
- public TopDanmu(Context context,int duration) {
- super(context);
- this.duration=duration;
- }
- public interface OnDisappearListener
- {
- public void disappear();
- }
- @Override
- public void send() {
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- Thread.sleep(duration);
- handler.sendEmptyMessage(1);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }).start();
- }
- public void setOnDisappearListener(OnDisappearListener onDisappearListener )
- {
- this.onDisappearListener=onDisappearListener;
- }
- }
发送顶部弹幕
顶部弹幕要水平居中,这里的容器设置的宽度超过的屏幕大小,所以要手动计算弹幕的水平位置
int margin= (int) ((sWidth-paint.measureText(danmu.getText().toString()))/2);
- private void setTopDanmu()
- {
- String ss="按是按时按是android.os.BinderProx按是";
- int ran= new Random().nextInt(ss.length());
- String str=ss.substring(ran);
- int ll=str.length()*DensityUtils.sp2px(this, 15);
- final TopDanmu danmu=new TopDanmu(this,2000);
- danmu.setTextSize(15);
- danmu.setText(str);
- danmu.setTextColor(Color.GREEN);
- danmu.setOnDisappearListener(new TopDanmu.OnDisappearListener() {
- @Override
- public void disappear() {
- container.removeView(danmu);
- topSendPosition.put(danmu.getPosition(), false);
- }
- });
- for(int i=0;i<count;i++)
- {
- if(topSendPosition.get(i)==false)
- {
- danmu.setPosition(i);
- RelativeLayout.LayoutParams lp=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, danmuHeight);
- lp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
- int margin= (int) ((sWidth-paint.measureText(danmu.getText().toString()))/2);
- lp.topMargin=i*danmuHeight;
- lp.leftMargin=margin;
- danmu.setGravity(Gravity.CENTER);
- container.addView(danmu, lp);
- danmu.send();
- topSendPosition.put(i,true);
- break;
- }
- }
- }
android 中的弹幕效果相关推荐
- Android中具有动画效果的图片资源
Android动画和Transition系列文章 初识属性动画--使用Animator创建动画 再谈属性动画--介绍以及自定义Interpolator插值器 三谈属性动画--Keyframe以及Vie ...
- 【Android笔记25】Android中的动画效果之逐帧动画
这篇文章,主要介绍Android中的动画效果之逐帧动画. 目录 一.逐帧动画 1.1.什么是逐帧动画 1.2.逐帧动画的使用 (1)创建drawable动画资源<
- android 如何实现弹幕,Android简单实现弹幕效果
本文实例为大家分享了Android实现弹幕效果的具体代码,供大家参考,具体内容如下 首先分析一下,他是由三层布局来共同完成的,第一层视频布局,第二层字幕布局,第三层输入框布局,要想让这三个布局在同一页 ...
- android中帧布局效果,Android开发实现布局帧布局霓虹灯效果示例
本文实例讲述了android开发实现布局帧布局霓虹灯效果.分享给大家供大家参考,具体如下: 效果图: 实现方式: framelayout中,设置8个textview,在主函数中,设计颜色数组,通过有序 ...
- android 弹幕动画,Android自制精彩弹幕效果
好久没有写过文章,最近发现直播特别的火,很多app都集成了直播的功能,发现有些直播是带有弹幕的,效果还不错,今天心血来潮,特地写了篇制作弹幕的文章. 今天要实现的效果如下: 1.弹幕垂直方向固定 2. ...
- android中实现毛笔效果(View 中绘图)
最近有一个项目设计一个APP实现通过触摸屏实现毛笔写字效果.传统的绘画板程序直接通过Path的moveTo和LineTo便可实现简单的线条绘画程序.然而要达到毛笔的笔锋效果则需要更为详细点的设计.我的 ...
- android中实现毛笔效果(View 中画图)
近期有一个项目设计一个APP实现通过触摸屏实现毛笔写字效果.传统的绘画板程序直接通过Path的moveTo和LineTo便可实现简单的线条绘画程序.然而要达到毛笔的笔锋效果则须要更为具体点的设计.我的 ...
- android中帧布局效果,布局之FrameLayout(帧布局)详解
New UI-布局之FrameLayout(帧布局)详解 --转载请注明出处:coder-pig,欢迎转载,请勿用于商业用途!本节引言:FrameLayout(帧布局)可以说是六大布局中最为简单的一 ...
- android毛玻璃效果,Android 中实现毛玻璃效果
- 关于高斯模糊效果的实现 public class BitmapLoader { private Context mContext; public BitmapLoader(Context cont ...
最新文章
- 李沐团队新作Gluon,复现CV经典模型到BERT,简单好用 | 强烈推荐
- 如何查看crontab的日志记录
- windows server 2008 R2 初试Hyper-V(一)
- 二极管极低电流I-V特性测量
- U-Boot常用命令
- html5图片加载不了,webView加载html图片遇到的问题解决
- flannel源码分析--newSubnetManager
- 开发可以复用的构件和利用可以复用的构件进行开发
- wi-fi共享大师免广告_如何保护Wi-Fi网络免受入侵
- Maximize The Beautiful Value
- linux mac地址文件夹,android4.4.2系统的mac地址文件在哪个文件里面
- 知乎热问:进入内核态究竟是什么意思?
- cannot resolve method ‘println(java.lang.String)
- wps的range对象
- 驱动读写应用程序内存
- KeilC51单片机外部中断原理解释
- 成长之路——发现问题、提出问题和解决问题
- VR这张旧船票,能否登上元宇宙这艘宇宙飞船?
- 面试问离职原因,怎么说才好?
- python爬虫 爬取图片