美文网首页Android自定义View
自定义view - 炫酷进度条

自定义view - 炫酷进度条

作者: 世道无情 | 来源:发表于2019-02-12 18:06 被阅读3次

    1. 思路分析


    自定义View步骤:
    1>:values__attrs.xml,自定义属性;
    2>:在第三个构造方法中,获取自定义属性;
    3>:onMeasure:不是非必须的,测量控件大小;
    4>:onDraw:所有绘制代码都写在onDraw方法中;

    思路分析
    1>:自定义属性:内圆颜色、外圆颜色、圆弧宽度、中间文字颜色、文字大小;
    2>:自定义ProgressBar,继承View;

    2. 效果图如下


    图片.png

    3. 代码如下


    1>:attrs.xml
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
        <!-- 炫酷进度条 -->
        <declare-styleable name="ProgressBar">
            <!-- 内圆弧背景 -->
            <attr name="innerBackground" format="color"/>
            <!-- 外圆弧背景 -->
            <attr name="outterBackground" format="color"/>
            <!-- 圆弧宽度 -->
            <attr name="roundWidth" format="dimension"/>
            <!-- 文字大小 -->
            <attr name="progressTextSize" format="dimension"/>
            <!-- 文字颜色 -->
            <attr name="progressTextColor" format="color"/>
        </declare-styleable>
    </resources>
    
    2>:ProgressBar
    /**
     * ================================================
     * Email: 2185134304@qq.com
     * Created by Novate 2018/12/29 15:25
     * Version 1.0
     * Params:
     * Description:    圆形进度条
     * ================================================
    */
    
    public class ProgressBar extends View {
    
        // 内圆弧默认颜色
        private int mInnerBackground = Color.RED ;
        // 外圆弧默认颜色
        private int mOuterBackground = Color.RED;
        // 圆弧宽度
        private int mRoundWidth = 10 ;
        // 文字大小
        private float mProgressTextSize = 15 ;
        // 文字颜色
        private int mProgressTextColor = Color.RED;
    
        // 3个画笔 内圆弧画笔、外圆弧画笔、文字画笔
        private Paint mInnerPaint,mOuterPaint,mTextPaint;
    
        // 设置最大进度
        private int mMax = 100 ;
        // 当前进度
        private int mProgress = 0 ;
        // 百分比
        private float  persent ;
    
        public ProgressBar(Context context) {
            this(context,null);
        }
    
        public ProgressBar(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs,0);
        }
    
        public ProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
    
            // 获取自定义属性
            TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ProgressBar);
            // 内圆弧背景
            mInnerBackground = typedArray.getColor(R.styleable.ProgressBar_innerBackground,mInnerBackground);
            // 外圆弧背景
            mOuterBackground = typedArray.getColor(R.styleable.ProgressBar_outterBackground,mOuterBackground);
            // 圆弧宽度
            mRoundWidth = typedArray.getDimensionPixelSize(R.styleable.ProgressBar_roundWidth,(int)dip2px(mRoundWidth));
            // 文字大小
            mProgressTextSize = typedArray.getDimensionPixelSize(R.styleable.ProgressBar_progressTextSize,sp2px(mProgressTextSize));
            // 文字颜色
            mProgressTextColor = typedArray.getColor(R.styleable.ProgressBar_progressTextColor,mProgressTextColor);
            // 释放资源
            typedArray.recycle();
    
    
            // 初始化3个画笔
            initPaint();
        }
    
        private void initPaint() {
            // 内圆弧画笔
            mInnerPaint = new Paint();
            // 设置抗锯齿
            mInnerPaint.setAntiAlias(true);
            // 内圆弧颜色
            mInnerPaint.setColor(mInnerBackground);
            // 圆弧宽度
            mInnerPaint.setStrokeWidth(mRoundWidth);
            // 只绘制图形边缘(描边) Paint.Style.FILL 只绘制图形内容 Paint.Style.FILL_AND_STROKE 既绘制轮廓也绘制内容
            mInnerPaint.setStyle(Paint.Style.STROKE);
    
            //外圆弧画笔
            mOuterPaint = new Paint() ;
            mOuterPaint.setAntiAlias(true);
            mOuterPaint.setColor(mOuterBackground);
            mOuterPaint.setStrokeWidth(mRoundWidth); //设置圆弧宽度
            mOuterPaint.setStyle(Paint.Style.STROKE);
    
            //文字画笔
            mTextPaint = new Paint() ;
            mTextPaint.setAntiAlias(true);
            mTextPaint.setTextSize(mProgressTextSize);
            mTextPaint.setColor(mProgressTextColor);
        }
    
    
        /**
         * 测量控件大小
         */
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            // 与qq计步器一样,只写最简单的形式,直接获取宽高,也就是说对应到xml布局文件中的宽高属性只能设置固定值,
            // 不能是wrap_content,如果想要设置wrap_content,这里首先要获取宽高模式,然后根据宽高模式再去获取宽高
    
            int width = MeasureSpec.getSize(widthMeasureSpec) ;
            int height = MeasureSpec.getSize(heightMeasureSpec) ;
    
            // 测量大小 这里保证是正方形:下边2种方式
    //        setMeasuredDimension(width>height?height:width,width>height?height:width);
            setMeasuredDimension(Math.min(width, height), Math.min(width, height));
        }
    
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
    
            // 1. 画内圆[是圆形,不是圆弧]
            drawCircle(canvas) ;
    
            // 2. 画外圆弧
            drawArc(canvas) ;
    
            // 3. 画文字
            drawText(canvas) ;
        }
    
    
        /**
         * 画文字
         */
        private void drawText(Canvas canvas) {
            // 要画的文字
            String text = (int)(persent*100)+"%";
            Rect rect = new Rect();
            // 文字区域
            mTextPaint.getTextBounds(text,0,text.length(),rect);
    
            int dx = getWidth()/2 - rect.width()/2;
    
            Paint.FontMetricsInt fontMetricsInt = mTextPaint.getFontMetricsInt();
            int dy = (fontMetricsInt.bottom-fontMetricsInt.top)/2-fontMetricsInt.bottom;
            // 基线
            int baseLine = getHeight()/2+dy;
            canvas.drawText(text,dx,baseLine,mTextPaint);
        }
    
    
        /**
         * 设置最大进度
         */
        public synchronized void setMax(int max){
            this.mMax=max;
        }
    
        /**
         * 当前进度
         */
        public synchronized void setProgress(int progress){
            if (progress < 0){
    
            }
            this.mProgress=progress;
    
            // 不断的获取到当前进度,然后需要不断的刷新
            invalidate();
        }
    
    
        /**
         * 2. 画外圆弧, 固定写法
         */
        private void drawArc(Canvas canvas) {
            RectF rectF = new RectF(0+mRoundWidth/2,0+mRoundWidth/2,getWidth()-mRoundWidth/2,getHeight()-mRoundWidth/2);
            if (mProgress == 0)
                return;
    
            persent = (float)mProgress/mMax;
    
            // param1: 圆弧形状和大小范围 param2: 开始的角度 param3: 扫过的角度 params4: 设置在画圆弧的时候,是否经过圆形 param5: 画笔
            canvas.drawArc(rectF,0,persent*360,false,mOuterPaint);
        }
    
    
        /**
         * 1. 画内圆:是圆形,不是圆弧, 固定写法
         */
        private void drawCircle(Canvas canvas) {
            // 中心点
            int center = getWidth()/2;
            // param1:圆心x坐标 param2:圆心y坐标 param3:圆的半径 param4: 画笔
            canvas.drawCircle(center,center,center-mRoundWidth/2,mInnerPaint);
        }
    
        private int sp2px(float sp) {
            return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics());
        }
    
        private float dip2px(int dip) {
            return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, getResources().getDisplayMetrics());
        }
    }
    
    3>:activity_progressbar
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:orientation="vertical" android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <com.novate.test.customview.ProgressBar
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:innerBackground="@color/colorPrimary"
            app:outterBackground="@color/colorAccent"
            app:roundWidth="20dp"
            app:progressTextColor="@color/colorAccent"
            app:progressTextSize="20sp"
            android:id="@+id/progress_bar"
            />
    </LinearLayout>
    
    4>:ProgressBarActivity
    public class ProgressBarActivity extends AppCompatActivity {
        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_progressbar);
    
            final ProgressBar mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
            // 设置最大进度
            mProgressBar.setMax(4000);
    
            // 属性动画
            ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0,4000);
            valueAnimator.setDuration(2000);
            valueAnimator.start();
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    // 不断的获取当前进度
                    float currrentProgress = (float) animation.getAnimatedValue();
                    // 设置当前进度
                    mProgressBar.setProgress((int) currrentProgress);
                }
            });
        }
    }
    

    相关文章

      网友评论

        本文标题:自定义view - 炫酷进度条

        本文链接:https://www.haomeiwen.com/subject/tpdplqtx.html