首页 > 系统 > Android > 正文

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

2019-12-12 03:57:08
字体:
来源:转载
供稿:网友

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

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

布局很简单,上面是一个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程序设计有所帮助。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表