![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2QvwVe0lmdhJ3ZvwFM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2LcZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DNwUDN1gzMyEDOwcDM2EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
前言:看了很多鴻洋的文章,感覺受益匪淺,正巧 今天在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); // 根據角度畫圓弧
}
}
}