您的位置:首页 > 移动开发 > Android开发

自定义圆形统计图(静态)

2016-06-23 18:35 429 查看
    最近项目中有这个需求,将总资产的组成以图形的形态展现出来,所以就写了个自定义View来实现这个需求。



    其实试下这个思路还是挺简单的,因为只需要在onDraw方法中使用画笔画出一个又一个的扇形,就能实现这样的效果。

    以下是我的思路,首先介绍下canvas.drawArc()方法。

    RectF rectF = new RectF(100, 100, 500, 500);

    //绘制扇形

    canvas.drawArc(rectF, startAngle, endAngle, true, paint);

    参数说明:

    rectF:绘制扇形的区域

    startAngle:扇形的开始绘制的角度(是角度值不是弧度值)

    endAngle:扇形绘制结束的角度值

    true:是否从圆心开始画扇形

    paint:画笔

    所以实现起来的思路就是:

    通过给定的数据值,也就是一个包含数字的数组,然后算出每个数字的比重,乘上360度,算出每个数字所占的扇形的角度值,然后通过给不同数字的画上颜色不同的扇形,当处理完所有的数据后,就可以看到由不同颜色扇形所组成的一个圆,这当然不是我们所想要的,所以在最后,以相同的圆心画一个白色的圆,当然这个圆的半径要比刚刚那个彩色的圆的半径要小,最后剩下的就是我们想要的结果,最后在扇形的中间写上我们需要的文字即可。

    这个是画上几个扇形后的效果。



在中间画一个白色的圆之后就变成这样的了



其实这个时候就已经初见成效了。最后加上文字就好了。



最后提供自定义的控件。

SelfStatistics.java

package com.cretin.testprogress.views;

import android.annotation.TargetApi;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.RectF;

import android.os.Build;

import android.util.AttributeSet;

import android.view.View;

import java.util.ArrayList;

import java.util.List;

/**

* Created by cretin on 16/6/23.

*/

public class SelfStatistics extends View {

   private Paint paint;

   //对外提供注入数据的变量

   private float[] datas;

   //自定义view内部存储数据信息

   private List<Infos> listDatas = new ArrayList<>();

   //默认统计图的颜色配置 如果数据大于4 则颜色轮询

   private String colorRes[] = new String[]{"#fdb128", "#4a90e2", "#89c732", "#f46950"};

   private int mPanelWidth;

   public SelfStatistics(Context context) {

       super(context);

       init();

   }

   private void init() {

       paint = new Paint();

   }

   public SelfStatistics(Context context, AttributeSet attrs) {

       super(context, attrs);

       init();

   }

   public SelfStatistics(Context context, AttributeSet attrs, int defStyleAttr) {

       super(context, attrs, defStyleAttr);

       init();

   }

   @TargetApi(Build.VERSION_CODES.LOLLIPOP)

   public SelfStatistics(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {

       super(context, attrs, defStyleAttr, defStyleRes);

       init();

   }

   public float[] getDatas() {

       return datas;

   }

   public void startDraw() {

       invalidate();

   }

   public void setDatas(float[] datas) {

       this.datas = datas;

   }

   @Override

   protected void onDraw(Canvas canvas) {

       super.onDraw(canvas);

       if (datas != null && datas.length > 0) {

           calculateDatas();

           //获取圆心的x坐标

           int center = mPanelWidth / 2;

           //圆环的半径

           int radius = center - 10;

           //消除锯齿

           paint.setAntiAlias(true);

           //给外圈设置样式

           paint.setStyle(Paint.Style.FILL_AND_STROKE);

           //设置StrokeWidth

           paint.setStrokeWidth(20);

           //给外圈设置颜色

           paint.setColor(Color.WHITE);

           //画最外层的圈

           canvas.drawCircle(center, center, radius, paint);

           //设置进度的颜色

           for (Infos infos : listDatas) {

           //定义一个RectF类

               paint.setColor(Color.parseColor(infos.getColor()));

               RectF rectF = new RectF(center - radius, center - radius, center + radius, center + radius);

               //绘制扇形

               canvas.drawArc(rectF, infos.getStartAngle(), infos.getEndAngle(), true, paint);

           }

            //画最外层的圈

           paint.setColor(Color.WHITE);

           canvas.drawCircle(center, center, radius - 50, paint);

           drawTexts(canvas, center);

       }

   }

   @Override

   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

       int widthSize = MeasureSpec.getSize(widthMeasureSpec);

       int widthMode = MeasureSpec.getMode(widthMeasureSpec);

       int heightSize = MeasureSpec.getSize(heightMeasureSpec);

       int heightMode = MeasureSpec.getMode(heightMeasureSpec);

       int width = Math.min(widthSize, heightSize);

       if (widthMode == MeasureSpec.UNSPECIFIED) {

           width = heightSize;

       } else if (heightMode == MeasureSpec.UNSPECIFIED) {

           width = widthSize;

       }

       setMeasuredDimension(width, width);

   }

   @Override

   protected void onSizeChanged(int w, int h, int oldw, int oldh) {

       super.onSizeChanged(w, h, oldw, oldh);

       mPanelWidth = Math.min(w,h);

   }

   private void drawTexts(Canvas canvas, int center) {

       float total = 0;

       for (int i = 0; i < datas.length; i++) {

           total += datas[i];

       }

       String totalStr = total + "元";

       paint.setStrokeWidth(2);

       //设置进度扇形的样式

       paint.setStyle(Paint.Style.FILL);

       //设置文字的大小

       paint.setTextSize(35);

       int widthStr1 = (int) paint.measureText("总资产");

       int widthStr2 = (int) paint.measureText(totalStr);

       paint.setColor(Color.parseColor("#333333"));

       float baseX = center - widthStr1 / 2;

       float baseY = center + 20 / 4;

       Paint.FontMetrics fontMetrics = paint.getFontMetrics();

       float fontTotalHeight = fontMetrics.bottom - fontMetrics.top;

       float offY = fontTotalHeight / 2 - fontMetrics.bottom - 30;

       float newY = baseY + offY;

       canvas.drawText("总资产", baseX, newY, paint);

       paint.setColor(Color.parseColor("#fc561f"));

       float baseX1 = center - widthStr2 / 2;

       float baseY1 = center + 20 / 4;

       Paint.FontMetrics fontMetrics1 = paint.getFontMetrics();

       float fontTotalHeight1 = fontMetrics1.bottom - fontMetrics1.top;

       float offY1 = fontTotalHeight1 / 2 - fontMetrics1.bottom + 30;

       float newY1 = baseY1 + offY1;

       canvas.drawText(totalStr, baseX1, newY1, paint);

   }

   //为绘画做基本的计算

   private void calculateDatas() {

       float total = 0;

       float tempAngle = 270;

       //计算出总数

       for (int i = 0; i < datas.length; i++) {

           total += datas[i];

       }

       //创建不同的Infos对象

       Infos infos;

       for (int i = 0; i < datas.length; i++) {

           infos = new Infos();

           float currData = datas[i];

           float startAngle = tempAngle;

           float endAngle = (float) (currData * 100 / total * 3.6);

           infos.setStartAngle(startAngle);

           infos.setEndAngle(endAngle);

           infos.setColor(colorRes[i % colorRes.length]);

           tempAngle = endAngle + tempAngle;

           listDatas.add(infos);

       }

   }

   class Infos {

       private float startAngle;

       private float endAngle;

       private String color;

       public String getColor() {

           return color;

       }

       public void setColor(String color) {

           this.color = color;

       }

       public float getStartAngle() {

           return startAngle;

       }

       public void setStartAngle(float startAngle) {

           this.startAngle = startAngle;

       }

       public float getEndAngle() {

           return endAngle;

       }

       public void setEndAngle(float endAngle) {

           this.endAngle = endAngle;

       }

   }

}

最后提供使用的方法:

布局文件:activity_main.xml

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

   xmlns:tools="http://schemas.android.com/tools"

   android:layout_width="match_parent"

   android:layout_height="match_parent"

   tools:context="com.cretin.testprogress.MainActivity">

   <com.cretin.testprogress.views.SelfStatistics

       android:id="@+id/progress"

       android:layout_width="wrap_content"

       android:layout_height="wrap_content" />

</RelativeLayout>

主函数的调用:

package com.cretin.testprogress;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import com.cretin.testprogress.views.SelfStatistics;

public class MainActivity extends AppCompatActivity {

   private SelfStatistics selfStatistics;

   @Override

   protected void onCreate(Bundle savedInstanceState) {

       super.onCreate(savedInstanceState);

       setContentView(R.layout.activity_main);

       selfStatistics = (SelfStatistics) findViewById(R.id.progress);

       float datas[] = new float[]{4000,3000,7000,8000};

       selfStatistics.setDatas(datas);

       selfStatistics.startDraw();

   }

}

最后我写了一个demo,欢迎下载,重在分享,不要积分哦,哈哈

下载地址为:http://download.csdn.net/detail/u010998327/9557747
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息