項目中需要實現一個一級傭金以及二級傭金的比例示意圖。看下設計稿 
一、分析
一開始分析的是,先繪制完圓環,然后再去找到各自圓環的中心點,進行做切線,做中垂線出來繪制折線,然后繪制傭金比例以及顯示。后面發現這么計算太麻煩了。索性就定死那個兩個折線圖以及比例顯示。大概的思路如下圖。會進行一系列簡化。

1、簡化點,把折線顯示部分設置成了固定,然后圓環在動。 2、因為我們使用canvas繪制圓環或者圓的時候,其實是在一個矩形區域中繪制的,所以我們簡化了折線那一部分,就是圓距離矩形左下(右上)角的距離,然后水平方向就是raduis的長度,半徑長度。 3、可以看到設計稿紙上我們有一個圓弧之間的一個間距,與底色相同顏色為了區分兩個圓環。這里可以采用繪制完圓環后在上層重新繪制那調白線,那就需要計算各點坐標繪制兩條折線,我后面一想,還可以采用在同一個rectf區域中覆蓋一個相同半徑的空心圓環,ok,頓時沒有了難點有木有。實心嵌套空心圓環實現兩個圓環之間的
4、看下我實現的最終效果圖

二、計算各點坐標 注意,我們的坐標是重左上角開始的。。。往下或者往右走 這里再繼續解釋下,繪制圓弧的角度問題吧(順時針旋轉)如下圖

三、實現功能代碼
1、attr文件中的自定義屬性
<!--圓環餅圖--> <declare-styleable name="CircleChart"> <attr name="mRaduis" format="dimension" /> <attr name="mFirstPoint" format="float" /> <attr name="mLinewith" format="dimension" /> <attr name="mLineColor" format="color" /> <attr name="mFirstPointColor" format="color" /> <attr name="mSecondPointColor" format="color" /> <attr name="mPointTextsize" format="dimension" /> <attr name="mStokeColor" format="color" /> <attr name="mTextColor" format="color" /> </declare-styleable>2、自定義餅圖控件:CircleChart.java
package com.xx.xx.widget;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.TypedValue;import android.widget.TextView;import com.coofond.carservices.R;/** * @description: 我的分享餅圖 * @Author zsj on 2017/2/21 15:24. */public class CircleChart extends TextView { /** * 餅圖半徑 */ PRivate int mRaduis; /** * 一級傭金顏色 */ private int mFirstPointColor; /** * 二級傭金顏色 */ private int mSecondPointColor; /** * 第一傭金比例 */ private float mFirstPoint; /** * 餅圖上的字體大小 */ private int mPointTextSize; /** * 線條寬度 */ private int mLineWith; /** * 線條顏色 */ private int mLineColor; /** * 填充的畫筆 */ private Paint mPaint; /** * 用來描邊的畫筆 */ private Paint mStokePaint; /** * 描邊顏色 */ private int mStokeColor; /** * 繪制文字的畫筆 */ private Paint mTextPaint; /** * 繪制文字的顏色 */ private int mTextColor; /** * @param mFirstPoint 設置第一傭金比例 */ public void setmFirstPoint(float mFirstPoint) { this.mFirstPoint = mFirstPoint; } public CircleChart(Context context) { this(context, null); } public CircleChart(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircleChart(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); /** * 獲取我們的自定義屬性 */ TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CircleChart, defStyleAttr, 0); int n = a.getIndexCount(); for (int i = 0; i < n; i++) { int attr = a.getIndex(i); switch (attr) { case R.styleable.CircleChart_mRaduis: mRaduis = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics())); break; case R.styleable.CircleChart_mFirstPoint: mFirstPoint = a.getFloat(attr, 50); break; case R.styleable.CircleChart_mLinewith: mLineWith = a.getDimensionPixelOffset(attr, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics())); break; case R.styleable.CircleChart_mLineColor: mLineColor = a.getColor(attr, Color.BLACK); break; case R.styleable.CircleChart_mFirstPointColor: mFirstPointColor = a.getColor(attr, Color.BLUE); break; case R.styleable.CircleChart_mSecondPointColor: mSecondPointColor = a.getColor(attr, Color.RED); break; case R.styleable.CircleChart_mPointTextsize: mPointTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 12, getResources().getDisplayMetrics())); break; case R.styleable.CircleChart_mStokeColor: mStokeColor = a.getColor(attr, Color.WHITE); break; case R.styleable.CircleChart_mTextColor: mTextColor = a.getColor(attr, Color.BLACK); break; } } a.recycle(); //初始化paint mPaint = new Paint(); mStokePaint = new Paint(); mTextPaint = new Paint(); } @Override protected void onDraw(Canvas canvas) { mPaint.setAntiAlias(true);//消除鋸齒 mStokePaint.setAntiAlias(true);//消除鋸齒 mTextPaint.setAntiAlias(true);//消除鋸齒 mStokePaint.setStyle(Paint.Style.STROKE); mStokePaint.setStrokeWidth(mLineWith / 2); mPaint.setStyle(Paint.Style.FILL); mPaint.setColor(mFirstPointColor); mStokePaint.setColor(mStokeColor); RectF oval = new RectF(mRaduis, mRaduis, mRaduis * 3, mRaduis * 3); //繪制實心圓弧 canvas.drawArc(oval, 135 - (mFirstPoint / 100 * 360) / 2, (mFirstPoint / 100 * 360), true, mPaint); //繪制與底色相同的圓環 canvas.drawArc(oval, 135 - (mFirstPoint / 100 * 360) / 2, (mFirstPoint / 100 * 360), true, mStokePaint); mPaint.setColor(mSecondPointColor); //繪制實心圓弧 canvas.drawArc(oval, 315 - (360 - mFirstPoint / 100 * 360) / 2, (360 - mFirstPoint / 100 * 360), true, mPaint); //繪制與底色相同的圓環 canvas.drawArc(oval, 315 - (360 - mFirstPoint / 100 * 360) / 2, (360 - mFirstPoint / 100 * 360), true, mStokePaint); mTextPaint.setColor(mTextColor); mTextPaint.setStyle(Paint.Style.FILL); mTextPaint.setStrokeWidth(1); //繪制折線 canvas.drawLine((float) (1 - Math.sqrt(2) / 2) * mRaduis + mRaduis, (float) (1 + Math.sqrt(2) / 2) * mRaduis + mRaduis, mRaduis, 3 * mRaduis, mTextPaint); canvas.drawLine(mRaduis, 2 * mRaduis + mRaduis, 0, 3 * mRaduis, mTextPaint); canvas.drawLine((float) (2 + Math.sqrt(2) / 2) * mRaduis, (float) (2 * mRaduis - Math.sqrt(2) / 2 * mRaduis), 3 * mRaduis, mRaduis, mTextPaint); canvas.drawLine(3 * mRaduis, mRaduis, 4 * mRaduis, mRaduis, mTextPaint); //繪制文字 mTextPaint.setColor(mTextColor); mTextPaint.setTextSize(mPointTextSize); canvas.drawText("一級傭金", 0, 3 * mRaduis - mRaduis / 20, mTextPaint); canvas.drawText("二級傭金", 4 * mRaduis - mTextPaint.measureText("二級傭金"), mRaduis - mRaduis / 20, mTextPaint); mTextPaint.setColor(mFirstPointColor); canvas.drawText((int) mFirstPoint + "%", 0, 3 * mRaduis + mRaduis / 20 + mPointTextSize, mTextPaint); mTextPaint.setColor(mSecondPointColor); canvas.drawText((int) (100 - mFirstPoint) + "%", 4 * mRaduis - mTextPaint.measureText("75%"), mRaduis + mRaduis / 20 + mPointTextSize, mTextPaint); }}3、xml文件引用
<com.xx.xx.widget.CircleChart android:id="@+id/cir_point" android:layout_width="240dp" android:layout_height="200dp" android:layout_gravity="center" android:layout_marginBottom="20px" android:layout_marginTop="-80px" app:mFirstPoint="10" app:mFirstPointColor="@color/textorange" app:mLinewith="5dp" app:mPointTextsize="14sp" app:mRaduis="60dp" app:mSecondPointColor="@color/orange" app:mStokeColor="@color/activitycolor" app:mTextColor="@color/textcolordark" />4、activity中調用
cirPoint.setmFirstPoint(60);//獲取這個控件直接set...就這么簡單源代碼:https://github.com/TrebleZ/circletest
CSDN下載地址:http://download.csdn.net/detail/z_zt_t/9766113
新聞熱點
疑難解答