Android 사용자 정의 링 카운트다운 컨트롤

14230 단어 Android카운트다운
본 사례 는 안 드 로 이 드 사용자 정의 링 카운트다운 컨트롤 의 구체 적 인 코드 를 공유 하 였 으 며,구체 적 인 내용 은 다음 과 같 습 니 다.
먼저 최종 효과 도 를 한 장 주세요.

주요 사고방식: 그 라 데 이 션 색 링 을 그 릴 때 속성 애니메이션 을 설정 하고 속성 애니메이션 의 실행 시간 에 따라 카운트다운 시간 으로 합 니 다.속성 애니메이션 의 진 도 를 감청 하여 카운트다운 의 목적 을 달성 합 니 다.
두말 하지 않 고 코드 를 직접 붙 여 라.구체 적 인 실현 방향 은 모두 주석 에 있다.
사용자 정의 속성:

<declare-styleable name="CountDownProgressBar">
  <attr name="countDown_circleWidth" format="dimension" />
  <attr name="countDown_centerTextSize" format="dimension" />
  <attr name="countDown_betaAngle" format="integer" />
  <attr name="countDown_firstColor" format="color" />
  <attr name="countDown_secondColor" format="color" />
  <attr name="countDown_centerTextColor" format="color" />
  <attr name="countDown_isShowGradient" format="boolean" />
</declare-styleable>
주 코드:

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.LinearInterpolator;
 
import com.daodaojk.myapplication.R;
 
public class CountDownProgressBar extends View {
 /**
  *       
  */
 private int maxValue = 200;
 
 /**
  *      
  */
 private int currentValue ;
 
 /**
  *        ,                ,alphaAngle=(currentValue/maxValue)*360
  */
 private float alphaAngle;
 
 /**
  *        ,   Color.LTGRAY
  */
 private int firstColor;
 
 /**
  *          
  */
 private int secondColor;
 /**
  *       (    )
  */
 private int centerTextColor = Color.BLUE;
 /**
  *          (  40dp)
  */
 private int centerTextSize;
 
 /**
  *      
  */
 private int circleWidth;
 
 /**
  *       
  */
 private Paint circlePaint;
 
 /**
  *       
  */
 private Paint textPaint;
 /**
  *        
  */
 private boolean isShowGradient = false;
 
 /**
  *         
  */
 private int[] colorArray = new int[]{Color.parseColor("#2773FF"),
   Color.parseColor("#27C0D2"), Color.parseColor("#40C66E")};
 private int duration;
 private OnFinishListener listener;
 private ValueAnimator animator;
 
 public CountDownProgressBar(Context context) {
  this(context, null);
 }
 
 
 public CountDownProgressBar(Context context, AttributeSet attrs) {
  this(context, attrs, 0);
 }
 
 
 public CountDownProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
 
  TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CountDownProgressBar,
    defStyleAttr, 0);
  int n = ta.getIndexCount();
 
  for (int i = 0; i < n; i++) {
   int attr = ta.getIndex(i);
   switch (attr) {
    case R.styleable.CountDownProgressBar_countDown_firstColor:
     firstColor = ta.getColor(attr, Color.LTGRAY); //         
     break;
    case R.styleable.CountDownProgressBar_countDown_secondColor:
     secondColor = ta.getColor(attr, Color.BLUE); //           
     break;
    case R.styleable.CountDownProgressBar_countDown_centerTextSize:
     centerTextSize = ta.getDimensionPixelSize(attr, (int) dip2px(40)); //            40dp
     break;
    case R.styleable.CountDownProgressBar_countDown_circleWidth:
     circleWidth = ta.getDimensionPixelSize(attr, (int) dip2px(6f)); //        6dp
     break;
    case R.styleable.CountDownProgressBar_countDown_centerTextColor:
     centerTextColor = ta.getColor(attr, Color.BLUE); //            
     break;
    case R.styleable.CountDownProgressBar_countDown_isShowGradient:
     isShowGradient = ta.getBoolean(attr, false); //         
     break;
    default:
     break;
   }
  }
  ta.recycle();
 
  circlePaint = new Paint();
  circlePaint.setAntiAlias(true); //    
  circlePaint.setDither(true); //    
  circlePaint.setStrokeWidth(circleWidth);//    
 
  textPaint = new Paint();
  textPaint.setAntiAlias(true);
  textPaint.setDither(true);
 }
 
 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  //             ,                  ,         
  int widthPixels = this.getResources().getDisplayMetrics().widthPixels;//     
  int heightPixels = this.getResources().getDisplayMetrics().heightPixels;//     
  int width = MeasureSpec.getSize(widthMeasureSpec);
  int hedight = MeasureSpec.getSize(heightMeasureSpec);
  int minWidth = Math.min(widthPixels, width);
  int minHedight = Math.min(heightPixels, hedight);
  setMeasuredDimension(Math.min(minWidth, minHedight), Math.min(minWidth, minHedight));
 }
 
 @Override
 protected void onDraw(Canvas canvas) {
  int center = this.getWidth() / 2;
  int radius = center - circleWidth / 2;
 
  drawCircle(canvas, center, radius); //       
  drawText(canvas, center);
 }
 
 /**
  *       
  *
  * @param canvas     
  * @param center    x y  
  * @param radius     
  */
 private void drawCircle(Canvas canvas, int center, int radius) {
  circlePaint.setShader(null); //       shader
  circlePaint.setColor(firstColor); //          ,         
  circlePaint.setStyle(Paint.Style.STROKE); //          
  canvas.drawCircle(center, center, radius, circlePaint); //        
  RectF oval = new RectF(center - radius, center - radius, center + radius, center + radius); //        
  if (isShowGradient) {
   //         
   // shader  Android              。Shader              ,          。
   LinearGradient linearGradient = new LinearGradient(circleWidth, circleWidth, getMeasuredWidth()
     - circleWidth, getMeasuredHeight() - circleWidth, colorArray, null, Shader.TileMode.MIRROR);
   circlePaint.setShader(linearGradient);
  }
  circlePaint.setShadowLayer(10, 10, 10, Color.BLUE);
  circlePaint.setColor(secondColor); //        
  circlePaint.setStrokeCap(Paint.Cap.ROUND); //           
 
  alphaAngle = currentValue * 360.0f / maxValue * 1.0f; //              ,            float  ,  alphaAngle   0
  canvas.drawArc(oval, -90, alphaAngle, false, circlePaint);
 }
 
 /**
  *     
  *
  * @param canvas     
  * @param center    x y  
  */
 private void drawText(Canvas canvas, int center) {
  int result = ((maxValue - currentValue) * (duration / 1000) / maxValue); //     
  String percent;
  if (maxValue == currentValue) {
   percent = "  ";
   textPaint.setTextSize(centerTextSize); //           
  } else {
   percent = (result / 60 < 10 ? "0" + result / 60 : result / 60) + ":" + (result % 60 < 10 ? "0" + result % 60 : result % 60);
//   percent = result+" ";
   textPaint.setTextSize(centerTextSize+centerTextSize/3); //           
  }
  textPaint.setTextAlign(Paint.Align.CENTER); //       ,   x     
  textPaint.setColor(centerTextColor); //       
 
  textPaint.setStrokeWidth(0); //               0,          
  Rect bounds = new Rect(); //     
  textPaint.getTextBounds(percent, 0, percent.length(), bounds); //             
  FontMetricsInt fontMetrics = textPaint.getFontMetricsInt(); //     Text      
  int baseline = center + (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom; //          canvas.drawText(percent, center, baseline, textPaint); //          
 
 }
 
 /**
  *        
  *
  * @param width
  */
 public void setCircleWidth(int width) {
  this.circleWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, width, getResources()
    .getDisplayMetrics());
  circlePaint.setStrokeWidth(circleWidth);
  //       View      UI    。invalidate()          View onDraw()  。
  invalidate();
 }
 
 /**
  *        ,      LTGRAY
  *
  * @param color
  */
 public void setFirstColor(int color) {
  this.firstColor = color;
  circlePaint.setColor(firstColor);
  //       View      UI    。invalidate()          View onDraw()  。
  invalidate();
 }
 
 /**
  *         ,     <br>
  *
  * @param color
  */
 public void setSecondColor(int color) {
  this.secondColor = color;
  circlePaint.setColor(secondColor);
  //       View      UI    。invalidate()          View onDraw()  。
  invalidate();
 }
 
 /**
  *             
  *
  * @param colors     ,   int[]
  */
 public void setColorArray(int[] colors) {
  this.colorArray = colors;
  //       View      UI    。invalidate()          View onDraw()  。
  invalidate();
 }
 
 
 /**
  *         ,           
  *
  * @param duration     
  */
 public void setDuration(int duration, OnFinishListener listener) {
   this.listener = listener;
  this.duration = duration + 1000;
  if (animator != null) {
   animator.cancel();
  } else {
   animator = ValueAnimator.ofInt(0, maxValue);
   animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
     currentValue = (int) animation.getAnimatedValue();
     //       View      UI    。invalidate()          View onDraw()  。
     invalidate();
     if (maxValue == currentValue && CountDownProgressBar.this.listener != null) {
      CountDownProgressBar.this.listener.onFinish();
     }
    }
   });
   animator.setInterpolator(new LinearInterpolator());
  }
  animator.setDuration(duration);
  animator.start();
 }
 
 public interface OnFinishListener {
  void onFinish();
 }
 
 public void setOnFinishListener(OnFinishListener listener) {
  this.listener = listener;
 }
 
 public static int px2dip(int pxValue) {
  final float scale = Resources.getSystem().getDisplayMetrics().density;
  return (int) (pxValue / scale + 0.5f);
 }
 
 
 public static float dip2px(float dipValue) {
  final float scale = Resources.getSystem().getDisplayMetrics().density;
  return (dipValue * scale + 0.5f);
 }
} 
xml 레이아웃:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 android:orientation="vertical">
<Button
 android:layout_width="match_parent"
 android:text="  "
 android:id="@+id/btn_start"
 android:layout_height="wrap_content" />
 <com.daodaojk.myapplication.view.CountDownProgressBar
  android:id="@+id/cpb_countdown"
  android:layout_width="200dp"
  android:layout_marginTop="100dp"
  android:layout_gravity="center_horizontal"
  app:countDown_centerTextSize="25dp"
  app:countDown_circleWidth="4dp"
  app:countDown_firstColor="@color/text_gray_ccc"
  app:countDown_secondColor="@color/text_blue"
  app:countDown_isShowGradient="true"
  app:countDown_centerTextColor="#2395FF"
  android:layout_height="200dp" />
</LinearLayout>
페이지 호출:

package com.daodaojk.myapplication.ui;
 
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
 
import com.daodaojk.myapplication.R;
import com.daodaojk.myapplication.view.CountDownProgressBar;
 
public class CountDownActivity extends AppCompatActivity {
 
 private CountDownProgressBar cpb_countdown;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_count_down);
  Button btn_start = findViewById(R.id.btn_start);
  cpb_countdown = (CountDownProgressBar) findViewById(R.id.cpb_countdown);
  btn_start.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    cpb_countdown.setDuration(10000, new CountDownProgressBar.OnFinishListener() {
     @Override
     public void onFinish() {
      Toast.makeText(CountDownActivity.this, "   ", Toast.LENGTH_SHORT).show();
     }
    });
   }
  });
 }
}
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기