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

Android编程实现简易弹幕效果示例【附demo源码下载】

程序员文章站 2024-02-20 10:54:41
本文实例讲述了android编程实现简易弹幕效果。分享给大家供大家参考,具体如下: 首先上效果图,类似于360检测到骚扰电话页面: 布局很简单,上面是一个relat...

本文实例讲述了android编程实现简易弹幕效果。分享给大家供大家参考,具体如下:

首先上效果图,类似于360检测到骚扰电话页面:

Android编程实现简易弹幕效果示例【附demo源码下载】

布局很简单,上面是一个relativelayout,下面一个button.

功能:

(1)弹幕生成后自动从右侧往左侧滚动(translateanimation),弹幕消失后立刻被移除。
(2)弹幕位置随机出现,并且不重复(防止文字重叠)。
(3)字体大小在一定范围内随机改变,字体颜色也可以设置。
(4)自定义先减速,后加速的interpolator,弹幕加速进入、减速停留、然后加速出去。

1.activity代码:

/**
 * 简易弹幕效果实现
 * created by admin on 15-6-4.
 */
public class mainactivity extends actionbaractivity {
  private myhandler handler;
  //弹幕内容
  private tanmubean tanmubean;
  //放置弹幕内容的父组件
  private relativelayout containervg;
  //父组件的高度
  private int validheightspace;
  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_main);
    containervg = (relativelayout) findviewbyid(r.id.tanmu_container);
    tanmubean = new tanmubean();
    tanmubean.setitems(new string[]{"测试一下", "弹幕这东西真不好做啊", "总是出现各种问题~~", "也不知道都是为什么?麻烦!", "哪位大神可以帮帮我啊?", "i need your help.",
        "测试一下", "弹幕这东西真不好做啊", "总是出现各种问题~~", "也不知道都是为什么?麻烦!", "哪位大神可以帮帮我啊?", "i need your help.",
        "测试一下", "弹幕这东西真不好做啊", "总是出现各种问题~~", "也不知道都是为什么?麻烦!", "哪位大神可以帮帮我啊?", "i need your help."});
    handler = new myhandler(this);
    //开始弹幕
    view starttanmuview = findviewbyid(r.id.starttanmu);
    starttanmuview.setonclicklistener(new view.onclicklistener() {
      @override
      public void onclick(view v) {
        if (containervg.getchildcount() > 0) {
          return;
        }
        existmarginvalues.clear();
        new thread(new createtanmuthread()).start();
      }
    });
  }
  //每2s自动添加一条弹幕
  private class createtanmuthread implements runnable {
    @override
    public void run() {
      int n = tanmubean.getitems().length;
      for (int i = 0; i < n; i++) {
        handler.obtainmessage(1, i, 0).sendtotarget();
        systemclock.sleep(2000);
      }
    }
  }
  //需要在主线城中添加组件
  private static class myhandler extends handler {
    private weakreference<mainactivity> ref;
    myhandler(mainactivity ac) {
      ref = new weakreference<>(ac);
    }
    @override
    public void handlemessage(message msg) {
      super.handlemessage(msg);
      if (msg.what == 1) {
        mainactivity ac = ref.get();
        if (ac != null && ac.tanmubean != null) {
          int index = msg.arg1;
          string content = ac.tanmubean.getitems()[index];
          float textsize = (float) (ac.tanmubean.getmintextsize() * (1 + math.random() * ac.tanmubean.getrange()));
          int textcolor = ac.tanmubean.getcolor();
          ac.showtanmu(content, textsize, textcolor);
        }
      }
    }
  }
  private void showtanmu(string content, float textsize, int textcolor) {
    final textview textview = new textview(this);
    textview.settextsize(textsize);
    textview.settext(content);
//    textview.setsingleline();
    textview.settextcolor(textcolor);
    int leftmargin = containervg.getright() - containervg.getleft() - containervg.getpaddingleft();
    //计算本条弹幕的topmargin(随机值,但是与屏幕中已有的不重复)
    int verticalmargin = getrandomtopmargin();
    textview.settag(verticalmargin);
    layoutparams params = new layoutparams(layoutparams.wrap_content, layoutparams.wrap_content);
    params.addrule(relativelayout.align_parent_top);
    params.topmargin = verticalmargin;
    textview.setlayoutparams(params);
    animation anim = animationhelper.createtranslateanim(this, leftmargin, -screenutils.getscreenw(this));
    anim.setanimationlistener(new animation.animationlistener() {
      @override
      public void onanimationstart(animation animation) {
      }
      @override
      public void onanimationend(animation animation) {
        //移除该组件
        containervg.removeview(textview);
        //移除占位
        int verticalmargin = (int) textview.gettag();
        existmarginvalues.remove(verticalmargin);
      }
      @override
      public void onanimationrepeat(animation animation) {
      }
    });
    textview.startanimation(anim);
    containervg.addview(textview);
  }
  //记录当前仍在显示状态的弹幕的位置(避免重复)
  private set<integer> existmarginvalues = new hashset<>();
  private int linescount;
  private int getrandomtopmargin() {
    //计算用于弹幕显示的空间高度
    if (validheightspace == 0) {
      validheightspace = containervg.getbottom() - containervg.gettop()
          - containervg.getpaddingtop() - containervg.getpaddingbottom();
    }
    //计算可用的行数
    if (linescount == 0) {
      linescount = validheightspace / screenutils.dp2px(this, tanmubean.getmintextsize() * (1 + tanmubean.getrange()));
      if (linescount == 0) {
        throw new runtimeexception("not enough space to show text.");
      }
    }
    //检查重叠
    while (true) {
      int randomindex = (int) (math.random() * linescount);
      int marginvalue = randomindex * (validheightspace / linescount);
      if (!existmarginvalues.contains(marginvalue)) {
        existmarginvalues.add(marginvalue);
        return marginvalue;
      }
    }
  }
}

2.平移动画生成工具:

public class animationhelper {
  /**
   * 创建平移动画
   */
  public static animation createtranslateanim(context context, int fromx, int tox) {
    translateanimation tlanim = new translateanimation(fromx, tox, 0, 0);
    //自动计算时间
    long duration = (long) (math.abs(tox - fromx) * 1.0f / screenutils.getscreenw(context) * 4000);
    tlanim.setduration(duration);
    tlanim.setinterpolator(new decelerateaccelerateinterpolator());
    tlanim.setfillafter(true);
    return tlanim;
  }
}

screenutils是用来获取屏幕宽高、dp与px之间互转的工具类。

3.自定义的interpolator,其实只有一行代码

public class decelerateaccelerateinterpolator implements interpolator {
  //input从0~1,返回值也从0~1.返回值的曲线表征速度加减趋势
  @override
  public float getinterpolation(float input) {
    return (float) (math.tan((input * 2 - 1) / 4 * math.pi)) / 2.0f + 0.5f;
  }
}

4.tanmubean是一个实体类

public class tanmubean {
  private string[] items;
  private int color;
  private int mintextsize;
  private float range;
  public tanmubean() {
    //init default value
    color = color.parsecolor("#eeeeee");
    mintextsize = 16;
    range = 0.5f;
  }
  public string[] getitems() {
    return items;
  }
  public void setitems(string[] items) {
    this.items = items;
  }
  public int getcolor() {
    return color;
  }
  public void setcolor(int color) {
    this.color = color;
  }
  /**
   * min textsize, in dp.
   */
  public int getmintextsize() {
    return mintextsize;
  }
  public void setmintextsize(int mintextsize) {
    this.mintextsize = mintextsize;
  }
  public float getrange() {
    return range;
  }
  public void setrange(float range) {
    this.range = range;
  }
}

完整实例代码点击此处本站下载

更多关于android相关内容感兴趣的读者可查看本站专题:《android视图view技巧总结》、《android开发动画技巧汇总》、《android编程之activity操作技巧总结》、《android布局layout技巧总结》、《android开发入门与进阶教程》、《android资源操作技巧汇总》及《android控件用法总结

希望本文所述对大家android程序设计有所帮助。