纯粹依照自己的想法仿照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 弹幕评论效果的更多相关文章

  1. Android弹幕编程设计实现的解决方案(一)

     Android弹幕编程设计实现的解决方案(一) 在现在的一些视频类网站.视频类直播网站,比如A站和B站,当视频在播放的时候,会在屏幕上出现一些滚动的字幕,这些字幕是UGC,通常是用户的评论,称之 ...

  2. 【Android源代码下载】收集整理android界面UI效果源码

    在Android开发中,Android界面UI效果设计一直都是很多童鞋关注的问题,今天给大家分享下大神收集整理的多个android界面UI效果,都是源码,都是干货,贡献给各位网友! 话不多说,直接上效 ...

  3. Android ViewPager 动画效果

    找到个不错的开源项目:https://github.com/jfeinstein10/JazzyViewPager Android ViewPager 动画效果   

  4. android 弹幕效果demo

    记得之前有位朋友在我的公众号里问过我,像直播的那种弹幕功能该如何实现?如今直播行业确实是非常火爆啊,大大小小的公司都要涉足一下直播的领域,用斗鱼的话来讲,现在就是千播之战.而弹幕则无疑是直播功能当中最 ...

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

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

  6. Android 弹幕效果开发案例

    概述 现在有个很流行的效果就是弹幕效果,满屏幕的文字从右到左飘来飘去.看的眼花缭乱,看起来还蛮cool的 现在就是来实现这一的一个效果,大部分的都是从右向左移动漂移,本文的效果中也支持从左向右的漂移移 ...

  7. Android ListView各种效果实现总结,持续更新...

    一.ListView圆角:重写ListView的onInterceptTouchEvent方法,通过pointToPosition(x,y)方法判断当前点击位置所对应的项,有三种情况:分别是第一项.最 ...

  8. Android 遮罩层效果

    (用别人的代码进行分析) 不知道在开发中有没有经常使用到这种效果,所谓的遮罩层就是给一张图片不是我们想要的形状,这个时候我们就可以使用遮罩效果把这个图片变成我们想要的形状,一般使用最多就是圆形的效果, ...

  9. Android登录等待效果

    上一篇为大家分享了关于AsyncTask的使用,本篇结合AsyncTask为大家介绍一个我们经常看到的一个效果,就是当我们点击登录后,会弹出一个请等待的小窗体,这个效果是如何实现的呢?本篇我就带大家简 ...

随机推荐

  1. Configure Tomcat 7 to run Python CGI scripts in windows(Win7系统配置tomcat服务器,使用python进行cgi编程)

    Pre-installation requirements1. Java2. Python steps1. Download latest version of Tomcat (Tomcat 7) f ...

  2. 题解 P2610 【[ZJOI2012]旅游】

    今天模拟赛考了这道题,那就来水一篇题解吧...(话说提高组模拟赛考什么省选题啊??) 这道题要我们求一条线段最多能经过的三角形数量. 回想小学学过的奥数,老师告诉过我们这样一件事:`点无大小 线无粗细 ...

  3. Ehcache学习总结(3)--Ehcache 整合Spring 使用页面、对象缓存

    Ehcache 整合Spring 使用页面.对象缓存 Ehcache在很多项目中都出现过,用法也比较简单.一般的加些配置就可以了,而且Ehcache可以对页面.对象.数据进行缓存,同时支持集群/分布式 ...

  4. WebKit载入流程 - 概述

    之前写了几篇载入流程的说明,是从下向上看,有点仅仅见树木不见森林的感觉.经过近期一段时间的学习,有了能加以概括抽象的方法. WebKit载入流程和页面组成是直接相关的,页面就是WebKit要载入的对象 ...

  5. 保存数据同一时候查询保存数据记录的ID

    保存数据时同一时候取出该数据的记录ID insert into Table(a,b) values(1,2) select @@identity

  6. Firefox中使用pac

    https://campus.barracuda.com/product/websecurityservice/article/WSS/ConfigProxyWithPACFile/ https:// ...

  7. 让透明div里的文字不透明

    最近在工作中遇到一个问题,我在div里写上文字,当我把div变为半透明的时候,里面的文字也会随之透明.情况如下: <div class="box"> 这是一段不应该透明 ...

  8. BZOJ 1579 道路升级 Dijkstra

    思路: 这道题 不能把所有边都建出来 会MLE的!!! oh gosh 其实不建所有的边 用的时候再调就行了-.(也没啥区别) //By SiriusRen #include <queue> ...

  9. Ionic2集成ngx-datatable,ng2-tree第三方控件.md

    1. 基本环境配置 1.1. 命令安装相应的依赖 1.2. 在Module定义中引入对应Module 1.3. 引入对应的CSS 2. 简单使用示例验证是否集成成功 2.1. ngx-datatabl ...

  10. Vue或React多页应用脚手架

    https://github.com/zhujiasheng/vue-multipage https://github.com/MeCKodo/vue-multipage