Android自定义饼形图

效果图如下:


属性文件如下:

attrs_pie_view.xml

<resources>
    <declare-styleable name="PieView">
        <attr name="color_a" format="color" />
        <attr name="color_b" format="color" />
        <attr name="color_c" format="color" />
        <attr name="color_d" format="color" />
        <attr name="stroke_width" format="dimension" />
        <attr name="text_color" format="color" />
        <attr name="text_size" format="dimension" />
        <attr name="text" format="string" />
        <attr name="percent_arc_a" format="float" />
        <attr name="text_percent_size" format="dimension" />
    </declare-styleable>
</resources>

代码文件如下:

PieView.java

package net.sytm.pieview;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.LinearInterpolator;


public class PieView extends View {

    //正常颜色
    private int colorA;
    //迟到颜色
    private int colorB;
    //早退颜色
    private int colorC;
    //未打卡颜色
    private int colorD;

    //扫过的角度
    private float arcA;
    private float arcB;
    private float arcC;
    private float arcD;
    //画笔宽度
    private int strokeWidth;
    //文字颜色
    private int textColor;
    //文字大小
    private int textSize;

    //直径
    private int diameter;
    //画笔
    private Paint paint;
    private TextPaint textPaint;

    //扇形区域
    private RectF rectF;
    //零时变量
    private float tmpArcA;
    private float tmpArcB;
    private float tmpArcC;
    private float tmpArcD;
    //文字区域
    private Rect rect;
    //中间百分数
    private String text;
    //文字区域
    private Rect rectPercent;
    //百分号%
    private String textPercent;
    //百分号大小
    private int textPercentSize;
    //提示文字
    private String textTips;

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

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

    public PieView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.PieView, defStyle, 0);
        int count = array.getIndexCount();
        for (int i = 0; i < count; i++) {
            int attr = array.getIndex(i);
            switch (attr) {
                case R.styleable.PieView_color_a:
                    colorA = array.getColor(attr, Color.WHITE);
                    break;
                case R.styleable.PieView_color_b:
                    colorB = array.getColor(attr, Color.WHITE);
                    break;
                case R.styleable.PieView_color_c:
                    colorC = array.getColor(attr, Color.WHITE);
                    break;
                case R.styleable.PieView_color_d:
                    colorD = array.getColor(attr, Color.WHITE);
                    break;
                case R.styleable.PieView_stroke_width:
                    strokeWidth = array.getDimensionPixelSize(attr,
                            (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, getResources().getDisplayMetrics()));
                    break;
                case R.styleable.PieView_text_color:
                    textColor = array.getColor(attr, Color.WHITE);
                    break;
                case R.styleable.PieView_text_size:
                    textSize = array.getDimensionPixelSize(attr,
                            (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, getResources().getDisplayMetrics()));
                    break;
                case R.styleable.PieView_text:
                    text = array.getString(attr);
                    break;
                case R.styleable.PieView_percent_arc_a:
                    //这个属性是只是为了预览视图
                    tmpArcA = percentToDegree(array.getFloat(attr, 0f));
                    break;
                case R.styleable.PieView_text_percent_size:
                    textPercentSize = array.getDimensionPixelSize(attr,
                            (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, getResources().getDisplayMetrics()));
                    break;
            }
        }
        array.recycle();

        paint = new Paint();
        paint.setAntiAlias(true);
        //直径取屏幕的一半
        diameter = getResources().getDisplayMetrics().widthPixels / 2;
        //半径
        int radius = diameter / 2;
        rectF = new RectF(- radius , - radius , radius, radius);
        rectPercent = new Rect();
        textPaint = new TextPaint();
        textPaint.setAntiAlias(true);
        rect = new Rect();
        textPercent = "%";
        textTips = "优秀度";
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthNode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);

        int heightNode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        int width;
        int height;
        if (widthNode == MeasureSpec.EXACTLY) {
            width = widthSize;
        }
        else {
            width = diameter * 2;
        }

        if (heightNode == MeasureSpec.EXACTLY) {
            height = heightSize;
        }
        else {
            height = diameter * 2 -  diameter / 2;
        }
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        initCanvas(canvas);
        drawArcA(canvas);
        drawArcB(canvas);
        drawArcC(canvas);
        drawArcD(canvas);
        drawText(canvas);
    }

    /**
     * 初始化画板
     * 移动画板的坐标原点
     * 目的为了后面绘制方便,更符合人类的思维模式
     * @param canvas
     */
    private void initCanvas(Canvas canvas) {
        canvas.translate(getWidth() / 2, getHeight() / 2);
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.RED);

        //原点
        if (BuildConfig.DEBUG) {
            canvas.drawCircle(0, 0, 3, paint);
        }

    }

    /**
     * 绘制正常数据
     * @param canvas
     */
    private void drawArcA(Canvas canvas) {
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(colorA);
        paint.setStrokeWidth(strokeWidth);
        canvas.drawArc(rectF, 0, tmpArcA, false, paint);
    }

    /**
     * 绘制迟到数据
     * @param canvas
     */
    private void drawArcB(Canvas canvas) {
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(colorB);
        paint.setStrokeWidth(strokeWidth);
        canvas.drawArc(rectF, arcA, tmpArcB, false, paint);
    }

    /**
     * 绘制早退数据
     * @param canvas
     */
    private void drawArcC(Canvas canvas) {
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(colorC);
        paint.setStrokeWidth(strokeWidth);
        canvas.drawArc(rectF, arcA + arcB, tmpArcC, false, paint);
    }

    /**
     * 绘制未打卡数据
     * @param canvas
     */
    private void drawArcD(Canvas canvas) {
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(colorD);
        paint.setStrokeWidth(strokeWidth);
        canvas.drawArc(rectF, arcA + arcB + arcC, tmpArcD, false, paint);
    }

    /**
     * 绘制文字
     * @param canvas
     */
    private void drawText(Canvas canvas) {
        textPaint.setColor(textColor);
        textPaint.setTextSize(textSize);
        textPaint.getTextBounds(text, 0, text.length(), rect);
        canvas.drawText(text, 0 - rect.width() / 1.5f, rect.height() / 4 , textPaint);
        //绘制百分号
        textPaint.setTextSize(textPercentSize);
        textPaint.getTextBounds(textPercent, 0, textPercent.length(), rectPercent);
        canvas.drawText(textPercent,  rect.width() / 4 + rectPercent.width(), rect.height() / 10 + rectPercent.height() / 3, textPaint);
        //绘制优秀度
        textPaint.setColor(Color.parseColor("#999999"));
        textPaint.setTextSize(textPercentSize);
        textPaint.getTextBounds(textTips, 0, textTips.length(), rectPercent);
        canvas.drawText(textTips,  - rectPercent.width() / 2, rect.height() + rectPercent.height(), textPaint);
    }


    /**
     * 百分比转换为度数
     * @param percent
     * @return
     */
    private float percentToDegree(float percent) {
        return 360 * percent / 100;
    }

    public void setArcA(float percent) {
        this.arcA = percentToDegree(percent);
    }

    public void setArcB(float percent) {
        this.arcB = percentToDegree(percent);
    }

    public void setArcC(float percent) {
        this.arcC = percentToDegree(percent);
    }

    public void setArcD(float percent) {
        this.arcD = percentToDegree(percent);
    }

    public void setText(String text) {
        this.text = text;
    }

    public void startAnim() {
        ValueAnimator valueAnimatorA = ValueAnimator.ofFloat(0f, arcA);
        valueAnimatorA.setInterpolator(new LinearInterpolator());
        valueAnimatorA.setDuration(1000);
        valueAnimatorA.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                tmpArcA = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        valueAnimatorA.start();

        ValueAnimator valueAnimatorB = ValueAnimator.ofFloat(0f, arcB);
        valueAnimatorB.setInterpolator(new LinearInterpolator());
        valueAnimatorB.setDuration(1000);
        valueAnimatorB.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                tmpArcB = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        valueAnimatorB.start();

        ValueAnimator valueAnimatorC = ValueAnimator.ofFloat(0f, arcC);
        valueAnimatorC.setInterpolator(new LinearInterpolator());
        valueAnimatorC.setDuration(1000);
        valueAnimatorC.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                tmpArcC = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        valueAnimatorC.start();

        ValueAnimator valueAnimatorD = ValueAnimator.ofFloat(0f, arcD);
        valueAnimatorD.setInterpolator(new LinearInterpolator());
        valueAnimatorD.setDuration(1000);
        valueAnimatorD.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                tmpArcD = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        valueAnimatorD.start();

    }
}

使用步骤如下:

布局引用视图:

<?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:layout_width="match_parent"
    android:layout_height="match_parent">

    <net.sytm.pieview.PieView
        android:layout_width="368dp"
        android:layout_height="wrap_content"
        android:id="@+id/pie_view"
        app:color_a="#d2f6f2"
        app:color_b="#fe8081"
        app:color_c="#ffdf6e"
        app:color_d="#afa9ff"
        app:stroke_width="32dp"
        app:text="70"
        app:text_size="64sp"
        app:text_color="#333333"
        app:percent_arc_a="100"
        app:text_percent_size="14sp" />

</LinearLayout>

示例代码:

package net.sytm.pieview;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        PieView pieView = (PieView) findViewById(R.id.pie_view);
        //赋值百分比
        pieView.setArcA(70);
        //赋值百分比
        pieView.setArcB(15);
        //赋值百分比
        pieView.setArcC(10);
        //赋值百分比
        pieView.setArcD(5);
        //中间的百分数
        pieView.setText("70");
        pieView.startAnim();
    }
}

项目源码下载:http://download.csdn.net/detail/hu285279904/9774936

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值