酷炫进度条 自定义SeekBar

原作者地址:http://blog.csdn.net/tl792814781/article/details/52289864


前些天一同学给了我一个ui图,是这样子的:

UI图

需求:

1、看了ui图可以知道这类似android自带的seekbar控件,
2、一个水平进度条和一个圆形进度条;
3、圆形进度条显示环形刻度和当前进度值;
4、并且圆形进度可滑动操作;

最终实现效果:


效果图

废话不多说上代码:

水平的进度条: HorizonalProgress.class
  1. package com.totcy.magicprogress;  
  2.   
  3. import android.animation.ObjectAnimator;  
  4. import android.content.Context;  
  5. import android.graphics.Canvas;  
  6. import android.graphics.Color;  
  7. import android.graphics.Paint;  
  8. import android.graphics.RectF;  
  9. import android.util.AttributeSet;  
  10. import android.view.View;  
  11. import android.view.animation.DecelerateInterpolator;  
  12.   
  13. /** 
  14.  * Description 酷炫水平进度条 
  15.  * Author: tu 
  16.  * Date: 2016-08-22 
  17.  * Time: 14:59 
  18.  */  
  19. public class HorizonalProgress extends View {  
  20.     private int viewWidth;//view的宽度  
  21.     private int viewHigth;//view的高度  
  22.     private Paint mPaint;//画笔  212 62 96  
  23.     private int colorSecondProgress = Color.argb(255,229,237,245);//背景圆颜色,进度条背景色  
  24.     private int colorProgress = Color.argb(255,19,146,255);//背景圆颜色,一级进度条颜色  
  25.     private int progressHeight = 30;//进度条的高度  
  26.     private RectF rectF = new RectF();  
  27.     private int curProgress = 0//必须小于等于100 大于0  
  28.     private int oldProgress = 0;  
  29.       
  30.     public void setColorSecondProgress(int colorSecondProgress) {  
  31.         this.colorSecondProgress = colorSecondProgress;  
  32.     }  
  33.     public void setColorProgress(int colorProgress) {  
  34.         this.colorProgress = colorProgress;  
  35.     }  
  36.     public void setProgressHeight(int progressHeight) {  
  37.         this.progressHeight = progressHeight;  
  38.     }  
  39.     public void setCurProgress(int curProgress) {  
  40.         this.curProgress = curProgress;  
  41.         invalidate();  
  42.     }  
  43.     public HorizonalProgress(Context context) {  
  44.         this(context,null);  
  45.     }  
  46.   
  47.     public HorizonalProgress(Context context, AttributeSet attrs) {  
  48.         this(context, attrs,0);  
  49.     }  
  50.   
  51.     public HorizonalProgress(Context context, AttributeSet attrs, int defStyleAttr) {  
  52.         super(context, attrs, defStyleAttr);  
  53.         init();  
  54.     }  
  55.     private void init(){  
  56.         //初始化坐标画笔  
  57.         mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//  
  58.         mPaint.setColor(colorSecondProgress);  
  59.         mPaint.setAntiAlias(true);  
  60.         mPaint.setStyle(Paint.Style.STROKE);//空心  
  61.         curProgress = 0;  
  62.     }  
  63.     @Override  
  64.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  65.         int widthSize = MeasureSpec.getSize(widthMeasureSpec);  
  66.         int widthMode = MeasureSpec.getMode(widthMeasureSpec);  
  67.         int heightMode = MeasureSpec.getMode(heightMeasureSpec);  
  68.         int heightSize = MeasureSpec.getSize(heightMeasureSpec);  
  69.         int height;  
  70.         int width;  
  71.   
  72.         //宽度测量  
  73.         if (widthMode == MeasureSpec.EXACTLY) {  
  74.             width = widthSize;  
  75.         } else {  
  76.             width = getMeasuredWidth();  
  77.         }  
  78.         viewWidth = width;  
  79.         //高度测量  
  80.         if (heightMode == MeasureSpec.EXACTLY) {  
  81.             height = heightSize;  
  82.         } else {  
  83.             height = getMeasuredHeight();  
  84.         }  
  85.         //进度条的高度根据  
  86.         viewHigth = progressHeight;  
  87.   
  88.         setMeasuredDimension(width, viewHigth);  
  89.     }  
  90.   
  91.     /** 
  92.      * 绘制进度 
  93.      * @param canvas 
  94.      */  
  95.     private  void drawProgress(Canvas canvas){  
  96.         rectF.left = 0;  
  97.         rectF.right = viewWidth;  
  98.         rectF.top = 0;  
  99.         rectF.bottom = viewHigth;  
  100.         mPaint.setStyle(Paint.Style.FILL);  
  101.         mPaint.setColor(colorSecondProgress);  
  102.         //灰色背景  
  103.         canvas.drawRoundRect(rectF,viewHigth/2,viewHigth/2,mPaint);  
  104.   
  105.         //进度  
  106.         mPaint.setColor(colorProgress);  
  107.         rectF.right = curProgress * viewWidth / 100;  
  108.         canvas.drawRoundRect(rectF,viewHigth/2,viewHigth/2,mPaint);  
  109.   
  110.     }  
  111.     @Override  
  112.     protected void onDraw(Canvas canvas) {  
  113.         super.onDraw(canvas);  
  114.         drawProgress(canvas);  
  115.     }  
  116.     public void setProgress(int progress){  
  117.         if (progress < 0 || progress > 100)  
  118.             return;  
  119.         ObjectAnimator o = ObjectAnimator.ofInt(this"curProgress", oldProgress, progress);  
  120.         o.setDuration(1000);  
  121.         o.setInterpolator(new DecelerateInterpolator());  
  122.         o.start();  
  123.         oldProgress = progress;  
  124.     }  
  125. }  

圆形进度条  CircleProgress.class
  1. package com.totcy.magicprogress;  
  2.   
  3. import android.animation.ObjectAnimator;  
  4. import android.content.Context;  
  5. import android.graphics.Canvas;  
  6. import android.graphics.Color;  
  7. import android.graphics.Paint;  
  8. import android.graphics.RectF;  
  9. import android.util.AttributeSet;  
  10. import android.view.View;  
  11. import android.view.animation.DecelerateInterpolator;  
  12.   
  13. /** 
  14.  * Description 圆形装逼进度条 
  15.  * Author: tu 
  16.  * Date: 2016-08-19 
  17.  * Time: 14:33 
  18.  */  
  19. public class CircleProgress extends View{  
  20.   
  21.     private float textSize = getResources().getDimension(R.dimen.text_size_14);  
  22.     private float dotX, dotY;//圆点xy  
  23.     private int viewWidth;//view的宽度  
  24.     private int viewHigth;//view的高度  
  25.     private Paint mPaint,mPaintArc;//画笔  212 62 96  
  26.     private int colorBg = Color.argb(255,54,68,76);//背景圆颜色  
  27.     private int colorWhite = Color.argb(255,255,255,255);//文字颜色  
  28.     private int colorBlack = Color.argb(255,34,49,59);//第二刻度颜色  
  29.     private int colorBlue = Color.argb(255,94,248,249);//刻度颜色  
  30.     private int pandding = 10;  
  31.     private RectF rectF;  
  32.     private float radius = 10;//半径  
  33.     private float scaleLineLenth = 3;//刻度线长  
  34.     private int scaleAngle = 10;//刻度间隔  
  35.     private int scaleWidth = 5;//刻度宽度  
  36.     private int curProgress = 0;//0 ~ 100进度 当前进度  
  37.     private int oldProgress = 0;  
  38.   
  39.     public void setColorBlue(int colorBlue) {  
  40.         this.colorBlue = colorBlue;  
  41.     }  
  42.   
  43.     public void setTextSize(float textSize) {  
  44.         this.textSize = textSize;  
  45.     }  
  46.   
  47.     public int getCurProgress() {  
  48.         return curProgress;  
  49.     }  
  50.   
  51.     public void setCurProgress(int curProgress) {  
  52.         this.curProgress = curProgress;  
  53.         invalidate();  
  54.     }  
  55.   
  56.     public CircleProgress(Context context) {  
  57.         this(context,null);  
  58.     }  
  59.   
  60.     public CircleProgress(Context context, AttributeSet attrs) {  
  61.         this(context, attrs,0);  
  62.     }  
  63.   
  64.     public CircleProgress(Context context, AttributeSet attrs, int defStyleAttr) {  
  65.         super(context, attrs, defStyleAttr);  
  66.         init(context);  
  67.     }  
  68.   
  69.     /** 
  70.      * 初始化画笔 
  71.      */  
  72.     private void init(Context context) {  
  73.   
  74.         //初始化坐标画笔  
  75.         mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//  
  76.         mPaintArc = new Paint(Paint.ANTI_ALIAS_FLAG);//  
  77.         mPaint.setColor(colorWhite);  
  78.         mPaintArc.setColor(colorBg);  
  79.         mPaint.setAntiAlias(true);  
  80.         mPaintArc.setAntiAlias(true);  
  81.         mPaint.setTextSize(15);  
  82.         mPaint.setStyle(Paint.Style.STROKE);//空心  
  83.         //当前进度  
  84.   
  85.     }  
  86.     @Override  
  87.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  88.         int widthSize = MeasureSpec.getSize(widthMeasureSpec);  
  89.         int widthMode = MeasureSpec.getMode(widthMeasureSpec);  
  90.         int heightMode = MeasureSpec.getMode(heightMeasureSpec);  
  91.         int heightSize = MeasureSpec.getSize(heightMeasureSpec);  
  92.         int height;  
  93.         int width;  
  94.   
  95.         //宽度测量  
  96.         if (widthMode == MeasureSpec.EXACTLY) {  
  97.             width = widthSize;  
  98.         } else {  
  99.             width = getMeasuredWidth();  
  100.         }  
  101.         dotX = width / 2;  
  102.         viewWidth = width;  
  103.         //高度测量  
  104.         if (heightMode == MeasureSpec.EXACTLY) {  
  105.             height = heightSize;  
  106.         } else {  
  107.             height = getMeasuredHeight();  
  108.         }  
  109.         viewHigth = height;  
  110.         dotY = height / 2;  
  111.         radius = dotX-(getPaddingLeft() + getPaddingRight())/2;  
  112.         scaleLineLenth = radius/3;  
  113.         rectF = new RectF(dotX - radius, dotY - radius, dotX + radius, dotY + radius);  
  114.         setMeasuredDimension(width, height);  
  115.     }  
  116.     private void drawProgress(Canvas canvas){  
  117.         if(mPaintArc == null){  
  118.             return;  
  119.         }  
  120.         //圆  
  121.         mPaintArc.setStyle(Paint.Style.FILL);  
  122.         canvas.drawCircle(dotX, dotY, radius, mPaintArc);  
  123.         //中心进度值  
  124.         mPaint.setStyle(Paint.Style.FILL_AND_STROKE);//实心  
  125.         mPaint.setTextAlign(Paint.Align.CENTER);  
  126.         mPaint.setStrokeWidth(1);  
  127.         mPaint.setTextSize(textSize);  
  128.         mPaint.setColor(colorWhite);  
  129.         canvas.drawText(curProgress + "%",dotX,  
  130.                 dotY+getResources().getDimension(R.dimen.text_size_14)/2  
  131.                 ,mPaint);  
  132.         //黑色刻度  12点钟方向为起始点(-90°),正时针方法绘制  
  133.         for (int angle = -90; angle <= 270; angle += scaleAngle){  
  134.             float xY[] = caculCoordinate(angle);  
  135.             if(xY != null) {  
  136.                 mPaint.setStrokeWidth(scaleWidth);  
  137.                 mPaint.setColor(colorBlack);  
  138.                 canvas.drawLine(xY[0], xY[1],xY[2],xY[3], mPaint);  
  139.             }  
  140.         }  
  141.         //进度算法  
  142.         //360 除与 scaleAngle(进度间隔10) = 36; 再拿进度总数100换算当前进度  
  143.         //算出当前进度占几个刻度  
  144.         int curProgressCount = curProgress * (360/scaleAngle) /100;  
  145.         int angleStart = -90;  
  146.         for (int count = 0; count < curProgressCount;count ++){  
  147.             float xY[] = caculCoordinate(angleStart);  
  148.             if(xY != null) {  
  149.                 mPaint.setStrokeWidth(scaleWidth);  
  150.                 mPaint.setColor(colorBlue);  
  151.                 canvas.drawLine(xY[0], xY[1],xY[2],xY[3], mPaint);  
  152.             }  
  153.             angleStart += scaleAngle;  
  154.         }  
  155.   
  156.     }  
  157.   
  158.     /** 
  159.      * 根据圆心角 计算圆周上的坐标 
  160.      * @param angle 
  161.      * @return xY[0] startX; xY[1] startY; xY[2] endX; xY[3] endY; 
  162.      */  
  163.     private float[] caculCoordinate(int angle){  
  164.         //angle >180     angle = angle -180  
  165.         float xY[] = new float[4];  
  166.         //角度处理  
  167.         int tempAngle = Math.abs(angle);  
  168.         float tempScaleLineLenth = scaleLineLenth;  
  169.   
  170.          if(270 > tempAngle && tempAngle >= 180) {  
  171.             tempAngle = tempAngle - 180;  
  172.             xY[0] = dotX - getCoordinateX(tempAngle,radius);  
  173.             xY[1] = dotY - getCoordinateY(tempAngle,radius);  
  174.   
  175.             xY[2] = xY[0] + getCoordinateX(tempAngle,tempScaleLineLenth);  
  176.             xY[3] = xY[1] + getCoordinateY(tempAngle,tempScaleLineLenth);  
  177.         }else if(180 > tempAngle && tempAngle > 90){  
  178.             tempAngle = 180 - tempAngle;  
  179.             xY[0] = dotX - getCoordinateX(tempAngle,radius);  
  180.             xY[1] = dotY + getCoordinateY(tempAngle,radius);  
  181.   
  182.             xY[2] = xY[0] + getCoordinateX(tempAngle,tempScaleLineLenth);  
  183.             xY[3] = xY[1] - getCoordinateY(tempAngle,tempScaleLineLenth);  
  184.         }else if(90 >= tempAngle && tempAngle >= 0){  
  185.             xY[0] = dotX + getCoordinateX(tempAngle,radius);  
  186.             xY[1] = angle < 0 ? dotY - getCoordinateY(tempAngle,radius) : dotY + getCoordinateY(tempAngle,radius);  
  187.   
  188.             xY[2] = xY[0] - getCoordinateX(tempAngle,tempScaleLineLenth);  
  189.             xY[3] = angle < 0 ? xY[1] + getCoordinateY(tempAngle,tempScaleLineLenth) : xY[1] - getCoordinateY(tempAngle,tempScaleLineLenth);  
  190.         }  
  191.   
  192.         return xY;  
  193.     }  
  194.   
  195.   
  196.     /** 
  197.      * 获取圆周上y值相对值 
  198.      * @param tempAngle 
  199.      * @param radius 算开始坐标是传半径,算结束坐标时传刻度线的长度 
  200.      * @return 
  201.      */  
  202.     private float getCoordinateY(int tempAngle,float radius){  
  203.   
  204.         //利用正弦函数算出y坐标  
  205.         return (float) (Math.sin(tempAngle*Math.PI/180)*(radius - 15)); //10 是离圆弧的距离  
  206.     }  
  207.     /** 
  208.      * 获取圆周上X值相对值 
  209.      * @param tempAngle 
  210.      * @return 
  211.      */  
  212.     private float getCoordinateX(int tempAngle,float radius){  
  213.   
  214.         //利用余弦函数算出y坐标  
  215.         return (float) (Math.cos(tempAngle*Math.PI/180)*(radius - 15));  
  216.     }  
  217.     @Override  
  218.     protected void onDraw(Canvas canvas) {  
  219.         super.onDraw(canvas);  
  220.         drawProgress(canvas);  
  221.     }  
  222.     public void setProgress(int progress){  
  223.         if (progress < 0 || progress > 100)  
  224.             return;  
  225.         ObjectAnimator o = ObjectAnimator.ofInt(this"curProgress", oldProgress, progress);  
  226.         o.setDuration(1000);  
  227.         o.setInterpolator(new DecelerateInterpolator());  
  228.         o.start();  
  229.         oldProgress = progress;  
  230.     }  
  231. }  

组合起来使用: MyProgress.class
  1. package com.totcy.magicprogress;  
  2.   
  3. import android.R.dimen;  
  4. import android.content.Context;  
  5. import android.content.res.TypedArray;  
  6. import android.graphics.Color;  
  7. import android.util.AttributeSet;  
  8. import android.util.Log;  
  9. import android.view.MotionEvent;  
  10. import android.view.View;  
  11. import android.view.ViewConfiguration;  
  12. import android.view.ViewGroup;  
  13. import android.view.ViewTreeObserver;  
  14. import android.view.ViewTreeObserver.OnGlobalLayoutListener;  
  15. import android.widget.FrameLayout;  
  16. import android.widget.RelativeLayout;  
  17.   
  18. /** 
  19.  * Description 组合装逼进度 
  20.  * Author: tu 
  21.  * Date: 2016-08-22 
  22.  * Time: 15:36 
  23.  */  
  24. public class MyProgress extends RelativeLayout {  
  25.       
  26.     private Context context;  
  27.     private float textProgressSize;//圆形进度条中间文字  
  28.     private float horizonalProgressHeight;//横条高度  
  29.     private float circleProgressRadus;//圆形半径  
  30.     private int colorProgress;//进度条颜色,圆盘刻度颜色  
  31.     private int colorSecondProgress;//进度条背景颜色  
  32.       
  33.     private boolean flagPaint = true;//绘图标志  
  34.     int newProgress;  
  35.     private CircleProgress mCircleProgress;  
  36.     private HorizonalProgress mHorizonalProgress;  
  37.     //private int touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();//最小滑动阀值  
  38.   
  39.     public MyProgress(Context context) {  
  40.         this(context,null);  
  41.     }  
  42.   
  43.     public MyProgress(Context context, AttributeSet attrs) {  
  44.         this(context, attrs,0);  
  45.     }  
  46.   
  47.     public MyProgress(Context context, AttributeSet attrs, int defStyleAttr) {  
  48.         super(context, attrs, defStyleAttr);  
  49.         this.context = context;  
  50.         init(attrs);  
  51.         ViewTreeObserver vto = getViewTreeObserver();  
  52.         vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {  
  53.             @Override  
  54.             public void onGlobalLayout() {  
  55.                 if(flagPaint){  
  56.                     flagPaint = false;  
  57.                     initHorizonalProgress();  
  58.                 }else{  
  59.                       
  60.                 }  
  61.             }  
  62.       });  
  63.     }  
  64.   
  65.     private void init(AttributeSet attrs){  
  66.         flagPaint = true;  
  67.         //获取自定义xml属性  
  68.         TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.myMagicProgress);  
  69.         int n = typedArray.getIndexCount();  
  70.         for (int i = 0; i < n; i++) {  
  71.             int attr = typedArray.getIndex(i);  
  72.             switch (attr) {  
  73.             case R.styleable.myMagicProgress_circleProgressRadus:  
  74. //              Log.e("tag", "typedArray.getDimension(attr, 0)="+typedArray.getDimension(attr, 0)+",typedArray.getDimension(i, 0)="+typedArray.getDimension(i, 0));  
  75.                 circleProgressRadus = typedArray.getDimension(attr, 0);  
  76.                 break;  
  77.             case R.styleable.myMagicProgress_horizonalProgressHeight:  
  78.                 horizonalProgressHeight = typedArray.getDimension(attr, 0);  
  79.                             break;  
  80.             case R.styleable.myMagicProgress_textProgressSize:  
  81.                 textProgressSize = typedArray.getDimension(attr, 0);  
  82.                 break;  
  83.             case R.styleable.myMagicProgress_colorProgress:  
  84.                 colorProgress = typedArray.getColor(attr, Color.GRAY);  
  85.                 break;  
  86.             case R.styleable.myMagicProgress_colorSecondProgress:  
  87.                 colorSecondProgress = typedArray.getColor(attr, Color.GRAY);  
  88.                 break;  
  89.             default:  
  90.                 break;  
  91.             }  
  92.         }  
  93.           
  94.         //横向进度条稍后设置参数,需要圆形进度条绘图完成,根据宽度绘制左右边距  
  95.         mHorizonalProgress = new HorizonalProgress(getContext());  
  96.         mHorizonalProgress.setProgressHeight((int) horizonalProgressHeight);  
  97.         mHorizonalProgress.setColorSecondProgress(colorSecondProgress);  
  98.         mHorizonalProgress.setColorProgress(colorProgress);  
  99.           
  100.         int radus = (int) circleProgressRadus;  
  101.         mCircleProgress = new CircleProgress(getContext());  
  102.         mCircleProgress.setTextSize(textProgressSize);  
  103.         mCircleProgress.setColorBlue(colorProgress);  
  104.         LayoutParams cp_lp = new RelativeLayout.LayoutParams(radus,radus);  
  105.         cp_lp.addRule(RelativeLayout.CENTER_VERTICAL);  
  106.         mCircleProgress.setLayoutParams(cp_lp);  
  107.   
  108.         addView(mHorizonalProgress);  
  109.         addView(mCircleProgress);  
  110.   
  111.         initView();  
  112.           
  113.     }  
  114.     private float mDownX;  
  115.     private void initView(){  
  116.         mCircleProgress.setOnTouchListener(new OnTouchListener() {  
  117.             @Override  
  118.             public boolean onTouch(View view, MotionEvent event) {  
  119.                 switch (event.getAction()) {  
  120.                     case MotionEvent.ACTION_DOWN:  
  121.                         mDownX = event.getX();  
  122. //                      Log.d("Tag",event.getX() + ":" + event.getRawX());  
  123.                         break;  
  124.                     case MotionEvent.ACTION_MOVE:  
  125. //                      Log.d("Tag",event.getX() + ":" + event.getRawX());  
  126.                         float disX = event.getX() - mDownX;  
  127.                         float llX = mCircleProgress.getX() + disX;  
  128. //                      Log.e("tag", "disX="+disX+",llX="+llX+",mHorizonalProgress.getWidth()="+mHorizonalProgress.getWidth());  
  129.                         //校正边界,反正滑块划出  
  130.                         llX = checkoundary(llX);  
  131.                         mCircleProgress.setX(llX);  
  132.                         //计算进度条百分比  
  133.                         newProgress = getProgress(llX);  
  134.                         //更新进度条  
  135.                         updateProgress(newProgress);  
  136.                         break;  
  137.                     case MotionEvent.ACTION_UP:  
  138.                         break;  
  139.                     default:  
  140.                         break;  
  141.                 }  
  142.                 return true;  
  143.             }  
  144.         });  
  145.     }  
  146.     /** 
  147.      * 绘制横向进度条 
  148.      */  
  149.     public void initHorizonalProgress(){  
  150. //      Log.e("tag", "mCircleProgress.getWidth()="+mCircleProgress.getWidth());  
  151.         //设置边距,左右空出滑块半径的距离  
  152.         LayoutParams hp_lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,(int) horizonalProgressHeight);  
  153.         hp_lp.leftMargin = mCircleProgress.getWidth()/2;  
  154.         hp_lp.rightMargin = mCircleProgress.getWidth()/2;  
  155.         hp_lp.addRule(RelativeLayout.CENTER_VERTICAL);  
  156.         mHorizonalProgress.setLayoutParams(hp_lp);  
  157.     }  
  158.       
  159.     /** 
  160.      * 校正边界 
  161.      * @return 
  162.      */  
  163.     public float checkoundary(float llX){  
  164.         if(llX<0){  
  165.             llX = 0f;  
  166.         }else if(llX>mHorizonalProgress.getWidth()){  
  167.             llX = mHorizonalProgress.getWidth();  
  168.         }  
  169.         return llX;  
  170.     }  
  171.       
  172.     /** 
  173.      * 换算百分比 
  174.      */  
  175.     public int getProgress(float llX){  
  176.         return (int) ((llX/mHorizonalProgress.getWidth())*100);  
  177.     }  
  178.       
  179.     /** 
  180.      * 更新进度 
  181.      * @param newProgress 
  182.      */  
  183.     public void updateProgress(int newProgress){  
  184. //      Log.e("tag", "newProgress="+newProgress);  
  185.         mCircleProgress.setProgress(newProgress);  
  186.         mHorizonalProgress.setProgress(newProgress);  
  187.     }  
  188. }  


总结:


整个控件的难点在于CircleProgress上环形刻度的绘制,圆周上取坐标的算法 ,具体算法代码中都有注释,下面结合这张草图分析可以更加透彻:
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值