Android自定义View实现ColorProgressbar

android官方给出的自定义控件的步骤:
1、创建View
2、处理View的布局
3、绘制View
4、与用户进行交互
5、优化已定义的View

强调内容
自定义属性:
自定义属性通常写在在res/values/attrs.xml文件中 ,使用自定义属性的时候需要指定命名空间,在android studio,用http://schemas.android.com/apk/res/res-auto
在 xml中创建了一个view时,所有在xml中声明的属性都会被传入到view的构造方法中的AttributeSet类型的参数当中。
通过调用Context的obtainStyledAttributes()方法返回一个TypedArray对象。然后直接用TypedArray对象获取自定义属性的值。
由于TypedArray对象是共享的资源,所以在获取完值之后必须要调用recycle()方法来回收。
Android自定义View实现ColorProgressbar_第1张图片

布局如下:


<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.mycolorarcprogressbar.MainActivity">
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:orientation="vertical">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn1"
        android:text="Start"/>
    <com.example.mycolorarcprogressbar.MyColorProgressBar
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_gravity="center_horizontal"
        android:id="@+id/bar1"

       />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn2"
        android:text="start"
        />
    <com.example.mycolorarcprogressbar.MyColorProgressBar
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_gravity="center_horizontal"
        android:id="@+id/bar2"

        />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn3"
        android:text="start"
        />
    <com.example.mycolorarcprogressbar.MyColorProgressBar
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_gravity="center_horizontal"
        android:id="@+id/bar3"

        />

LinearLayout>
ScrollView>

自定义VIew的属性:


<resources>
    <declare-styleable name="MyColorProgressBar">
       <attr name="ColorArcProgressBar_front_color1" format="color"/>
        <attr name="ColorArcProgressBar_front_color2" format="color"/>
        <attr name="ColorArcProgressBar_front_color3" format="color"/>
        <attr name="ColorArcProgressBar_total_engle" format="color"/>
        <attr name="ColorArcProgressBar_back_width" format="color"/>
        <attr name="ColorArcProgressBar_front_width" format="color"/>
        <attr name="ColorArcProgressBar_is_need_title" format="color"/>
        <attr name="ColorArcProgressBar_is_need_content" format="color"/>
        <attr name="ColorArcProgressBar_is_need_unit" format="color"/>
        <attr name="ColorArcProgressBar_is_need_dial" format="color"/>
        <attr name="ColorArcProgressBar_string_unit" format="color"/>
        <attr name="ColorArcProgressBar_string_title" format="color"/>
        <attr name="ColorArcProgressBar_current_value" format="color"/>
        <attr name="ColorArcProgressBar_max_value" format="color"/>
    declare-styleable>
resources>
package com.example.mycolorarcprogressbar;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import com.example.mycolorarcprogressbar.MyColorProgressBar;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private Button  mButton1,mButton2,mButton3;
    private MyColorProgressBar mBar1,mBar2,mBar3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBar1 = (MyColorProgressBar) findViewById(R.id.bar1);
        mButton1 = (Button) findViewById(R.id.btn1);
        mBar2 = (MyColorProgressBar) findViewById(R.id.bar2);
        mButton2 = (Button) findViewById(R.id.btn2);
        mBar3 = (MyColorProgressBar) findViewById(R.id.bar3);
        mButton3 = (Button) findViewById(R.id.btn3);
        mButton1.setOnClickListener(this);
        mButton2.setOnClickListener(this);
        mButton3.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn1:
                //进度条当前的值
                mBar1.setCurrentValues(100);
                break;
            case R.id.btn2:
                mBar2.setCurrentValues(50);
                break;
            case R.id.btn3:
                mBar3.setCurrentValues(30);
                break;
        }
    }
}


package com.example.mycolorarcprogressbar;

import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import android.animation.ValueAnimator;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.RectF;
import android.graphics.SweepGradient;
import android.util.DisplayMetrics;
import android.view.WindowManager;

public class MyColorProgressBar extends View {
    private int mWidth,mHeight;
    //直径
    private int diameter = 500;
    //圆心
    private float centerX,centerY;
    //定义画笔
    private Paint allArcPaint;
    //进度条的画笔
    private Paint progressPaint;
    //角度的画笔
    private Paint degreePaint;
    private RectF bgRect;
    //属性动画
    private ValueAnimator progressAnimator;
    //刚开始角度
    private float startAngle = 135;
    //渐变角度
    private float sweepAngle = 270;
    //当前角度
    private float currentAngle = 0;
    //最终角度
        private float lastAngle;
        private int[] colors = new int[]{Color.BLUE, Color.YELLOW, Color.RED, Color.RED};
        private float maxValues = 60;
        private float curValues = 0;
        private float bgArcWidth = dipToPx(2);
        private float progressWidth = dipToPx(10);
        private float textSize = dipToPx(60);
        private int aniSpeed = 1000;
        private float longdegree = dipToPx(13);
        private float shortdegree = dipToPx(5);
        private final int DEGREE_PROGRESS_DISTANCE = dipToPx(8);

        private String longDegreeColor = "#111111";
        private String shortDegreeColor = "#111111";
        private String bgArcColor = "#111111";
        private boolean isShowCurrentSpeed = true;
        private String hintString = "Km/h";
        private boolean isNeedTitle;
        private boolean isNeedUnit;
        private boolean isNeedDial;
        private boolean isNeedContent;
        private String titleString;
    // sweepAngle / maxValues 的值
       private float k;

    public MyColorProgressBar(Context context) {
           super(context, null);
           initView();
       }
        public MyColorProgressBar(Context context, AttributeSet attrs) {
           super(context, attrs, 0);
           initCofig(context, attrs);
            initView();
       }

       public MyColorProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            initCofig(context, attrs);
            initView();
       }

    //初始布局配置
        private void initCofig(Context context, AttributeSet attrs) {
            //获得所有的属性值
            //R.styleable.MyColorProgressBar是需要在values下建一个attrs固定目录
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyColorProgressBar);
            int color1 = a.getColor(R.styleable.MyColorProgressBar_ColorArcProgressBar_front_color1, Color.MAGENTA);
            int color2 = a.getColor(R.styleable.MyColorProgressBar_ColorArcProgressBar_front_color2, Color.GREEN);
            int color3 = a.getColor(R.styleable.MyColorProgressBar_ColorArcProgressBar_front_color3, Color.BLUE);
            colors = new int[]{color1, color2, color3};

            sweepAngle = a.getInteger(R.styleable.MyColorProgressBar_ColorArcProgressBar_total_engle, 270);
            bgArcWidth = a.getDimension(R.styleable.MyColorProgressBar_ColorArcProgressBar_back_width, dipToPx(2));
            progressWidth = a.getDimension(R.styleable.MyColorProgressBar_ColorArcProgressBar_front_width, dipToPx(10));
            isNeedTitle = a.getBoolean(R.styleable.MyColorProgressBar_ColorArcProgressBar_is_need_title, false);
            isNeedContent = a.getBoolean(R.styleable.MyColorProgressBar_ColorArcProgressBar_is_need_content, false);
            isNeedUnit = a.getBoolean(R.styleable.MyColorProgressBar_ColorArcProgressBar_is_need_unit, false);
            isNeedDial = a.getBoolean(R.styleable.MyColorProgressBar_ColorArcProgressBar_is_need_dial, false);
            hintString = a.getString(R.styleable.MyColorProgressBar_ColorArcProgressBar_string_unit);
            titleString = a.getString(R.styleable.MyColorProgressBar_ColorArcProgressBar_string_title);
            curValues = a.getFloat(R.styleable.MyColorProgressBar_ColorArcProgressBar_current_value, 0);
            maxValues = a.getFloat(R.styleable.MyColorProgressBar_ColorArcProgressBar_max_value, 60);
            setCurrentValues(curValues);
            setMaxValues(maxValues);
            a.recycle();

        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int width = (int) (2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE);
            int height= (int) (2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE);
            setMeasuredDimension(width, height);
        }

        private void initView() {

            diameter = 3 * getScreenWidth() / 5;
            //弧形的矩阵区域
            bgRect = new RectF();
            bgRect.top = longdegree + progressWidth/2 + DEGREE_PROGRESS_DISTANCE;
            bgRect.left = longdegree + progressWidth/2 + DEGREE_PROGRESS_DISTANCE;
            bgRect.right = diameter + (longdegree + progressWidth/2 + DEGREE_PROGRESS_DISTANCE);
            bgRect.bottom = diameter + (longdegree + progressWidth/2 + DEGREE_PROGRESS_DISTANCE);

            //圆心
            centerX = (2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE)/2;
            centerY = (2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE)/2;

            //外部刻度线
            degreePaint = new Paint();
            degreePaint.setColor(Color.parseColor(longDegreeColor));

            //整个弧形
            allArcPaint = new Paint();
            allArcPaint.setAntiAlias(true);
            allArcPaint.setStyle(Paint.Style.STROKE);
            allArcPaint.setStrokeWidth(bgArcWidth);
            allArcPaint.setColor(Color.parseColor(bgArcColor));
            allArcPaint.setStrokeCap(Paint.Cap.ROUND);

            //当前进度的弧形
            progressPaint = new Paint();
            progressPaint.setAntiAlias(true);
            progressPaint.setStyle(Paint.Style.STROKE);
            progressPaint.setStrokeCap(Paint.Cap.ROUND);
            progressPaint.setStrokeWidth(progressWidth);
            progressPaint.setColor(Color.GREEN);


        }



        @Override
        protected void onDraw(Canvas canvas) {

            //抗锯齿
            canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));

            if (isNeedDial) {
                //画刻度线
                for (int i = 0; i < 40; i++) {
                    if (i > 15 && i < 25) {
                        canvas.rotate(9, centerX, centerY);
                        continue;
                    }
                    if (i % 5 == 0) {
                        degreePaint.setStrokeWidth(dipToPx(2));
                        degreePaint.setColor(Color.parseColor(longDegreeColor));
                        canvas.drawLine(centerX, centerY - diameter / 2 - progressWidth / 2 - DEGREE_PROGRESS_DISTANCE, centerX, centerY - diameter / 2 - progressWidth / 2 - DEGREE_PROGRESS_DISTANCE - longdegree, degreePaint);
                    } else {
                        degreePaint.setStrokeWidth(dipToPx(1.4f));
                        degreePaint.setColor(Color.parseColor(shortDegreeColor));
                        canvas.drawLine(centerX, centerY - diameter / 2 - progressWidth / 2 - DEGREE_PROGRESS_DISTANCE - (longdegree - shortdegree) / 2, centerX, centerY - diameter / 2 - progressWidth / 2 - DEGREE_PROGRESS_DISTANCE - (longdegree - shortdegree) / 2 - shortdegree, degreePaint);
                    }

                    canvas.rotate(9, centerX, centerY);
                }
            }

            //整个弧
            canvas.drawArc(bgRect, startAngle, sweepAngle, false, allArcPaint);

            //设置渐变色
            SweepGradient sweepGradient = new SweepGradient(centerX, centerY, colors, null);
            Matrix matrix = new Matrix();
            matrix.setRotate(130, centerX, centerY);
            sweepGradient.setLocalMatrix(matrix);
            progressPaint.setShader(sweepGradient);

            //当前进度
            canvas.drawArc(bgRect, startAngle, currentAngle, false, progressPaint);
            invalidate();

        }

        //设置最大值 maxValues
    public void setMaxValues(float maxValues) {
           this.maxValues = maxValues;
            k = sweepAngle/maxValues;
        }

        //设置当前值 currentValues
        public void setCurrentValues(float currentValues) {
            if (currentValues > maxValues) {
                currentValues = maxValues;
            }
            if (currentValues < 0) {
                currentValues = 0;
            }
            this.curValues = currentValues;
            lastAngle = currentAngle;
            setAnimation(lastAngle, currentValues * k, aniSpeed);
        }


        //  设置整个圆弧宽度 bgArcWidth
        public void setBgArcWidth(int bgArcWidth) {
            this.bgArcWidth = bgArcWidth;
        }

    //设置进度宽度 progressWidth

        public void setProgressWidth(int progressWidth) {
            this.progressWidth = progressWidth;
        }

        //设置速度文字大小 mtextSize

        public void setTextSize(int textSize) {
            this.textSize = textSize;
        }
        // 设置直径大小 diameter

        public void setDiameter(int diameter) {
            this.diameter = dipToPx(diameter);
        }


        // 为进度设置动画 last current

        private void setAnimation(float last, float current, int length) {
            progressAnimator = ValueAnimator.ofFloat(last, current);
            progressAnimator.setDuration(length);
            progressAnimator.setTarget(currentAngle);
            progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    currentAngle= (float) animation.getAnimatedValue();
                    curValues = currentAngle/k;
                }
            });
            progressAnimator.start();
        }
    private int dipToPx(float dip) {
            float density = getContext().getResources().getDisplayMetrics().density;
            return (int)(dip * density + 0.5f * (dip >= 0 ? 1 : -1));
        }
    private int getScreenWidth() {
            WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
            DisplayMetrics displayMetrics = new DisplayMetrics();
            windowManager.getDefaultDisplay().getMetrics(displayMetrics);
            return displayMetrics.widthPixels;
        }

        public void setIsShowCurrentSpeed(boolean isShowCurrentSpeed) {
            this.isShowCurrentSpeed = isShowCurrentSpeed;
        }
}

Android自定义View实现ColorProgressbar_第2张图片

Android自定义View实现ColorProgressbar_第3张图片

Android自定义View实现ColorProgressbar_第4张图片

你可能感兴趣的:(Android小项目)