1. 程式人生 > >自定義view-仿移動扇形進度條

自定義view-仿移動扇形進度條

            效果圖如下:

            

            一.圖形的拆解

            1,由兩個圓弧組成,一個是透明的弧,另一個則是綠色的弧

            2.文字的繪製

              1.弧形區域的計算與弧的繪製

               首先要計算出圓弧的半徑,根據半徑在計算出,弧形顯示的區域

               重新onMeasure方法 處理wrapcontent的時候,控制元件的大小

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int htightMode = MeasureSpec.getMode(heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        int defaultSize = 600;

        if (widthMode == MeasureSpec.AT_MOST && htightMode == MeasureSpec.AT_MOST )
        {
            setMeasuredDimension(defaultSize,defaultSize);
        } else if (widthMode == MeasureSpec.AT_MOST){

            setMeasuredDimension(defaultSize,height);
        }else if (htightMode == MeasureSpec.AT_MOST){

            setMeasuredDimension(width,defaultSize);
        }else {
            setMeasuredDimension(width,height);
        }
    }
             計算出圓的半徑,這裡使用控制元件大小的一半在減去弧形的寬度,在減100
 radious = (int) ((Math.min(getWidth(),getHeight()) /2 -  paint.getStrokeWidth()) - 100);
             

              算出弧形所在的區域

 rectF.left = getWidth() / 2 - radious;
        rectF.top = getHeight() / 2 - radious;
        rectF.right = getWidth() / 2 + radious;
        rectF.bottom = getHeight() / 2 + radious;
            

           2.繪製文字

          首先計算出中間文字的位置,這裡獲取控制元件寬度的一半減去文字大小的一半

 paint.setColor(Color.WHITE);
        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeWidth(1);
        paint.setTextSize(40);
        canvas.drawText(total,getWidth() / 2 - paint.measureText(total) /2,getHeight() / 2,paint);
        paint.setTextSize(30);
        canvas.drawText(title,getWidth() / 2 - paint.measureText(total) /2,getHeight() / 2 - paint.measureText(total) / 2,paint);
       這裡主要是底部文字高度計算,這裡的計算方法與上一節計算弧度的座標的效果是一樣的,具體可以參考上一篇的部落格
  mPath.addArc(rectF,180,180);
        mMeasure.setPath(mPath,false);
        mMeasure.getPosTan(mMeasure.getLength(), pos, tan);
canvas.drawText(alerady,getWidth() / 2 - paint.measureText(alerady) / 2,pos[1] + paint.measureText(alerady) / 4,paint);

二。這裡貼上完整程式碼
package smartworld.com.hencoder;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

/**
 * Created by ${charles}     on 2017/7/13.
 *
 * @desc ${TODO}
 */

public class ArcProgress extends View
{
    private Paint paint;
    private int radious;
    private String total = "2371.00M";
    private String title = "可用流量";
    private String alerady = "已用流量27.99M";
    private Path mPath;
    private float[] pos;
    private float[] tan;
    private PathMeasure mMeasure;

    private ValueAnimator valueAnimator;
    private float mAnimatorValue;
    private float percent = 50;

    private int sweepAngle;
    public ArcProgress(Context context, AttributeSet attrs)
    {
        super(context, attrs);

        paint = new Paint();
        paint.setAntiAlias(true);

        mPath = new Path();
        mMeasure = new PathMeasure();
        pos = new float[2];
        tan = new float[2];

        valueAnimator = ValueAnimator.ofFloat(0,1);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
        {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator)
            {
                mAnimatorValue = (float) valueAnimator.getAnimatedValue();

                float degree  = percent / 100 * 180;

                Log.e("valuAnimator",mAnimatorValue * degree + "");
                sweepAngle = (int) (mAnimatorValue * degree);

                invalidate();
            }
        });
        valueAnimator.setDuration(3000);
//        valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        valueAnimator.start();

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int htightMode = MeasureSpec.getMode(heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        int defaultSize = 600;

        if (widthMode == MeasureSpec.AT_MOST && htightMode == MeasureSpec.AT_MOST )
        {
            setMeasuredDimension(defaultSize,defaultSize);
        } else if (widthMode == MeasureSpec.AT_MOST){

            setMeasuredDimension(defaultSize,height);
        }else if (htightMode == MeasureSpec.AT_MOST){

            setMeasuredDimension(width,defaultSize);
        }else {
            setMeasuredDimension(width,height);
        }
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);

        RectF rectF = new RectF();
        radious = (int) ((Math.min(getWidth(),getHeight()) /2 -  paint.getStrokeWidth()) - 100);
        rectF.left = getWidth() / 2 - radious;
        rectF.top = getHeight() / 2 - radious;
        rectF.right = getWidth() / 2 + radious;
        rectF.bottom = getHeight() / 2 + radious;

        paint.setColor(Color.parseColor("#44000000"));
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(10);
        canvas.drawArc(rectF,180,180,false,paint);

        mPath.addArc(rectF,180,180);
        mMeasure.setPath(mPath,false);
        mMeasure.getPosTan(mMeasure.getLength(), pos, tan);
        //canvas.drawCircle(pos[0], pos[1], 10, paint);

        paint.setColor(Color.GREEN);
        canvas.drawArc(rectF,180,sweepAngle,false,paint);

        paint.setColor(Color.WHITE);
        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeWidth(1);
        paint.setTextSize(40);
        canvas.drawText(total,getWidth() / 2 - paint.measureText(total) /2,getHeight() / 2,paint);
        paint.setTextSize(30);
        canvas.drawText(title,getWidth() / 2 - paint.measureText(total) /2,getHeight() / 2 - paint.measureText(total) / 2,paint);

        paint.setTextSize(35);
        canvas.drawText(alerady,getWidth() / 2 - paint.measureText(alerady) / 2,pos[1] + paint.measureText(alerady) / 4,paint);
    }
}