干货来了,手把手教你Android自定义饼状图,带加载动画!

是时候拿起笔画一个自定义控件了————————————

废话不多讲,先上效果图:↓↓↓



正式开始我们的自定义工作。

第一步:创建实体类ViewBean

/**
 * Created by Jabez on 2017/3/24.
 */

public class ViewBean {
    private int color;//圆环颜色
    private String text;//版块文字
    private float data;//数据
    private float angle;//扫过弧度

    public float getAngle() {
        return angle;
    }

    public void setAngle(float angle) {
        this.angle = angle;
    }

    public int getColor() {
        return color;
    }

    public void setColor(int color) {
        this.color = color;
    }

    public String getText() {
        return text;
    }

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

    public float getData() {
        return data;
    }

    public void setData(float data) {
        this.data = data;
    }

}
上述代码注释很清楚,不过多解释啦!
-----------------------------------------

第二步:新建一个自定义动画类CustomAnimation
import java.util.List;

/**
 * Created by Jabez on 2017/3/24.
 */

public class CustomAnimation extends Animation {
    private View view;
    private List<ViewBean> viewBeanList;
    private float total;//总金额,需要传递过来
    public CustomAnimation(View view,List<ViewBean> viewBeenList, float total){
        this.view = view;
        this.viewBeanList = viewBeenList;
        this.total = total;
    }
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        super.applyTransformation(interpolatedTime, t);
        if(interpolatedTime <= 1.0f) {
            for (int i = 0; i < viewBeanList.size(); i++) {
                ViewBean viewBean = viewBeanList.get(i);
                float percent = (viewBean.getData() / total) * 360 * interpolatedTime;
                viewBean.setAngle(percent);
                //重新绘制
                view.postInvalidate();
            }
        }
    }
}

通过上述自定义动画,实际上就是更改圆弧的弧度,更改一次就重新绘制一次,特别要提的就是上面的一个percent(百分占比)算法,
viewBean.getData() / total是获取这条数据在全部数据中所占比例,然后 viewBean.getData() / total * 360就是在整个圆中的占比,
最后 (viewBean.getData() / total) * 360 * interpolatedTime,interpolatedTime是插入值时间(范围是0~1.0),所以算法算出来就是当前时间上,圆弧的角度。
举个简单的例子就是你设置了2000毫秒的动画时间,当执行到1s时,interpolatedTime = 0.5,算出来就是圆弧角度了。
--------------------------------------------------------------------------------------------------------

第三步:新建一个CustomArcView类


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;

import com.cdbhe.myproject.custom.CustomAnimation;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Jabez on 2017/3/24.
 */

public class CustomArcView extends View {
    private Paint paint;
    private Paint textPaint;
    private List<ViewBean> viewBeenList = null;
    private float total = 0;
    private CustomAnimation customAnimation;
    private int delayMillis = 2000;
    public CustomArcView(Context context) {
        super(context);
    }

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

    public void init(){
        ViewBean viewBean = new ViewBean();
        viewBean.setColor(Color.CYAN);
        viewBean.setText("余额");
        viewBean.setData(100);
        viewBeenList = new ArrayList<>();
        viewBeenList.add(viewBean);

        //初始化画笔
        paint = new Paint();
        paint.setAntiAlias(true);//设置抗锯齿
        paint.setStyle(Paint.Style.FILL);//设置为线条样式

        //初始化文字画笔
        textPaint = new Paint();
        textPaint.setColor(Color.BLACK);
        textPaint.setStyle(Paint.Style.STROKE);
        textPaint.setTextSize(sp2px(14));

        for(int i=0;i<viewBeenList.size();i++){
            total+=viewBeenList.get(i).getData();
        }
        initAnim();
    }

    public void initAnim(){
        customAnimation = new CustomAnimation(this,viewBeenList,total);
        customAnimation.setDuration(delayMillis);
        customAnimation.setFillAfter(true);
        customAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
        startAnimation(customAnimation);
    }

    public void setViewBeanList(List<ViewBean> viewBeanList){
        this.viewBeenList = viewBeanList;
        initAnim();
    }

    public void setDelayMillis(int delayMillis){
        this.delayMillis = delayMillis;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        RectF rectF = new RectF(10, 10, 300, 300);//设置绘制外切矩阵

        float start = 0;//绘制开始的弧度
        float cy = 20;//y轴坐标
        for (int i = 0; i < viewBeenList.size(); i++) {//循环绘制
            ViewBean viewBean = viewBeenList.get(i);
            //绘制圆弧
            paint.setColor(viewBean.getColor());//设置画笔颜色
            canvas.drawArc(rectF, start, viewBean.getAngle(), true, paint);//绘制圆弧
            start += viewBean.getAngle();
            //绘制标注
            canvas.drawCircle(320,cy,10,paint);
            //绘制文字
            canvas.drawText(viewBean.getText() + " " + viewBean.getData(),340,cy+5,textPaint);
            cy += 35;
        }

        //画中心白色圆
        paint.setColor(Color.WHITE);
        canvas.drawCircle(155, 155, 50, paint);
    }

    /**
     * dp 2 px
     *
     * @param dpVal
     */
    protected int dp2px(int dpVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, getResources().getDisplayMetrics());
    }

    /**
     * sp 2 px
     *
     * @param spVal
     * @return
     */
    protected int sp2px(int spVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                spVal, getResources().getDisplayMetrics());

    }
}
上面的代码已经很清晰了,一看就懂的,具体步骤为:先定义需要的变量,如全局画笔Paint(需要全局,因为如果定义在onDraw的话,重新绘制又会new,会增大系统开销),
还有就是绘制文字的textPaint,还有就是上面写出来的。

在构造里面就调用初始化方法,初始化初始List(在不传数值的情况下默认一条数据),初始化画笔以及动画

PS:customAnimation.setInterpolator(new AccelerateDecelerateInterpolator());这个是设置加载的播放速度的,有如下实例:
AccelerateDecelerateInterpolator  在动画开始与结束的地方速率改变比较慢,在中间的时候加速。
AccelerateInterpolator  在动画开始的地方速率改变比较慢,然后开始加速。
CycleInterpolator  动画循环方法特定的次数,速率改变沿着正弦曲线。
DecelerateInterpolator  在动画开始的地方速率改变比较慢,然后开始减速。
LinearInterpolator   匀速速率

接着就是onDraw方法了,canvas的方法就不多讲了,百度都都搜到,讲的话就废话了

-------------------------------------------------------------------------------
最后一步,调用吧:

import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

import com.cdbhe.myproject.R;
import com.cdbhe.myproject.layout.CustomArcView;
import com.cdbhe.myproject.layout.ViewBean;

import java.util.ArrayList;
import java.util.List;


public class MainActivity extends AppCompatActivity {
    private Button btn;
    private CustomArcView customArcView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn = (Button)findViewById(R.id.send);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                initComp();
            }
        });
    }
    private void initComp(){
        int[] colors = new int[]{Color.BLACK,Color.CYAN,Color.GRAY,Color.GREEN};
        String[] texts = new String[]{"余额","余额宝","亏欠","收入"};
        float[] datas = new float[]{20,40,10.00f,30.00f};
        customArcView = (CustomArcView)findViewById(R.id.customView);
        List<ViewBean> viewBeanList = new ArrayList<>();
        for(int i=0;i<colors.length;i++){
            ViewBean viewBean = new ViewBean();
            viewBean.setColor(colors[i]);
            viewBean.setText(texts[i]);
            viewBean.setData(datas[i]);
            viewBeanList.add(viewBean);
        }
        customArcView.setDelayMillis(1000);
        customArcView.setViewBeanList(viewBeanList);
    }
}

点击按钮后就如效果图所示,结篇!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值