自定义View控件之特殊的饼形图(环形图)
来源:互联网 发布:电脑网络受限制怎么办 编辑:程序博客网 时间:2024/06/10 12:14
2015/07/27最近因为项目需要写一个环形图,可以表示所占比例也可以表示进度,于是自己画了一个,觉得蛮有意思的,分享出来给大家看看。
1, 一共六个环形,每个颜色,弧度不同,
2, 在每个环形上,根据其环的弧度不同,在弧的中心点上,伸出线,在线上显示相应的数值
3, 在线的结尾处,显示一个圆角方形,内部是其百分比。
一般在画环形时,我们都是采用画圈,然后设置其style为空心,给StrokeWidth一个值,用它来设置环的宽,可是这里有一个问题,在设置完宽之后,它的这个宽是在边为1的情况下,向内外扩展。说简单一点,就是如果我们要画一个半径为100的环,如果你把StrokeWidth设成20,你会发现,最后画出来的,是一个半径为110的环。在这种情况下,我们在画环上线的时候,算其长度会有麻烦。
我采用了一个比较笨的方法,就是画一个实心圆,然后再画一个半径减去环宽的小圆,这样就达到了圆环的效果。这样还有一个好处是,中心的圆的颜色也可以自定义了。
这里其实最麻烦的是算环形的半径,这里我一直也没有想好有什么太好的方法,我的方法比较笨,就是取控件的高度一半,然后再减去一个值,因为我认为,这个控件是一个宽大于高的控件,因为左右会有伸出的线吗,所以相当来说,高就是比较小的哪个值,所以还要减一个值,是因为要给线上的值,留一个空位出来,看一下效果图,就明白什么意思了。
这里我采用了三角函数进行计算弧的中心点,然后根据它的不同位置进行画线,这里无非就是八种情况,向右上折,向右全直,向右下折,垂直向下然后右直,重直向下左直,向左上折,向左全直,向左下折。而直线的长度,我是根据线上的文字的长度来确定,然后左右各留出10的宽度.
这一步就比较简单了,采用drawRoundRect就可以很轻松的完成。
package com.example.cg.customcirclepre.custom;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Rect;import android.graphics.RectF;import android.util.AttributeSet;import android.util.TypedValue;import android.view.View;import com.example.cg.customcirclepre.R;import java.text.DecimalFormat;/** * 自定义的一个特殊饼状图 * 作者:David Wang * 时间:2017/7/1 0006 上午 10:38 */public class MyCustomCirpre extends View { private float iBNum = 150; //流入大单数 private int iBColor = Color.parseColor("#EE755C"); //流入大单颜色 private float iMNum = 200; //流入中单数 private int iMColor = Color.parseColor("#D7583E"); //流入中单颜色 private float iSNum = 180; //流入小单数 private int iSColor = Color.parseColor("#C73F23"); //流入小单颜色 private float oBNum = 660; //流出大单数 private int oBColor = Color.parseColor("#25D98E"); //流出大单颜色 private float oMNum = 210; //流出中单数 private int oMColor = Color.parseColor("#2EBA80"); //流出中单颜色 private float oSNum = 195; //流出小单数 private int oSColor = Color.parseColor("#1D8057"); //流出小单颜色 private int StrokeWidth = 120; //弧的宽度 private int TextSize = 30; //文字大小 private Paint mPaint; private RectF mRectf; private Rect mBound; private String txtNumPre; float[] point; //记录弧度最外边中心点的坐标 private int adjustDist = 10; //在弧度上面的线,为了调整其最好的显示位置设置一个调整的距离数 private float txtBeginX = 0; //线上文字开始的位置的X坐标值 private float txtBeginY = 0; //线上文字开始的位置的y坐标值 private float txtEndX =0; //线上文字结束的位置的x坐标值 public MyCustomCirpre(Context context) { this(context,null); } public MyCustomCirpre(Context context, AttributeSet attrs) { this(context, attrs,0); } public MyCustomCirpre(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray array = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.MyPre, defStyleAttr, 0); int n = array.getIndexCount(); for(int i=0;i<n;i++) { int arr = array.getIndex(i); switch (arr) { case R.styleable.MyPre_iBNum: iBNum = array.getFloat(arr,0); break; case R.styleable.MyPre_iBColor: iBColor = array.getColor(arr,Color.parseColor("#EE755C")); break; case R.styleable.MyPre_iMNum: iMNum = array.getFloat(arr,0); break; case R.styleable.MyPre_iMColor: iMColor = array.getColor(arr,Color.parseColor("#D7583E")); break; case R.styleable.MyPre_iSNum: iSNum = array.getFloat(arr,0); break; case R.styleable.MyPre_iSColor: iSColor = array.getColor(arr,Color.parseColor("#C73F23")); break; case R.styleable.MyPre_oBNum: oBNum = array.getFloat(arr,0); break; case R.styleable.MyPre_oBColor: oBColor = array.getColor(arr,Color.parseColor("#25D98E")); break; case R.styleable.MyPre_oMNum: oMNum = array.getFloat(arr,0); break; case R.styleable.MyPre_oMColor: oMColor = array.getColor(arr,Color.parseColor("#2EBA80")); break; case R.styleable.MyPre_oSNum: oSNum = array.getFloat(arr,0); break; case R.styleable.MyPre_oSColor: oSColor = array.getColor(arr,Color.parseColor("#1D8057")); break; case R.styleable.MyPre_StrokeWidth: StrokeWidth = array.getInt(arr,200); break; case R.styleable.MyPre_textSize: TextSize = array.getDimensionPixelSize(arr, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 12, getResources().getDisplayMetrics())); break; } } array.recycle(); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setStrokeWidth(5); mPaint.setStyle(Paint.Style.FILL); mRectf = new RectF(); mBound = new Rect(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int width ; int height ; if(widthMode==MeasureSpec.EXACTLY) { width = widthSize; }else { width = getPaddingLeft() + getWidth() + getPaddingRight(); } if(heightMode==MeasureSpec.EXACTLY) { height = heightSize; }else { height = getPaddingTop() + getHeight() + getPaddingBottom(); } setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); float radius; //定义半径 float left; float top; float right; float bottom; radius = getHeight()/2 - 80; left = getWidth()/2 - radius ; top = getHeight()/2 -radius ; right = getWidth()/2 + radius; bottom = getHeight()/2 + radius; mRectf.set(left, top, right, bottom); //计算总数 float sum = oBNum + oMNum + oSNum + iBNum + iMNum + iSNum; //计算六个值的百分比 float oBpre = oBNum / sum; float oMpre = oMNum / sum; float oSpre = oSNum / sum; float iBpre = iBNum / sum; float iMpre = iMNum / sum; float iSpre = iSNum / sum; //计算六个值所占圆的弧度数 float oBArc = oBpre * 360; float oMArc = oMpre * 360; float oSArc = oSpre * 360; float iBArc = iBpre * 360; float iMArc = iMpre * 360; float iSArc = iSpre * 360; /** * 画出六个扇面 */ mPaint.setColor(oBColor); canvas.drawArc(mRectf, 270, oBArc, true, mPaint); mPaint.setColor(oMColor); canvas.drawArc(mRectf, 270 + oBArc, oMArc, true, mPaint); mPaint.setColor(oSColor); canvas.drawArc(mRectf, 270 + oBArc + oMArc, oSArc, true, mPaint); mPaint.setColor(iSColor); canvas.drawArc(mRectf, 270 + oBArc + oMArc + oSArc, iSArc, true, mPaint); mPaint.setColor(iMColor); canvas.drawArc(mRectf, 270 + oBArc + oMArc + oSArc + iSArc, iMArc, true, mPaint); mPaint.setColor(iBColor); canvas.drawArc(mRectf, 270 + oBArc + oMArc + oSArc + iSArc + iMArc, iBArc, true, mPaint); /** * 画出中间的空白区域 */ mPaint.setColor(Color.parseColor("#ffffff")); canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius - StrokeWidth, mPaint);// DrawOB(canvas, radius, oBArc, oBpre);//// DrawOM(canvas, radius, oBArc, oMArc, oMpre);//// DrawOS(canvas, radius, oBArc + oMArc, oSArc, oSpre);//// DrawIS(canvas, radius, oBArc + oMArc + oSArc, iSArc, iSpre);//// DrawIM(canvas, radius, oBArc + oMArc + oSArc + iSArc, iMArc, iMpre);//// DrawIB(canvas,radius,oBArc + oMArc + oSArc + iSArc + iMArc,0,0); } /** * 格式化显示的百分比 * @param proValue 传入的数值一般是0.1234这种格式的 * @return 返回一个小数点后一位的百分比字符串 */ private String getProValText(float proValue) { DecimalFormat format = new DecimalFormat("#0.0"); return format.format(proValue * 100) + "%"; } public void setNum(float oBNum,float oMNum, float oSNum,float iBNum,float iMNum,float iSNum) { this.oBNum = oBNum; this.oMNum = oMNum; this.oSNum = oSNum; this.iBNum = iBNum; this.iMNum = iMNum; this.iSNum = iSNum; postInvalidate(); }}
源代码:AnnulusCirclePre.zip
- 自定义View控件之特殊的饼形图(环形图)
- 自定义View控件之特殊的饼形图(环形图)
- Android自定义view之环形等待控件的实现
- Android开发——自定义view之环形等待控件的实现
- 自定义View 特殊形状控件
- Android自定义View之实现环形进度条
- android 自定义view之简易环形进度条
- 自定义view之环形进度条加数字
- 自定义view-环形进度条
- 自定义view-环形进度条
- 自定义View环形递增
- 自定义View实现环形SeekBar
- 自定义View实现环形SeekBar
- 自定义控件之 继承 View
- 自定义View之组合控件
- 自定义View之组合控件
- 自定义View之组合控件
- 自定义view之继承控件
- extundelete工具恢复误删文件
- 50 Pow(x, n)
- 动态代理和静态代理
- mysql装完计算机管理里面没mysql服务怎么解决
- Disruptor入门
- 自定义View控件之特殊的饼形图(环形图)
- EBCO技术
- spark基础
- 如何在SVN上面添加一个新项目
- 【前端JQuery】回调获取json中包含换行符出现问题解决
- 12.6-全栈Java笔记:Java网络编程(四)
- C#WINFORM里如何调用WEB Service API
- 国家对虚拟货币的态度,真的是坐视不管?
- 性能测试的步骤