自定义View画圆 跟踪进度条 及改变颜色

1、自定义View的属性

2、在View的构造方法中获得我们自定义的属性

[ 3、重写onMesure ]

4、重写onDraw

我把3用[]标出了,所以说3不一定是必须的,当然了大部分情况下还是需要重写的。

1、自定义View的属性,首先在res/values/  下建立一个attrs.xml , 在里面定义我们的属性和声明我们的整个样式。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyView">
        <attr name="radius" format="dimension"/>
        <attr name="stripeWidth" format="dimension"/>   <!--色带宽度-->
        <attr name="percent" format="integer"/>         <!--百分比 最大值为100-->
        <attr name="smallColor" format="color"/>        <!--色带宽度-->
        <!--外圈颜色-->
        <attr name="bigColor" format="color"/>


        <!--中间字体颜色-->
        <attr name="centerTextSize" format="dimension"/>
        <!--色带宽度-->
    </declare-styleable>
</resources>

创建一个 Myview类来继承View 来实现它的及格有参构造

public class MyView extends View {
    //圆的半径
    private float mRadius;

    //色带的宽度
    private float mStripeWidth;
    //总体大小
    private int mHeight;
    private int mWidth;

    //动画位置百分比进度
    private int mCurPercent;

    //实际百分比进度
    private int mPercent;
    //圆心坐标
    private float x;
    private float y;

    //要画的弧度
    private int mEndAngle;

    //小圆的颜色
    private int mSmallColor;
    //大圆颜色
    private int mBigColor;

    //中心百分比文字大小
    private float mCenterTextSize;

    public MyView(Context context) {
        this(context, null);
    }

    public MyView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        // 获取自定义属性
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyView, defStyleAttr, 0);

        //获取色带的宽度
        mStripeWidth = a.getDimension(R.styleable.MyView_stripeWidth, PxUtils.dpToPx(30, context));
        //获取当前的百分比
        mCurPercent = a.getInteger(R.styleable.MyView_percent, 0);
        //获取小园的颜色
        mSmallColor = a.getColor(R.styleable.MyView_smallColor, Color.BLACK);
        //获取大圆的颜色
        mBigColor = a.getColor(R.styleable.MyView_bigColor, Color.WHITE);
        //获取中心文字的大小
        mCenterTextSize = a.getDimensionPixelSize(R.styleable.MyView_centerTextSize, PxUtils.spToPx(50, context));
        //获取园的半径
        mRadius = a.getDimensionPixelSize(R.styleable.MyView_radius, PxUtils.dpToPx(100, context));


    }

    //测量
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //获取测量模式
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        //获取测量大小
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        //如果为确定大小值,则圆的半径为宽度/2
        if (widthMode == MeasureSpec.EXACTLY && heightMode == MeasureSpec.EXACTLY) {
            mRadius = widthSize / 2;
            x = widthSize / 2;
            y = heightSize / 2;
            mWidth = widthSize;
            mHeight = heightSize;
        }
        //如果为wrap_content 那么View大小为圆的半径大小*2
        if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {
            mWidth = (int) (mRadius * 2);
            mHeight = (int) (mRadius * 2);
            x = mRadius;
            y = mRadius;

        }
        //设置视图的大小
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {


        mEndAngle = (int) (mCurPercent * 3.6);
        //绘制大圆
        Paint bigCirclePaint = new Paint();
        bigCirclePaint.setAntiAlias(true);
        bigCirclePaint.setColor(mBigColor);


        canvas.drawCircle(x, y, mRadius, bigCirclePaint);


        //饼状图
        Paint sectorPaint = new Paint();

        sectorPaint.setColor(mSmallColor);
        sectorPaint.setAntiAlias(true);
        RectF rect = new RectF(0, 0, mWidth, mHeight);

        canvas.drawArc(rect, 270, mEndAngle, true, sectorPaint);


        //绘制小圆,颜色透明
        Paint smallCirclePaint = new Paint();
        smallCirclePaint.setAntiAlias(true);
        smallCirclePaint.setColor(mBigColor);
        canvas.drawCircle(x, y, mRadius - mStripeWidth, smallCirclePaint);


        //绘制文本
        Paint textPaint = new Paint();
        String text = mCurPercent + "%";
        textPaint.setTextSize(mCenterTextSize);
        float textLength = textPaint.measureText(text);

        textPaint.setColor(Color.RED);
        canvas.drawText(text, x - textLength / 2, y, textPaint);
        super.onDraw(canvas);
    }

    public void setmSmallColor(int mSmallColor) {
        this.mSmallColor = mSmallColor;
        invalidate();
    }

    //重置
    public void setReset(int percent) {
        mCurPercent = percent;
        invalidate();
    }

    //外部设置百分比数
    public void setPercent(int percent) {
        if (percent > 100) {
            throw new IllegalArgumentException("percent must less than 100!");
        }
        setCurPercent(percent);
    }

    //内部设置百分比 用于动画效果
    private void setCurPercent(int percent) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 101; i++) {
                    mCurPercent = i;
                    try {
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    postInvalidate();
                }
            }
        }).start();

    }
}

对应的布局 主页面 坑点  布局里面的Myview标签控件 根据自己的创建的类 自动生成 里面对应的dabin属性自定义的 别忘导包  对应的这个布局的宽度高度有如下一句话 

xmlns:dabin="http://schemas.android.com/apk/res-auto"


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:dabin="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.view.MainActivity">

    <com.example.view.MyView
        android:id="@+id/my_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        dabin:stripeWidth="15dp"
        dabin:centerTextSize="16sp"
        dabin:percent="78"
        />


    <Button
        android:id="@+id/start"
        android:text="开始"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="26dp"
        android:layout_marginStart="26dp"
        android:layout_marginBottom="117dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />


    <Button
        android:text="重置"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/start"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_marginRight="51dp"
        android:layout_marginEnd="51dp"
        android:id="@+id/reset" />


    <Button
        android:text="改变外圈颜色"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignLeft="@+id/reset"
        android:layout_alignStart="@+id/reset"
        android:layout_marginLeft="19dp"
        android:layout_marginStart="19dp"
        android:layout_marginTop="56dp"
        android:id="@+id/button2" />

</RelativeLayout>
对应创建    一个转换Dip dp的的单位的类,可有可无,但是我对应的用了,这点根据自己需求 PxUtils

public class PxUtils {

    public static int dpToPx(int dp, Context context) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
    }

    public static int spToPx(int sp,Context context) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, context.getResources().getDisplayMetrics());
    }
}
最后 就是对应的主方法 Activity

public class MainActivity extends AppCompatActivity {
    private MyView myView;
    private Button mButton;
    private Button mReset;
    private Button mColor;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        myView = (MyView) findViewById(R.id.my_view);
        mButton = (Button) findViewById(R.id.start);
        mReset = (Button) findViewById(R.id.reset);
        mColor = (Button) findViewById(R.id.button2);

        //开始
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int n = (int) (Math.random() * 100);
                myView.setPercent(n);
            }
        });
        //重置
        mReset.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myView.setReset(78);
            }
        });
        mColor.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myView.setmSmallColor(Color.BLUE);
            }
        });

    }
}

 以上就能实现一个view圆  联动进度条  ,默认是78,转到100,有三个对应的按钮 点击 分别是重设 回到默认的 ,开始 :开始转动 ,第三个改变View的颜色


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值