项目中需要实现一个一级佣金以及二级佣金的比例示意图。看下设计稿
一、分析
一开始分析的是,先绘制完圆环,然后再去找到各自圆环的中心点,进行做切线,做中垂线出来绘制折线,然后绘制佣金比例以及显示。后面发现这么计算太麻烦了。索性就定死那个两个折线图以及比例显示。大概的思路如下图。会进行一系列简化。
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
新闻热点
疑难解答