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

来源:互联网 发布:金融公司网络推广 编辑:程序博客网 时间:2024/04/30 02:28

图片

前言:看了很多鸿洋的文章,感觉受益匪浅,正巧 今天在android聊天群里看到有这个需求,发现和鸿洋的这篇博客(http://blog.csdn.net/lmj623565791/article/details/24500107)很类似,正好我项目也不忙,我就自己实现了一下。

前期分析:外面的圆环就是根据比例把圆弧画出来就可以了,里边的文字和图片,刚看时我是想也画出来,但是后来考虑如果里边的东西以后改变了,修改起来也是很麻烦的,于是我就改成勇相对布局嵌套一下,我想这样也是更好实现,扩展性也比较好。

一,首先分析一下这个图

这个图外边圆环中圆弧的比例需要传递过来,颜色也需要指定,和外环的宽度也要指定,比例和颜色应该用集合的形式传递,而圆环的宽度可以用自定义属性。

-----------------------------------------------------------------------------------------------------

1.自定义属性

<resources>    <attr name="strokeWidth" format="dimension" />    <declare-styleable name="RoundChatView">        <attr name="strokeWidth" />    </declare-styleable></resources>

2.获取我们自定义的属性

TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.RoundChatView, defStyleAttr, 0);int n = a.getIndexCount();for (int i = 0; i < n; i++) {    int attr = a.getIndex(i);    switch (attr) {        case R.styleable.RoundChatView_strokeWidth:  // 圆环宽度            mStrokeWidth = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(                    TypedValue.COMPLEX_UNIT_PX, 20, getResources().getDisplayMetrics()));            break;    }}

3.重写onDraw()方法

@Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    mWidth = getWidth();    mPaint.setColor(Color.RED);    mPaint.setStyle(Paint.Style.STROKE);    mPaint.setStrokeWidth(mStrokeWidth); // 设置圆环的宽度    int centre = mWidth / 2; // 获取圆心的x坐标    int radius = centre - mStrokeWidth / 2;// 半径    RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius); // 用于定义的圆弧的形状和大小的界限    // 画圆环    for (int i = 0; i < mCount; i++) {        float degree = mDegree.get(i);        lastDegree += degree;        mPaint.setColor(i > mColor.length ? mColor[i - mColor.length] : mColor[i]);  // 循环取颜色值        canvas.drawArc(oval, -90 - lastDegree, degree, false, mPaint); // 根据角度画圆弧    }}

4.在布局中使用

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:custom="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.aijie.viewandgroupapp.MainActivity">    <com.aijie.viewandgroupapp.view.RoundChatView        android:id="@+id/roundChat"        android:layout_width="300dp"        android:layout_height="300dp"        android:layout_centerInParent="true"        custom:strokeWidth="50dp" />    <LinearLayout        android:layout_width="150dp"        android:layout_height="150dp"        android:layout_centerInParent="true"        android:gravity="center_horizontal"        android:orientation="vertical">        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginTop="20dp"            android:text="总支出"            android:textColor="#666666"            android:textSize="17sp" />        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginTop="20dp"            android:text="12120.00"            android:textColor="#666666"            android:textSize="26sp"            android:textStyle="bold" />        <ImageView            android:layout_width="30dp"            android:layout_height="30dp"            android:layout_marginTop="25dp"            android:src="@drawable/icon_center" />    </LinearLayout></RelativeLayout>

5.在代码中设置

@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    act = this;    roundChat = (RoundChatView) findViewById(R.id.roundChat);    List<Float> ratioList = new ArrayList<Float>();    ratioList.add(0.2f);    ratioList.add(0.1f);    ratioList.add(0.35f);    ratioList.add(0.2f);    ratioList.add(0.15f);    // 设置饼状图的比例    roundChat.setCount(5, ratioList);}

6.最终效果图



基本实现效果,具体的颜色控制可以再优化。

这个附上这个自定义控件的源码:

package com.aijie.viewandgroupapp.view;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.RectF;import android.util.AttributeSet;import android.util.Log;import android.util.TypedValue;import android.view.View;import com.aijie.viewandgroupapp.R;import java.util.ArrayList;import java.util.List;/** * Created by Administrator on 2016/7/8 0008. * 饼状图 */public class RoundChatView extends View {    private Context mContext;    /**     * 控件的宽度     */    private int mWidth;    /**     * 圆环的宽度     */    private int mStrokeWidth;    /**     * 画笔     */    private Paint mPaint;    /**     * 一共多少份     */    private int mCount = 0;    /**     * 每份所占的比例     */    private List<Float> mList = new ArrayList<Float>();    /**     * 饼状图每块的颜色     */    private int[] mColor = {Color.RED, Color.BLUE, Color.YELLOW, Color.GREEN, Color.BLUE};    /**     * 存储没份所占的角度     */    private List<Float> mDegree = new ArrayList<>();    public RoundChatView(Context context) {        this(context, null);    }    public RoundChatView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public RoundChatView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        mContext = context;        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        // 获取自定义的属性        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.RoundChatView, defStyleAttr, 0);        int n = a.getIndexCount();        for (int i = 0; i < n; i++) {            int attr = a.getIndex(i);            switch (attr) {                case R.styleable.RoundChatView_strokeWidth:  // 圆环宽度                    mStrokeWidth = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(                            TypedValue.COMPLEX_UNIT_PX, 20, getResources().getDisplayMetrics()));                    break;            }        }    }    private void initData(Context context) {        // 计算角度        if (mList.size() > 0) {            for (int i = 0; i < mList.size(); i++) {                Float ratio = mList.get(i);                Float degree = 360 * ratio;                mDegree.add(degree);            }        }    }    /**     * 设置份数和所占比例     *     * @param count     * @param list     */    public void setCount(int count, List<Float> list) {        this.mCount = count;        this.mList = list;        initData(mContext);    }    private int lastDegree = 0;  //已经画过的角度    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        mWidth = getWidth();        mPaint.setColor(Color.RED);        mPaint.setStyle(Paint.Style.STROKE);        mPaint.setStrokeWidth(mStrokeWidth); // 设置圆环的宽度        int centre = mWidth / 2; // 获取圆心的x坐标        int radius = centre - mStrokeWidth / 2;// 半径        RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius); // 用于定义的圆弧的形状和大小的界限        // 画圆环        for (int i = 0; i < mCount; i++) {            float degree = mDegree.get(i);            Log.i("aijie", "角度==" + degree);            lastDegree += degree;            mPaint.setColor(i > mColor.length ? mColor[i - mColor.length] : mColor[i]);  // 循环取颜色值            canvas.drawArc(oval, -90 - lastDegree, degree, false, mPaint); // 根据角度画圆弧        }    }}

0 0
原创粉丝点击