当前位置: 移动技术网 > 移动技术>移动开发>Android > 很棒的Android弹幕效果实例

很棒的Android弹幕效果实例

2019年07月24日  | 移动技术网移动技术  | 我要评论
很多项目需要用到弹幕效果,尤其是在播放视频的时候需要一起显示别人发的弹幕,也包括自己的发的。 今天就试着写了一下这个效果。  思路就是将从右往左的动画效果,字

很多项目需要用到弹幕效果,尤其是在播放视频的时候需要一起显示别人发的弹幕,也包括自己的发的。

今天就试着写了一下这个效果。

 思路就是将从右往左的动画效果,字体内容,字体大小,弹幕平移速度等属性一起与textview封装成barrageitem,并将控制效果与barrageitem绑定在barrageview进行显示。思路还是比较简单的。这里没有考虑到带有表情的弹幕,我会持续更新的。

 先看效果:

                   

 项目目录结构:

                         

 接下来定义barrageitem.class : 这个类就将textview与从右往左的动画效果,字体内容,字体大小,弹幕平移速度等属性绑定。              

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

barrageview.class:

public class barrageview extends relativelayout { 
 
  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; 
 
  // 速度,ms 
  private int maxspeed = 12000; 
 
  // 速度,ms 
  private int minspeed = 8000; 
 
  // 文字最大值 
  private int maxsize = 50; 
 
  // 文字最小值 
  private int minsize = 10; 
 
  private int totalheight = 0; 
 
  private int lineheight = 0;// 每一行弹幕的高度 
 
  private int totalline = 0;// 弹幕的行数 
 
  private string[] itemtext = { "他们都说蔡睿智很帅,但他总觉得自己很丑", 
      "他们都说蔡睿智是男神,但他只觉得自己是男生", "蔡睿智不是男神,蔡睿智是男生", "蔡睿智貌似是gay", "蔡睿智是弯的", 
      "蔡睿智是弯的,还好现在掰回来了", "他承受了他这个年纪不该有的机智与帅气,他好累", 
      "我恨自己的颜值,我觉得自己的才华才是吸引别人的地方", "他为什么对妹子不感兴趣呢?为什么?", "他为什么不想谈恋爱","他不会去爱别人,同时也不希望别人去爱他,他已经习惯一个人了", 
      "他的心里是否住着一个苍老的小孩", "他的世界一直就是他和他的影子,直到遇到她", "她引导他走出了自己的世界,改变他的很多看法", 
      "他渐渐的发现自己已经离不开他,他选择不再去压抑自己", "因为他已经不是那个无能为力的年纪","她经常说他 高冷,现在越来越觉得他恨闷骚","开始他一直与她保持朋友距离,但他发现自己根本作不到"}; 
  private int textcount; 
 
  public barrageview(context context, attributeset attrs, int defstyleattr) { 
    super(context, attrs, defstyleattr); 
    mcontext = context; 
    _init(); 
  } 
 
  public barrageview(context context, attributeset attrs) { 
    this(context, null, 0); 
 
  } 
 
  public barrageview(context context) { 
    this(context, null); 
 
  } 
 
  private void _init() { 
    textcount = itemtext.length; 
    int duration = (int) ((barrage_gap_max_duration - barrage_gap_min_duration) * math 
        .random()); 
    mhandler.sendemptymessagedelayed(0, duration); 
  } 
 
  @override 
  public void onwindowfocuschanged(boolean haswindowfocus) { 
    super.onwindowfocuschanged(haswindowfocus); 
    totalheight = getmeasuredheight(); 
    lineheight = getlineheight(); 
    totalline = totalheight / lineheight; 
  } 
 
  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); 
  } 
 
  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 arg0) { 
 
      } 
 
      @override 
      public void onanimationrepeat(animation arg0) { 
         
      } 
 
      @override 
      public void onanimationend(animation arg0) { 
        item.textview.clearanimation(); 
        barrageview.this.removeview(item.textview); 
      } 
    }); 
    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; 
  } 
 
  /** 
   * 计算textview中字符串的长度 
   * 
   * @param item 
   * @param text 
   *      要计算的字符串 
   * @param size 
   *      字体大小 
   * @return textview中字符串的长度 
   */ 
  public float gettextwidth(barrageitem item, string text, float size) { 
    rect bounds = new rect(); 
    textpaint paint; 
    paint = item.textview.getpaint(); 
    paint.gettextbounds(text, 0, text.length(), bounds); 
    return bounds.width(); 
  } 
 
  /** 
   * 获得每一行弹幕的最大高度 
   */ 
  private int getlineheight() { 
    barrageitem item = new barrageitem(); 
    string tx = itemtext[0]; 
    item.textview = new textview(mcontext); 
    item.textview.settext(tx); 
    item.textview.settextsize(maxsize); 
 
    rect bounds = new rect(); 
    textpaint paint; 
    paint = item.textview.getpaint(); 
    paint.gettextbounds(tx, 0, tx.length(), bounds); 
    return bounds.height(); 
  } 
 
  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); 
    } 
  } 
 
} 

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

 mainactivity.class:

<span style="font-size:18px;">public class mainactivity extends activity { 
 
  @override 
  protected void oncreate(bundle savedinstancestate) { 
    super.oncreate(savedinstancestate); 
    setcontentview(r.layout.activity_main); 
  } 
}</span> 

以上就是弹幕的源码,其实我觉得这里少了自己发送弹幕的功能,我会在以后的更新上去的,共勉。

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网