中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android編程實現簡易彈幕效果示例【附demo源碼下載】

發布時間:2020-10-23 23:24:38 來源:腳本之家 閱讀:187 作者:books1958 欄目:移動開發

本文實例講述了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程序設計有所幫助。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

江陵县| 平安县| 汉中市| 福鼎市| 衢州市| 尖扎县| 治县。| 赞皇县| 即墨市| 玛多县| 承德县| 瑞金市| 商城县| 普宁市| 治多县| 紫阳县| 阿坝| 台北市| 克东县| 桃源县| 常德市| 谷城县| 临沭县| 集贤县| 湘西| 巫山县| 临朐县| 盐边县| 南汇区| 斗六市| 洪江市| 太谷县| 谢通门县| 灵宝市| 恭城| 沈丘县| 兴和县| 兴宁市| 兴海县| 铁岭市| 新安县|