Android View 提升 十 之 自定义View

Android View 提升 十 之 自定义View

1. 圆盘 效果:

在这里插入图片描述

public class MyProgressView extends View {

    private RectF mWheelRect = new RectF();

    private RectF mSmallRect = new RectF();
    private Paint mSmallPaint;
    private float mSmallStrokeWidth;

    private Paint mDefaultWheelPaint;
    private Paint mFinishWheelPaint;
    private Paint mCenterWheelPaint;
    private Paint mTitlePaint, mStepPaint, mTargetPaint;
    private float mCircleStrokeWidth;
    private float mSweepAnglePer;
    private float mPercent;
    private int mStepNum, mCurrStepNum;
    private BarAnimation mAnim;
    private int mMaxStepNum;
    private float mTitleY, mStepY, mTargetY;
    private DecimalFormat mDecimalFormat = new DecimalFormat("#.0");
    private static String PERCENT;

    public MyProgressView(Context context){
        super(context);
        init(null,0);
    }

    public MyProgressView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(attrs,0);
    }

    public MyProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs,defStyleAttr);
    }

    private void init(AttributeSet attrs, int defStyle){
        mFinishWheelPaint = new Paint();
        mFinishWheelPaint.setColor(Color.rgb(100,113,205));
        mFinishWheelPaint.setStyle(Paint.Style.STROKE);
        mFinishWheelPaint.setStrokeCap(Paint.Cap.ROUND);
        mFinishWheelPaint.setAntiAlias(true);

        mCenterWheelPaint = new Paint();
        mCenterWheelPaint.setColor(Color.rgb(0, 0, 243));
        mCenterWheelPaint.setStyle(Paint.Style.STROKE);
        mCenterWheelPaint.setStrokeCap(Paint.Cap.ROUND);
        mCenterWheelPaint.setAntiAlias(true);

        mDefaultWheelPaint = new Paint();
        mDefaultWheelPaint.setColor(Color.rgb(255, 0, 0));
        mDefaultWheelPaint.setStyle(Paint.Style.STROKE);
        mDefaultWheelPaint.setStrokeCap(Paint.Cap.ROUND);
        mDefaultWheelPaint.setAntiAlias(true);

        mTitlePaint = new Paint();
        mTitlePaint.setAntiAlias(true);
        mTitlePaint.setColor(Color.WHITE);

        mStepPaint = new Paint();
        mStepPaint.setAntiAlias(true);
        mStepPaint.setColor(Color.WHITE);

        mTargetPaint = new Paint();
        mTargetPaint.setAntiAlias(true);
        mTargetPaint.setColor(Color.WHITE);
        mAnim = new BarAnimation();

        mSmallPaint = new Paint();
        mSmallPaint.setAntiAlias(true);
        mSmallPaint.setStyle(Paint.Style.STROKE);
        mSmallPaint.setStrokeCap(Paint.Cap.SQUARE);
        mSmallPaint.setColor(Color.CYAN);

    }


    private double startX;
    private double startY;
    private float stopX;
    private float stopY;
    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawArc(mWheelRect, 0, 179,false, mDefaultWheelPaint);
        canvas.drawArc(mWheelRect, 180, 180, false, mCenterWheelPaint);
        canvas.drawArc(mWheelRect, 0, mSweepAnglePer, false, mFinishWheelPaint);
        canvas.drawLine((float) startX, (float) startY,stopX,stopY,mSmallPaint);
        canvas.drawArc(mSmallRect, 0, 359,false,mSmallPaint);

//        canvas.drawText(mCurrStepNum + "",
//                mWheelRect.centerX() - (mStepPaint.measureText(String.valueOf(mCurrStepNum)) / 2), mStepY,
//                mStepPaint);
//        String description = "";
//        float percent = mPercent;
//        if(percent > 0.5){
//            description ="严重污染";
//        }else if(percent>0.2){
//            description ="中等污染";
//        }else{
//            description ="普通污染";
//        }
//
//        canvas.drawText(description , mWheelRect.centerX() -
//                (mTargetPaint.measureText(description) / 2), mTargetY, mTargetPaint);
//        SweepGradient sweepGradient = new SweepGradient(mWheelRect.centerX(), mWheelRect.centerY(),
//                new int[]{Color.rgb(127, 127, 127),Color.rgb(127, 127, 127),
//                        Color.rgb(127, 127, 127),Color.rgb(127, 127, 127),
//                        Color.rgb(127, 127, 127),Color.rgb(127, 127, 127)}, null);
//        mFinishWheelPaint.setShader(sweepGradient);

    }

    private float mBigRadius;
    private float mSmallRadius;

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int height = getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec);
        int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        int min = Math.min(width, height);// 获取View最短边的长度
        setMeasuredDimension(min, min);// 强制改View为以最短边为长度的正方形
        mCircleStrokeWidth = getTextScale(15, min);// 圆弧的宽度
        float pressExtraStrokeWidth = getTextScale(10, min);// 圆弧离矩形的距离
        mWheelRect.set(mCircleStrokeWidth + pressExtraStrokeWidth, mCircleStrokeWidth + pressExtraStrokeWidth,
                min - mCircleStrokeWidth - pressExtraStrokeWidth, min - mCircleStrokeWidth - pressExtraStrokeWidth);// 设置矩形
        mSmallStrokeWidth = getTextScale(15,min);
        float mSpace = getTextScale(150,min);
        float mSmallExtraStrokeWidth = mSpace+mCircleStrokeWidth+pressExtraStrokeWidth;
        mSmallRect.set(mSmallExtraStrokeWidth+mSmallStrokeWidth,
                    mSmallExtraStrokeWidth+mSmallStrokeWidth,
                min-mSmallStrokeWidth-mSmallExtraStrokeWidth,
                min-mSmallStrokeWidth-mSmallExtraStrokeWidth);
        mSmallPaint.setStrokeWidth(mSmallStrokeWidth);
        mBigRadius = mWheelRect.centerX()-mCircleStrokeWidth-pressExtraStrokeWidth-mCircleStrokeWidth;
        mSmallRadius = mSmallRect.centerX()-mSmallExtraStrokeWidth-mSmallStrokeWidth;

        startX = mWheelRect.centerX()+mBigRadius;
        startY = mWheelRect.centerY();
        stopX = mSmallRect.centerX()+mSmallRadius;
        stopY = mSmallRect.centerY();


        mTitlePaint.setTextSize(getTextScale(60, min));
        mStepPaint.setTextSize(getTextScale(120, min));
        mTargetPaint.setTextSize(getTextScale(40, min));
        mTitleY = getTextScale(170, min);
        mStepY = getTextScale(300, min);
        mTargetY = getTextScale(380, min);

        mFinishWheelPaint.setStrokeWidth(mCircleStrokeWidth);
        mCenterWheelPaint.setStrokeWidth(mCircleStrokeWidth);
        mDefaultWheelPaint.setStrokeWidth(mCircleStrokeWidth - getTextScale(2, min));
        mDefaultWheelPaint.setShadowLayer(getTextScale(10, min), 0, 0, Color.rgb(127, 127, 127));// 设置阴影

    }
    /**
     * 进度条动画
     *
     * @author Administrator
     */
    public class BarAnimation extends Animation {

        /**
         * 每次系统调用这个方法时, 改变mSweepAnglePer,mPercent,stepnumbernow的值,
         * 然后调用postInvalidate()不停的绘制view。
         */
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
//			if (interpolatedTime < 1.0f) {
//				mPercent = Float.parseFloat(mDecimalFormat.format(interpolatedTime * mStepNum * 100f / mMaxStepNum));// 将浮点值四舍五入保留一位小数
//				mSweepAnglePer = interpolatedTime * mStepNum * 360 / mMaxStepNum;
//				mCurrStepNum = (int) (interpolatedTime * mStepNum);
//			} else {
//            mPercent = Float.parseFloat(mDecimalFormat.format(mStepNum * 100f / mMaxStepNum));// 将浮点值四舍五入保留一位小数
//            if (mPercent > 100.0f) {
//                mPercent = 100.0f;
//            }
//            PERCENT = String.valueOf(mPercent);
//            mSweepAnglePer = mStepNum * 360 / mMaxStepNum;
//            mCurrStepNum = mStepNum;
//			}
            mPercent = Float.parseFloat(mDecimalFormat.format(interpolatedTime * mStepNum * 100f / mMaxStepNum));// 将浮点值四舍五入保留一位小数
            mSweepAnglePer = interpolatedTime * mStepNum * 360 / mMaxStepNum;
            mCurrStepNum = (int) (interpolatedTime * mStepNum);
            startX = mWheelRect.centerX()+(mBigRadius*(Math.cos(mSweepAnglePer/180*Math.PI)));
            startY = mWheelRect.centerY()+(mBigRadius*(Math.sin(mSweepAnglePer/180*Math.PI)));
            stopX = (float) (mSmallRect.centerX()+(mSmallRadius*(Math.cos(mSweepAnglePer/180*Math.PI))));
            stopY = (float) (mSmallRect.centerY()+(mSmallRadius*(Math.sin(mSweepAnglePer/180*Math.PI))));

            requestLayout();
        }
    }

    public float getPercent() {
        return mPercent;
    }

    /**
     * 根据控件的大小改变绝对位置的比例
     *
     * @param n
     * @param m
     * @return
     */
    public float getTextScale(float n, float m) {
        return n / 500 * m;
    }

    /**
     * 更新步数和设置一圈动画时间
     *
     * @param stepCount
     * @param time
     */
    public void update(int stepCount, int time) {
        this.mStepNum = stepCount;
        mAnim.setDuration(time);
        setAnimationTime(time);
        this.startAnimation(mAnim);
    }

    /**
     * @param stepNum
     */
    public void setMaxStepNum(int stepNum) {
        mMaxStepNum = stepNum;

    }

    public void setColor(int color) {
        mFinishWheelPaint.setColor(color);
        mStepPaint.setColor(color);
    }

    /**
     * 设置动画时间
     *
     * @param time
     */
    public void setAnimationTime(int time) {
        mAnim.setDuration(time * mStepNum / mMaxStepNum);// 按照比例设置动画执行时间
    }

}

2. 条形图 效果:

在这里插入图片描述

public class MyProgressView extends View {

    private RectF mWheelRect = new RectF();

    private RectF mSmallRect = new RectF();
    private Paint mSmallPaint;
    private float mSmallStrokeWidth;

    private Paint mDefaultWheelPaint;
    private Paint mFinishWheelPaint;
    private Paint mCenterWheelPaint;
    private Paint mTitlePaint, mStepPaint, mTargetPaint;
    private float mCircleStrokeWidth;
    private float mSweepAnglePer;
    private float mPercent=0f;
    private int mStepNum, mCurrStepNum;
    private BarAnimation mAnim;
    private int mMaxStepNum;
    private float mTitleY, mStepY, mTargetY;
    private DecimalFormat mDecimalFormat = new DecimalFormat("#.0");
    private static String PERCENT;

    public MyProgressView(Context context){
        super(context);
        init(null,0);
    }

    public MyProgressView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(attrs,0);
    }

    public MyProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs,defStyleAttr);
    }

    private void init(AttributeSet attrs, int defStyle){
        mFinishWheelPaint = new Paint();
        mFinishWheelPaint.setColor(Color.rgb(100,113,205));
        mFinishWheelPaint.setStyle(Paint.Style.STROKE);
        mFinishWheelPaint.setStrokeCap(Paint.Cap.ROUND);
        mFinishWheelPaint.setAntiAlias(true);

        mCenterWheelPaint = new Paint();
        mCenterWheelPaint.setColor(Color.rgb(0, 0, 243));
        mCenterWheelPaint.setStyle(Paint.Style.STROKE);
        mCenterWheelPaint.setStrokeCap(Paint.Cap.ROUND);
        mCenterWheelPaint.setAntiAlias(true);

        mDefaultWheelPaint = new Paint();
        mDefaultWheelPaint.setColor(Color.rgb(255, 0, 0));
        mDefaultWheelPaint.setStyle(Paint.Style.STROKE);
        mDefaultWheelPaint.setStrokeCap(Paint.Cap.ROUND);
        mDefaultWheelPaint.setAntiAlias(true);

        mTitlePaint = new Paint();
        mTitlePaint.setAntiAlias(true);
        mTitlePaint.setColor(Color.WHITE);

        mStepPaint = new Paint();
        mStepPaint.setAntiAlias(true);
        mStepPaint.setColor(Color.WHITE);

        mTargetPaint = new Paint();
        mTargetPaint.setAntiAlias(true);
        mTargetPaint.setColor(Color.RED);
        mAnim = new BarAnimation();

        mSmallPaint = new Paint();
        mSmallPaint.setAntiAlias(true);
        mSmallPaint.setStyle(Paint.Style.STROKE);
        mSmallPaint.setStrokeCap(Paint.Cap.SQUARE);
        mSmallPaint.setColor(Color.CYAN);

    }


    private int[] array = {3,5,7};

    @Override
    protected void onDraw(Canvas canvas) {
       drawPos(canvas);
        float tmp = center_x+mPointSpace;;
        int i = 0;
        while(i<array.length){

            canvas.drawLine(tmp,X_startY,tmp, X_startY-(getTextScale(array[i]*mPercent,xmin)),mStepPaint);
            i++;
            tmp=tmp+mPointSpace;
        }
    }
    float xmin;

    private void drawPos(Canvas canvas){
        canvas.drawLine(X_startX,X_startY,X_stopX,X_stopY,mSmallPaint);
        canvas.drawLine(X_stopX,X_stopY,X_stopX-mArcSpace,X_stopY+mArcSpace,mSmallPaint);
        canvas.drawLine(X_stopX,X_stopY,X_stopX-mArcSpace,X_stopY-mArcSpace,mSmallPaint);
        canvas.drawLine(Y_startX,Y_startY,Y_stopX,Y_stopY,mSmallPaint);
        canvas.drawLine(Y_stopX,Y_stopY,Y_stopX-mArcSpace,Y_stopY+mArcSpace,mSmallPaint);
        canvas.drawLine(Y_stopX,Y_stopY,Y_stopX+mArcSpace,Y_stopY+mArcSpace,mSmallPaint);
        float tmp = center_x;
        int i = 0;
        while(tmp<=X_stopX){
            if(i==0){
                i++;
                tmp=tmp+mPointSpace;
                continue;
            }
            canvas.drawLine(tmp,X_startY,tmp-mPointLine, X_startY,mTargetPaint);
            String msg=""+i+"";
            canvas.drawText(msg,tmp-mTargetPaint.measureText(msg)*4/5,X_startY+mTextSpace,mTargetPaint);
            i++;
            tmp=tmp+mPointSpace;
        }
        i=0;
        tmp = center_x;
        while(tmp>=X_startX){
            if(i==0){
                i--;
                tmp=tmp-mPointSpace;
                continue;
            }
            canvas.drawLine(tmp,X_startY,tmp-mPointLine, X_startY,mTargetPaint);
            String msg=""+i+"";
            canvas.drawText(msg,tmp-mTargetPaint.measureText(msg)*4/5,X_startY+mTextSpace,mTargetPaint);
            i--;
            tmp=tmp-mPointSpace;
        }
        i=0;
        tmp = center_y;
        while(tmp>=Y_stopY){
            canvas.drawLine(Y_startX,tmp,Y_startX,tmp-mPointLine,mTargetPaint);
            String msg=""+i+"";
            canvas.drawText(msg,Y_startX-mTextSpace,tmp+mTargetPaint.measureText(msg)*5/3,mTargetPaint);
            i++;
            tmp=tmp-mPointSpace;
        }
        i=-1;
        tmp = center_y+mPointSpace;
        while(tmp<=Y_startY){
            canvas.drawLine(Y_startX,tmp,Y_startX,tmp-mPointLine,mTargetPaint);
            String msg=""+i+"";
            canvas.drawText(msg,Y_startX-mTextSpace,tmp+mTargetPaint.measureText(msg)*2/3,mTargetPaint);
            i--;
            tmp=tmp+mPointSpace;
        }
    }

    private float X_startX;
    private float X_startY;
    private float Y_startX;
    private float Y_startY;
    private float X_stopX;
    private float X_stopY;
    private float Y_stopX;
    private float Y_stopY;

    private float mArcSpace;
    private float mTextSpace;
    private float mPointSpace;
    private float mPointLine;
    private float center_x;
    private float center_y;

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int height = getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec);
        int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        int min = Math.min(width, height);// 获取View最短边的长度
        xmin = min;
        setMeasuredDimension(min, min);// 强制改View为以最短边为长度的正方形
        // 确定坐标轴
        float space = getTextScale(15,min);
        X_startX = space;
        X_startY = min-space*6;
        X_stopX = min-space;
        X_stopY = min-space*6;

        Y_startX = space*6;
        Y_startY = min-space;
        Y_stopX = space*6;
        Y_stopY = space;

        center_x = Y_startX;
        center_y = X_stopY;
        //
        mArcSpace = getTextScale(10,min);
        mSmallPaint.setStrokeWidth(3*min/500);
        mTargetPaint.setTextSize(getTextScale(30,min));
        mTargetPaint.setStrokeWidth(4*min/500);
        mStepPaint.setStrokeWidth(10*min/500);
        mTextSpace = getTextScale(30,min);
        mPointSpace = getTextScale(50,min);
        mPointLine = getTextScale(5,min);
    }
    /**
     * 进度条动画
     *
     * @author Administrator
     */
    public class BarAnimation extends Animation {

        /**
         * 每次系统调用这个方法时, 改变mSweepAnglePer,mPercent,stepnumbernow的值,
         * 然后调用postInvalidate()不停的绘制view。
         */
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
//			if (interpolatedTime < 1.0f) {
//				mPercent = Float.parseFloat(mDecimalFormat.format(interpolatedTime * mStepNum * 100f / mMaxStepNum));// 将浮点值四舍五入保留一位小数
//				mSweepAnglePer = interpolatedTime * mStepNum * 360 / mMaxStepNum;
//				mCurrStepNum = (int) (interpolatedTime * mStepNum);
//			} else {
//            mPercent = Float.parseFloat(mDecimalFormat.format(mStepNum * 100f / mMaxStepNum));// 将浮点值四舍五入保留一位小数
//            if (mPercent > 100.0f) {
//                mPercent = 100.0f;
//            }
//            PERCENT = String.valueOf(mPercent);
//            mSweepAnglePer = mStepNum * 360 / mMaxStepNum;
//            mCurrStepNum = mStepNum;
//			}
            mPercent = Float.parseFloat(mDecimalFormat.format(interpolatedTime * mStepNum * 100f / mMaxStepNum));


            requestLayout();
        }
    }

    public float getPercent() {
        return mPercent;
    }

    /**
     * 根据控件的大小改变绝对位置的比例
     *
     * @param n
     * @param m
     * @return
     */
    public float getTextScale(float n, float m) {
        return n / 500 * m;
    }

    /**
     * 更新步数和设置一圈动画时间
     *
     * @param stepCount
     * @param time
     */
    public void update(int stepCount, int time) {
        this.mStepNum = stepCount;
        mAnim.setDuration(time);
        setAnimationTime(time);
        this.startAnimation(mAnim);
    }

    /**
     * @param stepNum
     */
    public void setMaxStepNum(int stepNum) {
        mMaxStepNum = stepNum;

    }

    public void setColor(int color) {
        mFinishWheelPaint.setColor(color);
        mStepPaint.setColor(color);
    }

    /**
     * 设置动画时间
     *
     * @param time
     */
    public void setAnimationTime(int time) {
        mAnim.setDuration(time * mStepNum / mMaxStepNum);// 按照比例设置动画执行时间
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值