android 评论弹幕,android 弹幕评论效果

纯粹依照自己的想法仿照b站的弹幕写的一个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();

}

将弹幕放在一个相对布局容器中

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

{

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

{

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;

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值