Android 自定义圆环比例图

阅读: 评论:0

Android 自定义圆环比例图

Android 自定义圆环比例图

最近公司要做一个效果,按照比例显示资金数

具体思路:根据一组数据计算出每个数据所占比例,再根据比例画出不同角度的圆弧

具体步骤:

  • 重写构造方法,获取自定义属性,初始化画笔Paint
  • 重写onMeasure方法,测量控件的宽高
  • 重写onDraw方法,画出圆弧和中间的文字 

重写构造方法,获取自定义属性,初始化画笔Paint

    1.自定义属性

    

 <declare-styleable name="RoundRateView"><attr name="rrv_circleWidth" format="dimension" /><attr name="rrv_intervalColor" format="color" /><attr name="rrv_aboveTextColor" format="color" /><attr name="rrv_belowTextColor" format="color" /><attr name="rrv_intervalAngle" format="dimension" /><attr name="rrv_belowTextSize" format="dimension" /><attr name="rrv_aboveTextSize" format="dimension" /><attr name="rrv_isShowText" format="boolean" /></declare-styleable>
    2.重写构造方法
public RoundRateView(Context context) {super(context);init(context, null, 0);}public RoundRateView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init(context, attrs, 0);}public RoundRateView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context, attrs, defStyleAttr);}private void init(Context context, AttributeSet attrs, int defStyleAttr) {TypedArray array = Theme().obtainStyledAttributes(attrs, R.styleable.RoundRateView, defStyleAttr, 0);int n = IndexCount();//自定义属性个数for (int i = 0; i < n; i++) {int attr = Index(i);//通过索引获取具体属性switch (attr) {case R.styleable.RoundRateView_rrv_circleWidth:mCircleWidth = DimensionPixelSize(attr, (int) dip2px(20f));if (mCircleWidth < 2) {mCircleWidth = 2;//最小宽度是2}break;case R.styleable.RoundRateView_rrv_intervalAngle:intervalAngle = DimensionPixelSize(attr, (int) dip2px(4f));break;case R.styleable.RoundRateView_rrv_aboveTextSize:aboveTextSize = DimensionPixelSize(attr, (int) dip2px(60));break;case R.styleable.RoundRateView_rrv_belowTextSize:belowTextSize = DimensionPixelSize(attr, (int) dip2px(40));break;case R.styleable.RoundRateView_rrv_intervalColor:intervalColor = Color(attr, Color.GRAY);break;case R.styleable.RoundRateView_rrv_aboveTextColor:aboveTextColor = Color(attr, Color.GRAY);break;case R.styleable.RoundRateView_rrv_belowTextColor:belowTextColor = Color(attr, Color.GRAY);break;case R.styleable.RoundRateView_rrv_isShowText:isShowText = Boolean(attr,true);break;}}le();//定义完后属性对象回mPaint = new Paint();  //创建画笔mPaint.setAntiAlias(true);  //设置绘制时抗锯齿mPaint.setStyle(Paint.Style.STROKE); //设置绘画空心(比如画圆时画的是空心圆而不是实心圆)mPaint.setStrokeWidth(mCircleWidth);//设置画笔线宽textPaint = new Paint();textPaint.setAntiAlias(true);textPaint.setDither(true);//        //这个是画矩形的画笔,方便大家理解这个圆弧
//        p = new Paint();
//        p.setStyle(Paint.Style.STROKE);
//        p.setColor(Color.RED);}

重写onMeasure方法,测量控件的宽高

  @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {Measure(widthMeasureSpec, heightMeasureSpec);int widthPixels = Resources().getDisplayMetrics().widthPixels;//获取屏幕宽int heightPixels = Resources().getDisplayMetrics().heightPixels;//获取屏幕高int width = Size(widthMeasureSpec);int hedight = Size(heightMeasureSpec);int minWidth = Math.min(widthPixels, width);//控件宽高不超过屏幕宽高int minHedight = Math.min(heightPixels, hedight);//控件宽高不超过屏幕宽高setMeasuredDimension(Math.min(minWidth, minHedight), Math.min(minWidth, minHedight));//设置宽高中的最小数为控件的实际宽高}

重写onDraw方法,画出圆弧和中间的文字

@Overrideprotected void onDraw(Canvas canvas) {Draw(canvas);drawCircle(canvas);if (isShowText) {//是否展示中间的文字drawText(canvas);}}/*** 画出圆弧* @param canvas*/private void drawCircle(Canvas canvas) {if (oval == null) {int min = Math.min(getWidth() - mCircleWidth / 2, getHeight() - mCircleWidth / 2);oval = new RectF(mCircleWidth / 2, mCircleWidth / 2,min, min);}float startAngle = -90f;//经过试验,-90这个值就是12点方向的位置//画一个底层圆环,颜色和间隙颜色一样,因为间隙的色块和其他色块之间会有小缝隙mPaint.setColor(intervalColor);mPaint.setStrokeWidth(mCircleWidth - 1); //宽度减1是防止底色溢出canvas.drawArc(oval, -90, 360, false, mPaint);mPaint.setStrokeWidth(mCircleWidth);for (int i = 0; i < angleList.size(); i++) {mPaint.(i));//设置画笔颜色if (i > 0) {startAngle += (i - 1);  //减1是因为总会有缝隙}canvas.drawArc(oval, startAngle, (i), false, mPaint);}}/*** 画出中间的文字* @param canvas 画布对象*/private void drawText(Canvas canvas) {int center = getWidth()/2;String percent ;if (isShowMoney) {if (allMoney>100000000) {try {double div = Arith.div(allMoney, 100000000d, 7);percent = div+"亿";} catch (IllegalAccessException e) {percent = "亿";e.printStackTrace();}}
//            else if (allMoney>10000) {
//                try {
//                    double div = Arith.div(allMoney, 10000d, 7);
//                    percent = div+"万";
//                } catch (IllegalAccessException e) {
//                    percent = "万";
//                    e.printStackTrace();
//                }
//
//            }else{percent = String.valueOf(allMoney);}}else{percent = "****";}textPaint.setTextSize(aboveTextSize);//防止文字边界超过内环边界  上面的文字大小减小 下面的文字大小也跟着减小while (asureText(percent)>getWidth()-2f*mCircleWidth) {aboveTextSize--;belowTextSize--;textPaint.setTextSize(aboveTextSize);}textPaint.setTextAlign(Paint.Align.CENTER); // 设置文字居中,文字的x坐标要注意textPaint.setColor(aboveTextColor); // 设置文字颜色textPaint.setStrokeWidth(0); // 注意此处一定要重新设置宽度为0,否则绘制的文字会重叠Rect bounds = new Rect(); // 文字边框TextBounds(percent, 0, percent.length(), bounds); // 获得绘制文字的边界矩形Paint.FontMetricsInt fontMetrics = FontMetricsInt(); // 获取绘制Text时的四条线int baseline = center + (fontMetrics.bottom - p) / 2 - fontMetrics.bottom; // 计算文字的基线,方法见.drawText(percent, center, baseline, textPaint); // 绘制文字percent = "总资产(元)";textPaint.setColor(belowTextColor); // 设置文字颜色textPaint.setTextSize(belowTextSize);//防止下面的文字超出内环边界while (asureText(percent)>getWidth()-2f*mCircleWidth) {belowTextSize--;textPaint.setTextSize(belowTextSize);}TextBounds(percent, 0, percent.length(), bounds); // 获得绘制文字的边界矩形Paint.FontMetricsInt fontMetrics1 = FontMetricsInt(); // 获取绘制Text时的四条线int baseline1 = center + (fontMetrics1.bottom - p) / 2 - fontMetrics.bottom+38*2;canvas.drawText(percent, center, baseline1, textPaint); // 绘制文字}

全部代码

t.Context;
t.res.Resources;
t.res.TypedArray;
aphics.Canvas;
aphics.Color;
aphics.Paint;
aphics.Rect;
aphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;import com.daodaojk.qhjf.R;
import com.daodaojk.qhjf.utils.Arith;
import com.daodaojk.qhjf.utils.CommonUtil;
import com.daodaojk.qhjf.utils.LogUtil;import java.util.ArrayList;
import java.util.List;public class RoundRateView extends View {private Paint mPaint;private int mCircleWidth; //圆环宽度private float intervalAngle = 4f;//间隔角度private int intervalColor = Color.GRAY;//间隔颜色 默认灰色private int aboveTextColor = Color.GRAY;//上面的文字 默认灰色private int belowTextColor = Color.GRAY;//下面的文字 默认灰色private int aboveTextSize = 60;//上面的文字字体大小private int belowTextSize = 40;//下面的文字字体大小private boolean isShowText = true; //是否显示中间文字 默认显示/*** 画文字的画笔*/private Paint textPaint;private int colors[] = {Color.parseColor("#41A8FF"), Color.parseColor("#86C8FF"), Color.parseColor("#FF8B13"), Color.parseColor("#FFB971"), Color.parseColor("#FF8A77"), Color.parseColor("#EEE685"), Color.parseColor("#EECBAD"), Color.parseColor("#EEAEEE"), Color.parseColor("#EE3B3B"), Color.parseColor("#EDEDED")};private List<Float> angleList = new ArrayList<>(); //所有的角度 集合private List<Integer> colorList = new ArrayList<>(); //所有的色值 集合private RectF oval;private double allMoney;private boolean isShowMoney = true; //是否是明文显示钱数,默认是明文显示//    private Paint p;public RoundRateView(Context context) {super(context);init(context, null, 0);}public RoundRateView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init(context, attrs, 0);}public RoundRateView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context, attrs, defStyleAttr);}private void init(Context context, AttributeSet attrs, int defStyleAttr) {TypedArray array = Theme().obtainStyledAttributes(attrs, R.styleable.RoundRateView, defStyleAttr, 0);int n = IndexCount();//自定义属性个数for (int i = 0; i < n; i++) {int attr = Index(i);//通过索引获取具体属性switch (attr) {case R.styleable.RoundRateView_rrv_circleWidth:mCircleWidth = DimensionPixelSize(attr, (int) dip2px(20f));if (mCircleWidth < 2) {mCircleWidth = 2;//最小宽度是2}break;case R.styleable.RoundRateView_rrv_intervalAngle:intervalAngle = DimensionPixelSize(attr, (int) dip2px(4f));break;case R.styleable.RoundRateView_rrv_aboveTextSize:aboveTextSize = DimensionPixelSize(attr, (int) dip2px(60));break;case R.styleable.RoundRateView_rrv_belowTextSize:belowTextSize = DimensionPixelSize(attr, (int) dip2px(40));break;case R.styleable.RoundRateView_rrv_intervalColor:intervalColor = Color(attr, Color.GRAY);break;case R.styleable.RoundRateView_rrv_aboveTextColor:aboveTextColor = Color(attr, Color.GRAY);break;case R.styleable.RoundRateView_rrv_belowTextColor:belowTextColor = Color(attr, Color.GRAY);break;case R.styleable.RoundRateView_rrv_isShowText:isShowText = Boolean(attr,true);break;}}le();//定义完后属性对象回mPaint = new Paint();  //创建画笔mPaint.setAntiAlias(true);  //设置绘制时抗锯齿mPaint.setStyle(Paint.Style.STROKE); //设置绘画空心(比如画圆时画的是空心圆而不是实心圆)mPaint.setStrokeWidth(mCircleWidth);//设置画笔线宽textPaint = new Paint();textPaint.setAntiAlias(true);textPaint.setDither(true);//        //这个是画矩形的画笔,方便大家理解这个圆弧
//        p = new Paint();
//        p.setStyle(Paint.Style.STROKE);
//        p.setColor(Color.RED);}/*** 设置数据列表* @param list*/public void setList(List<Double> list) {float allIntervalAngle = 0f ;//所有间隔加起来的角度float allModuleAngle;  //所有模块加起来的角度  allModuleAngle + allIntervalAngle=360;if (list.size() > colors.length) {return;}angleList.clear();colorList.clear();allMoney = 0d;for (int i = 0; i < list.size(); i++) {allMoney = Arith.add((i));}if (list.size() == 1) { //如果只有一条数据,就不要间隔angleList.add(360f);colorList.add(colors[0]);} else {for (int i = 0; i < list.size(); i++) {if ((i)!=0) {allIntervalAngle +=intervalAngle;}}if (allIntervalAngle==intervalAngle) {//如果只有一条数据不为0,就不要间隔颜色angleList.add(360f);colorList.add(colors[0]);}else{allModuleAngle = 360 - allIntervalAngle;float angle = 0;for (int i = 0; i < list.size(); i++) {if ((i)!=0) {float e = (float) ((i) / allMoney * allModuleAngle);if (i == list.size() - 1) {//如果是最后一个色块,所占角度就是剩余全部的角度this.angleList.add(allModuleAngle - angle);} else {angle += e;this.angleList.add(e);}this.angleList.add(intervalAngle);lorList.add(colors[i]);lorList.add(intervalColor);}}}}invalidate();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {Measure(widthMeasureSpec, heightMeasureSpec);int widthPixels = Resources().getDisplayMetrics().widthPixels;//获取屏幕宽int heightPixels = Resources().getDisplayMetrics().heightPixels;//获取屏幕高int width = Size(widthMeasureSpec);int hedight = Size(heightMeasureSpec);int minWidth = Math.min(widthPixels, width);int minHedight = Math.min(heightPixels, hedight);setMeasuredDimension(Math.min(minWidth, minHedight), Math.min(minWidth, minHedight));}public void setIsShowText(boolean isShowText) {this.isShowText = isShowText;invalidate();}@Overrideprotected void onDraw(Canvas canvas) {Draw(canvas);drawCircle(canvas);if (isShowText) {drawText(canvas);}}/*** 画出圆弧* @param canvas*/private void drawCircle(Canvas canvas) {if (oval == null) {int min = Math.min(getWidth() - mCircleWidth / 2, getHeight() - mCircleWidth / 2);oval = new RectF(mCircleWidth / 2, mCircleWidth / 2,min, min);}float startAngle = -90f;//经过试验,-90这个值就是12点方向的位置//画一个底层圆环,颜色和间隙颜色一样,因为间隙的色块和其他色块之间会有小缝隙mPaint.setColor(intervalColor);mPaint.setStrokeWidth(mCircleWidth - 1); //宽度减1是防止底色溢出canvas.drawArc(oval, -90, 360, false, mPaint);mPaint.setStrokeWidth(mCircleWidth);for (int i = 0; i < angleList.size(); i++) {mPaint.(i));//设置画笔颜色if (i > 0) {startAngle += (i - 1);  //减1是因为总会有缝隙}canvas.drawArc(oval, startAngle, (i), false, mPaint);}}/*** 画出中间的文字* @param canvas 画布对象*/private void drawText(Canvas canvas) {int center = getWidth()/2;String percent ;if (isShowMoney) {if (allMoney>100000000) {try {double div = Arith.div(allMoney, 100000000d, 7);percent = div+"亿";} catch (IllegalAccessException e) {percent = "亿";e.printStackTrace();}}
//            else if (allMoney>10000) {
//                try {
//                    double div = Arith.div(allMoney, 10000d, 7);
//                    percent = div+"万";
//                } catch (IllegalAccessException e) {
//                    percent = "万";
//                    e.printStackTrace();
//                }
//
//            }else{percent = CommonUtil.decimalFormatInt(allMoney);}}else{percent = "****";}textPaint.setTextSize(aboveTextSize);//防止文字边界超过内环边界  上面的文字大小减小 下面的文字大小也跟着减小while (asureText(percent)>getWidth()-2f*mCircleWidth) {aboveTextSize--;belowTextSize--;textPaint.setTextSize(aboveTextSize);}textPaint.setTextAlign(Paint.Align.CENTER); // 设置文字居中,文字的x坐标要注意textPaint.setColor(aboveTextColor); // 设置文字颜色textPaint.setStrokeWidth(0); // 注意此处一定要重新设置宽度为0,否则绘制的文字会重叠Rect bounds = new Rect(); // 文字边框TextBounds(percent, 0, percent.length(), bounds); // 获得绘制文字的边界矩形Paint.FontMetricsInt fontMetrics = FontMetricsInt(); // 获取绘制Text时的四条线int baseline = center + (fontMetrics.bottom - p) / 2 - fontMetrics.bottom; // 计算文字的基线,方法见.drawText(percent, center, baseline, textPaint); // 绘制文字percent = "总资产(元)";textPaint.setColor(belowTextColor); // 设置文字颜色textPaint.setTextSize(belowTextSize);//防止下面的文字超出内环边界while (asureText(percent)>getWidth()-2f*mCircleWidth) {belowTextSize--;textPaint.setTextSize(belowTextSize);}TextBounds(percent, 0, percent.length(), bounds); // 获得绘制文字的边界矩形Paint.FontMetricsInt fontMetrics1 = FontMetricsInt(); // 获取绘制Text时的四条线int baseline1 = center + (fontMetrics1.bottom - p) / 2 - fontMetrics.bottom+38*2;canvas.drawText(percent, center, baseline1, textPaint); // 绘制文字}public static int px2dip(int pxValue) {final float scale = System().getDisplayMetrics().density;return (int) (pxValue / scale + 0.5f);}public static float dip2px(float dipValue) {final float scale = System().getDisplayMetrics().density;return (dipValue * scale + 0.5f);}public void setIsShowMoney(boolean isShowMoney) {this.isShowMoney = isShowMoney;invalidate();}

控件使用

    1.xml文件:

 <application.view.RoundRateViewandroid:id="@+id/rrv_view"android:layout_width="170dp"android:layout_marginTop="50dp"android:layout_marginBottom="50dp"android:layout_height="170dp"app:rrv_circleWidth="17dp"app:rrv_aboveTextColor="@color/text_blue"app:rrv_belowTextColor="@color/colorAccent"app:rrv_aboveTextSize="19sp"app:rrv_belowTextSize="14sp"app:rrv_isShowText="true"app:rrv_intervalColor="#f6f6f6"android:layout_gravity="center_horizontal" />

    2.页面调用:

RoundRateView roundRateView = (RoundRateView) findViewById(v_view);
List<Double> floats = new ArrayList<>();
floats.add(400.08d);
floats.add(500d);
floats.add(600d);
floats.add(800d);
floats.add(1000d);
roundRateView.setList(floats);

最终效果:



参看文献: 

本文发布于:2024-02-02 11:10:16,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170684341743398.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:圆环   自定义   比例   Android
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23