91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

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

如何在Android中利用View顯示分數

發布時間:2020-11-25 15:26:42 來源:億速云 閱讀:569 作者:Leah 欄目:移動開發

這篇文章給大家介紹如何在Android中利用View顯示分數,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

所用的知識:

(1)自定義View中的 path ,主要用來繪制指示塊。

(2)屬性動畫-ValueAnimator,并設置屬性動畫的監聽器。

(3)根據屬性動畫是否結束的標志,決定是否繪制分數對應的描述文本內容。

實現步驟:

繼承自View,在構造函數中獲取自定義屬性和初始化操作(初始化畫筆)

private void obtainAttrs(Context context, AttributeSet attrs) {
    TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ScoreView);
    lineLength = typedArray.getDimension(R.styleable.ScoreView_lineLength, dp2Px(10));
    lineColor = typedArray.getColor(R.styleable.ScoreView_lineColor, Color.WHITE);
    typedArray.recycle();
  }
  private void init() {
    arrowPaint = createPaint(Color.WHITE, 0, Paint.Style.FILL, 0);
    arcPaint = createPaint(lineColor, dp2Px(1), Paint.Style.STROKE, 0);
    bgPaint = createPaint(lineColor, dp2Px(1), Paint.Style.FILL, 0);
    reachProgressPaint = createPaint(Color.WHITE, dp2Px(1), Paint.Style.FILL, 0);
    arcReachPaint = createPaint(Color.WHITE, dp2Px(1), Paint.Style.STROKE, 0);
    scoreTextPaint = createPaint(Color.WHITE, 0, Paint.Style.STROKE, dp2Px(26));
    descTextPaint = createPaint(Color.WHITE, 0, Paint.Style.STROKE, dp2Px(16));
  }

其中初始化畫筆抽取到一個函數中:

private Paint createPaint(int color, int strokeWidth, Paint.Style style, float textSize) {
    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    paint.setColor(color);
    paint.setStrokeWidth(strokeWidth);
    paint.setStyle(style);
    paint.setStrokeJoin(Paint.Join.ROUND);
    paint.setStrokeCap(Paint.Cap.ROUND);
    paint.setTextSize(textSize);
    return paint;
  }

覆蓋 onSizeChanged() ,得到控件的寬高,并決定要繪制區域的大小(控件默認設置了內邊距)

@Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    viewWidth = w;
    viewHeight = h;
    halfView = Math.min(viewWidth, viewHeight) / 2;  //寬度或高度中最小值的一半,即決定圓心的位置。
    radius = (Math.min(viewWidth, viewHeight) - 2 * DEFAULT_PADDING) / 2; //繪制園的半徑是寬高除去默認內邊距
  }

核心繪制代碼,覆蓋onDraw()方法,根據動畫是否結束的標志,決定是否繪制分數對應的文本。

@Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    drawArcBackground(canvas);
    drawArcProgress(canvas);
    drawScoreText(canvas);
    if (isAnimEnd) {
      drawDescText(canvas);
    }
  }

(1)繪制圓弧背景和灰色刻度背景。

 private void drawArcBackground(Canvas canvas) {
    canvas.save();
    canvas.translate(halfView, halfView);
    //繪制圓弧
    RectF rectF = new RectF(dp2Px(5) - radius, dp2Px(5) - radius, radius - dp2Px(5), radius - dp2Px(5));
    canvas.drawArc(rectF, 120, 300, false, arcPaint);
    //繪制刻度線
    canvas.rotate(30);
    for (int i = 0; i < 100; i++) {
      canvas.drawLine(0, radius - dp2Px(15), 0,
          radius - dp2Px(15) - lineLength,
          bgPaint);
      canvas.rotate(degree);
    }
    canvas.restore();
  }

(2) 繪制刻度,根據ValueAnimator進行動畫的當前值curValue,來動態改變繪制指示塊和已達進度圓弧,從而實現從0開始移動到設定值的動畫效果。

private void drawArcProgress(Canvas canvas) {
    canvas.save();
    canvas.translate(halfView, halfView);
    //繪制圓弧
    RectF rectF = new RectF(dp2Px(5) - radius, dp2Px(5) - radius, radius - dp2Px(5), radius - dp2Px(5));
    canvas.drawArc(rectF, 120, curValue * degree, false, arcReachPaint);
    //繪制指示方塊,方塊是從0開始移動某一個位置的
    canvas.rotate(30 + degree * curValue);
    Path path = new Path();
    path.moveTo(dp2Px(5), radius);
    path.lineTo(dp2Px(5), radius - dp2Px(10));
    path.lineTo(0, radius - dp2Px(15));
    path.lineTo(-dp2Px(5), radius - dp2Px(10));
    path.lineTo(-dp2Px(5), radius);
    path.close();
    canvas.drawPath(path, arrowPaint);
    //繪制已經達到的刻度
    canvas.restore();
    canvas.save();
    canvas.translate(halfView, halfView);
    canvas.rotate(30);
    for (int i = 0; i < curValue; i++) {
      canvas.drawLine(0, radius - dp2Px(15), 0,
          radius - dp2Px(15) - lineLength,
          reachProgressPaint);
      canvas.rotate(degree);
    }
    canvas.restore();
  }

(3) 繪制分數文本。

private void drawScoreText(Canvas canvas) {
    canvas.save();
    canvas.translate(halfView, halfView);
    String scoreText = curValue + "分";
    float textLength = scoreTextPaint.measureText(scoreText);
    canvas.drawText(scoreText, -textLength / 2, 0, scoreTextPaint);
    canvas.restore();
  }

(4) 動畫結束時,繪制最終分數對應的提示信息,該信息只有在動畫結束后,才會顯示出來。

private void drawDescText(Canvas canvas) {
    canvas.save();
    canvas.translate(halfView, halfView);
    String desc = "";
    if (curValue >= 90) {
      desc = "車神";
    } else {
      desc = "馬路殺手";
    }
    float descLength = descTextPaint.measureText(desc);
    canvas.drawText(desc, -descLength / 2, dp2Px(30), descTextPaint);
    canvas.restore();
    isAnimEnd = false; // isAnimEnd置為false,防止再次點擊start時,就顯示動畫結束時才能顯示的內容
  }

(5)提供對外設置最大值的接口,決定最后的分數。

 /**
   * 對外提供的接口,用于設置進度的最大值
   *
   * @param value
   */
  public void setMaxValue(int value) {
    if (valueAnimator == null) {
      valueAnimator = ValueAnimator.ofInt(0, value);
    }
    valueAnimator.setInterpolator(new LinearInterpolator());
    valueAnimator.setDuration(30 * value);
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
      @Override
      public void onAnimationUpdate(ValueAnimator animation) {
        curValue = (int) animation.getAnimatedValue();
        Log.i("debug", "curValue=" + curValue);
        invalidate();
      }
    });
    valueAnimator.addListener(new AnimatorListenerAdapter() {
      @Override
      public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
        isAnimEnd = true; //標記動畫結束
        Log.i("debug", "onAnimationEnd");
        Log.i("debug", "onAnimationEnd curValue = " + curValue);
        invalidate();
      }
    });
    valueAnimator.start();
  }

完整代碼:

public class ScoreView extends View {
  private final int DEFAULT_PADDING = dp2Px(5);
  private final int DEFAULT_WIDTH = dp2Px(200);  //默認寬度為200dp
  private final int DEFAULT_HEIGHT = dp2Px(200); //默認高度為200dp
  private int viewWidth; //View寬度
  private int viewHeight;  //View高度
  private int halfView; //view寬度或高度的一半
  private int radius;  //繪制圓形區域的半徑
  private Paint bgPaint;
  private Paint arrowPaint; //指示塊畫筆
  private Paint arcPaint; //圓弧畫筆
  private Paint arcReachPaint; //圓弧畫筆
  private Paint reachProgressPaint; //已達刻度
  private Paint scoreTextPaint;  //繪制分數文本
  private Paint descTextPaint;  //繪制描述文本
  private float degree = 3f; //相鄰刻度之間夾角大小為3度,角度制,不是弧度制
  private float lineLength;
  private int lineColor;
  private int curValue;  //動畫進行的當前值
  private ValueAnimator valueAnimator;
  private boolean isAnimEnd = false;
  public ScoreView(Context context) {
    this(context, null);
  }
  public ScoreView(Context context, AttributeSet attrs) {
    super(context, attrs);
    obtainAttrs(context, attrs);
    init();
  }
  private void obtainAttrs(Context context, AttributeSet attrs) {
    TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ScoreView);
    lineLength = typedArray.getDimension(R.styleable.ScoreView_lineLength, dp2Px(10));
    lineColor = typedArray.getColor(R.styleable.ScoreView_lineColor, Color.WHITE);
    typedArray.recycle();
  }
  private void init() {
    arrowPaint = createPaint(Color.WHITE, 0, Paint.Style.FILL, 0);
    arcPaint = createPaint(lineColor, dp2Px(1), Paint.Style.STROKE, 0);
    bgPaint = createPaint(lineColor, dp2Px(1), Paint.Style.FILL, 0);
    reachProgressPaint = createPaint(Color.WHITE, dp2Px(1), Paint.Style.FILL, 0);
    arcReachPaint = createPaint(Color.WHITE, dp2Px(1), Paint.Style.STROKE, 0);
    scoreTextPaint = createPaint(Color.WHITE, 0, Paint.Style.STROKE, dp2Px(26));
    descTextPaint = createPaint(Color.WHITE, 0, Paint.Style.STROKE, dp2Px(16));
  }
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    setMeasuredDimension(measureSize(widthMeasureSpec, DEFAULT_WIDTH), measureSize(heightMeasureSpec, DEFAULT_HEIGHT));
  }
  private int measureSize(int measureSpec, int defaultSize) {
    int measureSize = defaultSize;
    int mode = MeasureSpec.getMode(measureSpec);
    int size = MeasureSpec.getSize(measureSpec);
    if (mode == MeasureSpec.EXACTLY) {
      measureSize = size;
    } else {
      if (mode == MeasureSpec.AT_MOST) {
        measureSize = Math.min(defaultSize, size);
      }
    }
    return measureSize;
  }
  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    viewWidth = w;
    viewHeight = h;
    halfView = Math.min(viewWidth, viewHeight) / 2;  //寬度或高度中最小值的一半,即圓形的位置
    radius = (Math.min(viewWidth, viewHeight) - 2 * DEFAULT_PADDING) / 2; //半徑是寬高除去默認內邊距的
  }
  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    drawArcBackground(canvas);
    drawArcProgress(canvas);
    drawScoreText(canvas);
    if (isAnimEnd) {
      drawDescText(canvas);
    }
  }
  private void drawScoreText(Canvas canvas) {
    canvas.save();
    canvas.translate(halfView, halfView);
    String scoreText = curValue + "分";
    float textLength = scoreTextPaint.measureText(scoreText);
    canvas.drawText(scoreText, -textLength / 2, 0, scoreTextPaint);
    canvas.restore();
  }
  /**
   * 繪制文本
   *
   * @param canvas
   */
  private void drawDescText(Canvas canvas) {
    canvas.save();
    canvas.translate(halfView, halfView);
    String desc = "";
    if (curValue >= 90) {
      desc = "車神";
    } else {
      desc = "馬路殺手";
    }
    float descLength = descTextPaint.measureText(desc);
    canvas.drawText(desc, -descLength / 2, dp2Px(30), descTextPaint);
    canvas.restore();
    isAnimEnd = false; // isAnimEnd置為false,防止再次點擊start時,就顯示動畫結束時才能顯示的內容
  }
  /**
   * 繪制進度
   *
   * @param canvas
   */
  private void drawArcProgress(Canvas canvas) {
    canvas.save();
    canvas.translate(halfView, halfView);
    //繪制圓弧
    RectF rectF = new RectF(dp2Px(5) - radius, dp2Px(5) - radius, radius - dp2Px(5), radius - dp2Px(5));
    canvas.drawArc(rectF, 120, curValue * degree, false, arcReachPaint);
    //繪制指示方塊,方塊是從0開始移動某一個位置的
    canvas.rotate(30 + degree * curValue);
    Path path = new Path();
    path.moveTo(dp2Px(5), radius);
    path.lineTo(dp2Px(5), radius - dp2Px(10));
    path.lineTo(0, radius - dp2Px(15));
    path.lineTo(-dp2Px(5), radius - dp2Px(10));
    path.lineTo(-dp2Px(5), radius);
    path.close();
    canvas.drawPath(path, arrowPaint);
    //繪制已經達到的刻度
    canvas.restore();
    canvas.save();
    canvas.translate(halfView, halfView);
    canvas.rotate(30);
    for (int i = 0; i < curValue; i++) {
      canvas.drawLine(0, radius - dp2Px(15), 0,
          radius - dp2Px(15) - lineLength,
          reachProgressPaint);
      canvas.rotate(degree);
    }
    canvas.restore();
  }
  /**
   * 繪制背景
   *
   * @param canvas
   */
  private void drawArcBackground(Canvas canvas) {
    canvas.save();
    canvas.translate(halfView, halfView);
    //繪制圓弧
    RectF rectF = new RectF(dp2Px(5) - radius, dp2Px(5) - radius, radius - dp2Px(5), radius - dp2Px(5));
    canvas.drawArc(rectF, 120, 300, false, arcPaint);
    //繪制刻度線
    canvas.rotate(30);
    for (int i = 0; i < 100; i++) {
      canvas.drawLine(0, radius - dp2Px(15), 0,
          radius - dp2Px(15) - lineLength,
          bgPaint);
      canvas.rotate(degree);
    }
    canvas.restore();
  }
  /**
   * 創建畫筆
   *
   * @param color
   * @param strokeWidth
   * @param style
   * @param textSize
   * @return
   */
  private Paint createPaint(int color, int strokeWidth, Paint.Style style, float textSize) {
    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    paint.setColor(color);
    paint.setStrokeWidth(strokeWidth);
    paint.setStyle(style);
    paint.setStrokeJoin(Paint.Join.ROUND);
    paint.setStrokeCap(Paint.Cap.ROUND);
    paint.setTextSize(textSize);
    return paint;
  }
  /**
   * dp轉換成px
   *
   * @param dpValue
   * @return
   */
  private int dp2Px(int dpValue) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
        dpValue, getResources().getDisplayMetrics());
  }
  /**
   * 對外提供的接口,用于設置進度的最大值
   *
   * @param value
   */
  public void setMaxValue(int value) {
    if (valueAnimator == null) {
      valueAnimator = ValueAnimator.ofInt(0, value);
    }
    valueAnimator.setInterpolator(new LinearInterpolator());
    valueAnimator.setDuration(30 * value);
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
      @Override
      public void onAnimationUpdate(ValueAnimator animation) {
        curValue = (int) animation.getAnimatedValue();
        Log.i("debug", "curValue=" + curValue);
        invalidate();
      }
    });
    valueAnimator.addListener(new AnimatorListenerAdapter() {
      @Override
      public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
        isAnimEnd = true; //標記動畫結束
        Log.i("debug", "onAnimationEnd");
        Log.i("debug", "onAnimationEnd curValue = " + curValue);
        invalidate();
      }
    });
    valueAnimator.start();
  }
}

關于如何在Android中利用View顯示分數就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

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

AI

嘉定区| 长顺县| 安国市| 贵定县| 宕昌县| 綦江县| 榆社县| 彰化市| 丰都县| 海原县| 海口市| 闵行区| 呼玛县| 宝兴县| 海宁市| 政和县| 白水县| 中山市| 大同县| 鄂温| 延川县| 个旧市| 房山区| 多伦县| 宜春市| 宝山区| 宜黄县| 南宫市| 施秉县| 奉贤区| 通榆县| 克什克腾旗| 丹阳市| 永寿县| 曲阜市| 富平县| 封丘县| 深州市| 长泰县| 怀化市| 绿春县|