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

图片

前言:看了很多鸿洋的文章,感觉受益匪浅,正巧 今天在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()方法

@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);
        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.在代码中设置

@Override
protected 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); // 根据角度画圆弧
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值