自定义View之饼状图

原创 2016年08月28日 15:15:51

先展示下效果图:

这里写图片描述

接下来,我们将目标定义清楚:
目标是饼状图,那么,使用canvas画弧形是基础了。
既然是提供一个饼状图,那么,是需要自定义View的用户来使用的,就需要有数据的输入接口。
另外,还有View的属性,包括颜色以及View的大小(我用直径来表示)。

下面来具体实现:

1、自定义View的属性

在values下面新建一个attr.xml,现在里面定义我们的属性,

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

    <attr name="diameter" format="dimension" />
    <attr name="backColor" format="color" />
    <attr name="frontColor" format="color" />

    <declare-styleable name="PieChartView">
        <attr name="backColor" />
        <attr name="frontColor" />        
        <attr name="diameter" />
    </declare-styleable>

</resources>

2、在View的构造中获得属性

    public PieChartView(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);

        //获得我们所定义的自定义样式属性
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.PieChartView, defStyle, 0);
        int n = a.getIndexCount();
        for (int i = 0; i < n; i++)
        {
            int attr = a.getIndex(i);
            switch (attr)
            {
            case R.styleable.PieChartView_backColor:
                // 默认颜色设置为黑色
                mBackColor = a.getColor(attr, Color.BLACK);
                Log.i("view","mBackColor="+Integer.toHexString(mBackColor));
                break;
            case R.styleable.PieChartView_frontColor:
                // 默认颜色设置为黑色
                mFrontColor = a.getColor(attr, Color.BLACK);
                Log.i("view","mFrontColor="+Integer.toHexString(mFrontColor));
                break;
            case R.styleable.PieChartView_diameter:
                // 默认设置为40dp
                mDiameter = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
                        TypedValue.COMPLEX_UNIT_SP, 40, getResources().getDisplayMetrics()));
                break;  
            }
        }
        a.recycle();

        mPaint = new Paint();
        random = new Random();
        rect = new RectF();

        //支持用户点击,重新绘图
        this.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                postInvalidate();
            }
        }); 
    }

3、重写onMeasure

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        int width = 0;
        int height = 0;
        //设定直径的最小值
        if(mDiameter<40){
            mDiameter=40;
        }
        height=mDiameter;
        width=mDiameter;
        Log.i("view","w="+width+" h="+height);
        setMeasuredDimension(width, height);
    }

4、重写onDraw

    protected void onDraw(Canvas canvas)
    {
        mPaint.setColor(Color.YELLOW);
        int width = getMeasuredWidth();
        int height = getMeasuredHeight();

        //保证输入数据的有效性
        if(inputData==null){
            Log.i("view","inputData is null");
            return;
        }
        if((inputData.length==0)){
            Log.i("view","inputData is invalid: lenth=0");
            return; 
        }

        //将数据转换为角度
        int num=inputData.length;
        float[] angles=new float[num];
        int[] colors=new int[num];
        Double sum=0.0;
        for(int i=0;i<num;i++){
            sum+=inputData[i];
        }
        if(sum==0){
            Log.i("view","inputData is invalid: sum=0");
            return; 
        }
        float angleSum=0;
        for(int i=0;i<num;i++){
            angles[i]=(float)(inputData[i]*360/sum);
            angleSum+=angles[i];
            Log.i("view","angles["+i+"]="+angles[i]+" sum="+angleSum);
        }

        //产生随机颜色值
        int r,g,b;
        for(int i=0;i<num;i++){
            r=random.nextInt(256);
            g=random.nextInt(256);
            b=random.nextInt(256);
            colors[i]=Color.argb(255, r, g, b);
            Log.i("view","colors["+i+"]="+Integer.toHexString(colors[i]));
        }
        Log.i("view","mBackColor="+Integer.toHexString(mBackColor)+"mFrontColor="+Integer.toHexString(mFrontColor));
        mPaint.setColor(mFrontColor);

        //画出饼状图
        float startAngle=0;
        float sweepAngle=0;
        rect.set(0, 0, width, height);
        for(int i=0;i<num;i++){
            startAngle+=sweepAngle;
            sweepAngle=angles[i];
            mPaint.setColor(colors[i]);
            canvas.drawArc(rect, startAngle, sweepAngle, true, mPaint);     
        }       
    }

5、提供对外接口

这是一个很重要的对外接口,用于获取饼状图中各部分的原始数据:

    public Boolean setInputData(Double[] inputData1){       
        if(inputData1.length>0){
            this.inputData = new Double[inputData1.length];
            System.arraycopy(inputData1, 0, this.inputData, 0, inputData1.length);
            Log.i("view","inputData.length="+this.inputData.length);            
            return true;    
        } else {            
            return false;
        }
    }   

6、在布局文件中使用

在布局文件中我定义了5个view,中间一个大的,四角四个小的,这样效果比较炫:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:custom="http://schemas.android.com/apk/res/com.customview"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

     <com.customview.view.PieChartView
        android:id="@+id/pie_chart_view1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"        
        android:layout_centerHorizontal="true"  
        android:layout_centerVertical="true"          
        android:padding="10dp"
        custom:backColor="#ff203030"
        custom:frontColor="#ff60E0E0"      
        custom:diameter="200dp"      
        /> 

     <com.customview.view.PieChartView
        android:id="@+id/pie_chart_view2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@id/pie_chart_view1"
        android:layout_below="@id/pie_chart_view1"                   
        android:layout_centerHorizontal="true"
        android:padding="10dp"
        custom:backColor="#ff203030"
        custom:frontColor="#ff60E0E0"      
        custom:diameter="80dp"      
        /> 

     <com.customview.view.PieChartView
        android:id="@+id/pie_chart_view3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/pie_chart_view1"
        android:layout_below="@id/pie_chart_view1"                   
        android:layout_centerHorizontal="true"
        android:padding="10dp"
        custom:backColor="#ff203030"
        custom:frontColor="#ff60E0E0"      
        custom:diameter="80dp"      
        /> 

     <com.customview.view.PieChartView
        android:id="@+id/pie_chart_view4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@id/pie_chart_view1"
        android:layout_above="@id/pie_chart_view1"                   
        android:layout_centerHorizontal="true"
        android:padding="10dp"
        custom:backColor="#ff203030"
        custom:frontColor="#ff60E0E0"      
        custom:diameter="80dp"      
        /> 

     <com.customview.view.PieChartView
        android:id="@+id/pie_chart_view5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/pie_chart_view1"
        android:layout_above="@id/pie_chart_view1"                   
        android:layout_centerHorizontal="true"
        android:padding="10dp"
        custom:backColor="#ff203030"
        custom:frontColor="#ff60E0E0"      
        custom:diameter="80dp"      
        /> 

</RelativeLayout>

7、在activity中使用

主要是产生饼状图的原始数据,并送给自定义View来使用:

package com.customview;

import android.os.Bundle;
import android.util.Log;
import java.util.Random;
import com.customview.view.PieChartView;
import android.app.Activity;

public class MainActivity extends Activity
{
    PieChartView pie_chart_view1;
    PieChartView pie_chart_view2;
    PieChartView pie_chart_view3;
    PieChartView pie_chart_view4;
    PieChartView pie_chart_view5;

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

        pie_chart_view1 = (PieChartView)findViewById(R.id.pie_chart_view1);
        pie_chart_view2 = (PieChartView)findViewById(R.id.pie_chart_view2);
        pie_chart_view3 = (PieChartView)findViewById(R.id.pie_chart_view3);
        pie_chart_view4 = (PieChartView)findViewById(R.id.pie_chart_view4);
        pie_chart_view5 = (PieChartView)findViewById(R.id.pie_chart_view5);

        //产生随机数据,做为饼状图的输入
        Double[] inputData = new Double[6];
        Random random = new Random();
        for(int i=0;i<inputData.length;i++){
            inputData[i]=random.nextDouble()*30;
            Log.i("view", "log: inputData["+i+"]="+inputData[i]);
        }

        pie_chart_view1.setInputData(inputData);
        pie_chart_view2.setInputData(inputData);
        pie_chart_view3.setInputData(inputData);
        pie_chart_view4.setInputData(inputData);
        pie_chart_view5.setInputData(inputData);

    }

}

至此,完美收工。
这样就实现了一个自定义的饼状图,里面每一部分的颜色是随机生成的。同时,这个自定义View支持点击,每次点击,会重新执行onDraw,而在onDraw里面,又更新了颜色,所以,每次点击,会修改饼状图的颜色,效果杠杠滴!

完整代码见如下地址:

http://download.csdn.net/detail/lintax/9615083

参考:

http://m.blog.csdn.net/article/details?id=50556098

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

自定义控件(一) 一个比例饼状图

前言:看了很多鸿洋的文章,感觉受益匪浅,正巧 今天在android聊天群里看到有这个需求,发现和鸿洋的这篇博客(http://blog.csdn.net/lmj623565791/article/de...

Android 使用Canvas绘制饼图

效果: 嗯,一个很简单的饼图绘制。用法 可以在xml文件中配置,也可以直接new一个实例出来。 <com.paoword.oa.view.SectorGraphView an...

Android自定义View-绘制扇形实现圆形进度

先上图,这是要实现的效果,根据音量的大小中间的进度调节。麦克风部分是透明的,所以原理就是在蒙层的底部画白色的扇形。如下图所示 这样就能实现圆形像水瓮一样的进度。 实现方法: 通过Canv...

Android 自定义View画‘√’

Android 自定义View画’√‘

Android开发-自定义View-AndroidStudio(三)扇形多级菜单

转载请注明出处:http://blog.csdn.net/iwanghang/我正在参加CSDN 2016博客之星评选,希望得到您的宝贵一票~http://blog.csdn.net/vote/can...

Android自定义统计图(柱状图,折线图,饼状图)

最近由于项目需要,研究了一些统计图的做法,开始时,看了很多博文,大部分都是引用第三方的库,虽然简单,易上手,但是功能太死板,有很多要求都是不能满足的,所以经过研究,自己使用View中的canvas重新...

自定义view-饼图

效果图如下:                           看到上述view的效果,首先分析view有几部分组成,这里仅做练习,没有做适配。   &...

自定义View练习(一)饼状图

学习了自定义View后,练习一波,首先来看一下饼状图的效果 一步一步来,我们先理一下思路,自定义View的流程如下 而在圆饼图中,需要的步骤有: 步骤 关键字 作用 ...

Android自定义View之饼饼图

我们在设计图表的时候,有可能就会用到饼图。今天浏览网页无意发现了饼图,于是就想自己也设计一个,说干就干。以为很简单,还是有点费事,有想过放弃。但半途而废不是我的风格,就坚持写了下去。最后花了几个小时写...

Android绘制自定义饼状图

Android绘制自定义饼状图 效果 1.绘制圆环 草图 1. 创建自定义圆环对应的类package com.example.a01drawround.ui;import andro...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)