欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

实例解析如何在Android应用中实现弹幕动画效果

程序员文章站 2024-03-01 23:40:40
在b站或者其他视频网站看视频时,常常会打开弹幕效果,边看节目边看大家的吐槽。弹幕看起来很有意思,今天我们就来实现一个简单的弹幕效果。  从直观上,弹幕效...

在b站或者其他视频网站看视频时,常常会打开弹幕效果,边看节目边看大家的吐槽。弹幕看起来很有意思,今天我们就来实现一个简单的弹幕效果。

实例解析如何在Android应用中实现弹幕动画效果

 从直观上,弹幕效果就是在一个viewgroup上增加一些view,然后让这些view移动起来。所以,整体的实现思路大概是这样的:
1、定义一个relativelayout,在里面动态添加textview。
2、这些textview的字体大小、颜色、移动速度、初始位置都是随机的。
3、将textview添加到relativelayout的右边缘,每隔一段时间添加一个。
4、对每个textview做平移动画,使得textview从右向左移动。
5、当textview从左边移动出屏幕,将textview从relativelayout中移除。
       有了思路下面就来看具体的代码。
       首先定义barrageitem,用来存储每一个弹幕项的相关信息,包括字体内容、字体大小颜色、移动速度、垂直方向的位置、字体占据的宽度等。
 

public class barrageitem { 
  public textview textview; 
  public int textcolor; 
  public string text; 
  public int textsize; 
  public int movespeed;//移动速度 
  public int verticalpos;//垂直方向显示的位置 
  public int textmeasuredwidth;//字体显示占据的宽度 
} 

       然后定义barrageview,由于弹幕的字体颜色大小和移动速度都是随机的,需要定义最大最小值来限定它们的范围,然后通过产生随机数来设置它们在这个范围内的值。另外还需要定义弹幕的文本内容,这里是直接写死的一些固定值。
 
 

  private context mcontext; 
  private barragehandler mhandler = new barragehandler(); 
  private random random = new random(system.currenttimemillis()); 
  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 = 5000;//速度,ms 
  private int maxsize = 30;//文字大小,dp 
  private int minsize = 15;//文字大小,dp 
 
  private int totalheight = 0; 
  private int lineheight = 0;//每一行弹幕的高度 
  private int totalline = 0;//弹幕的行数 
  private string[] itemtext = {"是否需要帮忙", "what are you 弄啥来", "哈哈哈哈哈哈哈", "抢占沙发。。。。。。", "************", "是否需要帮忙","我不会轻易的狗带", "嘿嘿", "这是我见过的最长长长长长长长长长长长的评论"}; 
  private int textcount; 
//  private list<barrageitem> itemlist = new arraylist<barrageitem>(); 
 
  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(); 
  } 

       如果弹幕显示的垂直位置是随机的,就会出现垂直方向上弹幕重叠的情况,所以需要根据高度对垂直方向按照弹幕高度的最大值等分,然后让弹幕在这些指定的垂直位置随机分布。这个值在onwindowfocuschanged里计算,因为在这个方法中通过view的getmeasuredheight()得到的高度不为空。
 

@override 
public void onwindowfocuschanged(boolean haswindowfocus) { 
  super.onwindowfocuschanged(haswindowfocus); 
  totalheight = getmeasuredheight(); 
  lineheight = getlineheight(); 
  totalline = totalheight / lineheight; 
} 
    通过handler的sendemptymessagedelayed每隔随机的时间产生一个弹幕项。下面的代码设置弹幕项的属性。
 
class barragehandler extends handler { 
  @override 
  public void handlemessage(message msg) { 
    super.handlemessage(msg); 
    generateitem(); 
    //每个弹幕产生的间隔时间随机 
    int duration = (int) ((barrage_gap_max_duration - barrage_gap_min_duration) * math.random()); 
    this.sendemptymessagedelayed(0, duration); 
  } 
} 
 
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; 
  } 
  item.verticalpos = random.nextint(totalline) * lineheight; 
  showbarrageitem(item); 
} 

将每一个弹幕项添加到视图上,并给view添加一个translateanimation动画,当动画结束时,将view从视图上移除。

 

private void showbarrageitem(final barrageitem item) { 
 
    int leftmargin = this.getright() - this.getleft() - this.getpaddingleft(); 
 
    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() { 
      @override 
      public 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) { 
    translateanimation anim = new translateanimation(leftmargin, -item.textmeasuredwidth, 0, 0); 
    anim.setduration(item.movespeed); 
    anim.setinterpolator(new acceleratedecelerateinterpolator()); 
    anim.setfillafter(true); 
    return anim; 
  } 

这样就完成了弹幕的功能,实现原理并不复杂。可以根据具体的需求来增加更多的控制,如控制每一行弹幕不重复,控制弹幕移动的interpolator产生不同的滑动效果等等。