前言:看了很多鸿洋的文章,感觉受益匪浅,正巧 今天在android聊天群里看到有这个需求,发现和鸿洋的这篇博客(http://blog.youkuaiyun.com/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); // 根据角度画圆弧 } } }