当前位置: 移动技术网 > 移动技术>移动开发>Android > 实例解析如何在Android应用中实现弹幕动画效果

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

2019年07月24日  | 移动技术网移动技术  | 我要评论

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

2016428173817427.gif (1280×720)

 从直观上,弹幕效果就是在一个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产生不同的滑动效果等等。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网