java环形图,Android 绘制 环形图

由于项目需要环形图,但是在 MPAndroidChart中没找到 环形图,所以就自己百度搜索总结。

如何你也在搞iOS ,请参考

环形图 - Swift

!无图无真相!效果图如下

53f993749c47

效果图

看图,分成左右两个部分,左边 环形图,右边是说明 百分比值等等,

我只绘制了左边,右边用View堆起来就好!

一 、分析需要哪些 数据

确定 中间的空白圆的半径 r

确定 环形的宽度 ringWidth

确定 环形之间的间距 ringSpace

确定 环形 个数 ringCount

其他颜色等

二、绘制及其计算

1、绘制 最里面的环形

绘制的中心点:即view的中心;

绘制的半径:空白圆的半径 r + 环形宽度 / 2

可以理解为:先用圆规画了一个圆线,然后用彩笔笔尖对准圆线进行涂写,就画出来了一个圆环。。。

2、绘制 中间的环形

绘制的中心点:即view的中心;

绘制的半径:空白圆的半径 r + 环形宽度 + 环形间距 + 环形宽度 / 2

3、绘制 最外层的环形

绘制的中心点:即view的中心;

绘制的半径:空白圆的半径 r + 环形宽度2 + 环形间距2 + 环形宽度 / 2

4、绘制中间的文本

绘制的中心点:即view的中心;

绘制文本的最大宽度:空白圆的半径 r

如何换行?

完整代码如下:

一共就 6 个文件, 只要copy到自己工程中去,修改 import 包就可以了

colors.xml

attrs.xml

环形类 LzRingChart.java

common_circle.xml

activity_main.xml

MainActivity.java

colors.xml

#00000000

#D81B60

#33a3dc

#111111

#333333

#666666

#999999

#99000000

#ffffff

#cfcfcf

#d8d8d8

#e5e5e5

#f5f5f5

#b64533

#c85d44

#f15a22

#cbc547

#fdb933

#e0861a

#bed742

#7fb80e

#77ac98

#50b7c1

#c77eb5

#6f60aa

attr.xml 文件

common_circle.xml

android:shape="oval" >

android:height="6dp"/>

环形图 LzRingChart.java

package com.lz.ui;

import android.content.Context;

import android.content.res.TypedArray;

import android.graphics.Canvas;

import android.graphics.Paint;

import android.graphics.Rect;

import android.graphics.RectF;

import android.text.Layout;

import android.text.StaticLayout;

import android.text.TextPaint;

import android.util.AttributeSet;

import android.view.View;

import androidx.annotation.Nullable;

import androidx.core.content.ContextCompat;

import com.lz.tool.DeviceTool;

import com.lz.wehome.R;

public class LzRingChart extends View {

//中间的半径, 环形的宽度,环形间距, 环形背景颜色,环形的数量

int innerRadius, ringWidth, ringSpace, ringBgColor, ringCount;

//环形画笔

Paint ringBgPaint;

//文本画笔

TextPaint textPaint;

Rect textRect;

RectF ringRectF;

//百分比 0.xxx

float[] values;

//环形百分比颜色

int[] colors;

CharSequence title;

private Context context;

public LzRingChart(Context context) {

this(context, null);

}

public LzRingChart(Context context, @Nullable AttributeSet attrs) {

this(context, attrs, 0);

}

public LzRingChart(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

this.context = context;

//读取xml中值

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.LzRingChart, defStyleAttr, 0);

innerRadius = typedArray.getDimensionPixelSize(R.styleable.LzRingChart_innerRadius, DeviceTool.dp2px(context, 50));

ringWidth = typedArray.getDimensionPixelSize(R.styleable.LzRingChart_ringWidth, DeviceTool.dp2px(context, 5));

ringSpace = typedArray.getDimensionPixelSize(R.styleable.LzRingChart_ringSpace, DeviceTool.dp2px(context, 5));

ringBgColor = typedArray.getColor(R.styleable.LzRingChart_ringBgColor, ContextCompat.getColor(context, R.color.line_d8));

ringCount = typedArray.getInt(R.styleable.LzRingChart_ringCount, 1);

typedArray.recycle();

initPaint();

}

/**

* 配置

*/

void initPaint() {

//绘制圆环

ringBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

ringBgPaint.setStyle(Paint.Style.STROKE);

ringBgPaint.setColor(ringBgColor);

ringBgPaint.setStrokeWidth(ringWidth);

textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);

textPaint.setStyle(Paint.Style.FILL_AND_STROKE);

textPaint.setColor(context.getResources().getColor(R.color.main));

textPaint.setTextSize(DeviceTool.dp2px(context, 13));

textRect = new Rect();

ringRectF = new RectF();

// invalidate();

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

//测量尺寸

setMeasuredDimension(measureView(widthMeasureSpec), measureView(heightMeasureSpec));

}

/**

* 测量尺寸

*/

private int measureView(int measureSpec) {

int result;

int specMode = MeasureSpec.getMode(measureSpec);

int specSize = MeasureSpec.getSize(measureSpec);

if(specMode == MeasureSpec.EXACTLY){

result = specSize;

/**

* 比较 xml设置的 View宽高 是否小于半径等

*/

int real = (innerRadius + ringSpace*(ringCount-1) + ringWidth*ringCount)*2;

if (real > specSize) {

result = real;

}

}else{

result = (innerRadius + ringSpace*(ringCount-1) + ringWidth*ringCount)*2;

if(specMode==MeasureSpec.AT_MOST){

result=Math.min(result,specSize);

}

}

return result;

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//绘制背景色圆环

drawBgRing(canvas);

//百分比圆环

drawPercentRing(canvas);

//中间文本

drawCenterText(canvas);

}

/**

* 绘制 环形中间的文本

*/

void drawCenterText(Canvas canvas) {

if (title==null) return;

StaticLayout sl = new StaticLayout(title, textPaint, innerRadius*2, Layout.Alignment.ALIGN_CENTER, 1.1f, 0, true);

canvas.translate(getWidth()/2-sl.getWidth()/2, getHeight()/2-sl.getHeight()/2);

sl.draw(canvas);

}

/**

* 绘制 默认颜色的环形

*/

void drawBgRing(Canvas canvas) {

//需要重新设置一下

ringBgPaint.setColor(ringBgColor);

for (int i = 0; i < ringCount; i++) {

float letf = getWidth()/2 - innerRadius - ringWidth*(ringCount-i) - (ringCount-1-i)*ringSpace + ringWidth/2;

float top = getHeight()/2 - innerRadius - ringWidth*(ringCount-i) - (ringCount-1-i)*ringSpace + ringWidth/2;

float right = getWidth()/2 + innerRadius + ringWidth*(ringCount-i) + (ringCount-1-i)*ringSpace - ringWidth/2;

float bottom = getHeight()/2 + innerRadius + ringWidth*(ringCount-i) + (ringCount-1-i)*ringSpace - ringWidth/2;

ringRectF.set(letf, top, right, bottom);

canvas.drawArc(ringRectF, 0, 360,false, ringBgPaint);

}

}

/**

* 绘制百分比的环形

*/

void drawPercentRing(Canvas canvas) {

if (values == null || values.length ==0) return;

for (int i = 0; i < values.length; i++) {

ringBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

ringBgPaint.setStyle(Paint.Style.STROKE);

ringBgPaint.setColor(context.getResources().getColor(colors[i]));

ringBgPaint.setStrokeWidth(ringWidth);

float letf = getWidth()/2 - innerRadius - ringWidth*(ringCount-i) - (ringCount-1-i)*ringSpace + ringWidth/2;

float top = getHeight()/2 - innerRadius - ringWidth*(ringCount-i) - (ringCount-1-i)*ringSpace + ringWidth/2;

float right = getWidth()/2 + innerRadius + ringWidth*(ringCount-i) + (ringCount-1-i)*ringSpace - ringWidth/2;

float bottom = getHeight()/2 + innerRadius + ringWidth*(ringCount-i) + (ringCount-1-i)*ringSpace - ringWidth/2;

ringRectF.set(letf, top, right, bottom);

float sweepAngle = 360*values[i];

if (sweepAngle >= 360) sweepAngle = 360;

canvas.drawArc(ringRectF, -90, sweepAngle,false, ringBgPaint);

}

}

/**

* 设置 数据

* @param title 中间的标题

* @param values 百分比的值

* @param colors 颜色值

*/

public void setData(CharSequence title, float[] values, int[] colors) {

this.title = title;

this.values = values;

this.colors = colors;

invalidate();

}

}

activity_main.xml

xmlns:app="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:orientation="vertical"

android:gravity="center"

>

android:layout_width="match_parent"

android:layout_height="wrap_content"

app:cardCornerRadius="10dp"

android:layout_margin="10dp"

>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="horizontal"

android:gravity="center"

android:background="#f5f5f5"

android:padding="10dp"

>

android:id="@+id/chart_ring"

android:layout_width="100dp"

android:layout_height="100dp"

app:ringCount="3"

app:ringSpace="5dp"

app:ringWidth="5dp"

app:innerRadius="60dp"

app:ringBgColor="#eee"

/>

android:layout_width="0dp"

android:layout_weight="1"

android:layout_height="wrap_content"

android:orientation="vertical"

android:paddingStart="10dp"

android:paddingEnd="10dp"

>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="horizontal"

android:gravity="center_vertical"

>

android:id="@+id/view_mark1"

android:layout_width="6dp"

android:layout_height="6dp"

android:background="@drawable/common_circle"

/>

android:id="@+id/tv_t1"

android:layout_width="wrap_content"

android:layout_height="30dp"

android:gravity="center_vertical"

android:textColor="@color/c1"

android:text="深度"

android:textSize="18sp"

android:layout_marginStart="10dp"

/>

android:id="@+id/tv_value1"

android:layout_width="wrap_content"

android:layout_height="30dp"

android:gravity="center_vertical"

android:textColor="@color/black3"

android:text="其他描述信息"

android:textSize="13sp"

android:layout_marginStart="10dp"

/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="horizontal"

android:gravity="center_vertical"

>

android:id="@+id/view_mark2"

android:layout_width="6dp"

android:layout_height="6dp"

android:background="@drawable/common_circle"

/>

android:id="@+id/tv_t2"

android:layout_width="wrap_content"

android:layout_height="30dp"

android:gravity="center_vertical"

android:textColor="@color/c8"

android:text="深度"

android:textSize="18sp"

android:layout_marginStart="10dp"

/>

android:id="@+id/tv_value2"

android:layout_width="wrap_content"

android:layout_height="30dp"

android:gravity="center_vertical"

android:textColor="@color/black3"

android:text="其他描述信息"

android:textSize="13sp"

android:layout_marginStart="10dp"

/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="horizontal"

android:gravity="center_vertical"

>

android:id="@+id/view_mark3"

android:layout_width="6dp"

android:layout_height="6dp"

android:background="@drawable/common_circle"

/>

android:id="@+id/tv_t3"

android:layout_width="wrap_content"

android:layout_height="30dp"

android:gravity="center_vertical"

android:textColor="@color/c12"

android:text="清醒"

android:textSize="18sp"

android:layout_marginStart="10dp"

/>

android:id="@+id/tv_value3"

android:layout_width="wrap_content"

android:layout_height="30dp"

android:gravity="center_vertical"

android:textColor="@color/black3"

android:text="其他描述信息"

android:textSize="13sp"

android:layout_marginStart="10dp"

/>

MainActivity.java

主要代码

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

showRingChart();

}

private LzRingChart ringChart;

private View vMark1, vMark2, vMark3;

void showRingChart() {

ringChart = findViewById(R.id.chart_ring);

String totalStr = "08:00";

SpannableString s = new SpannableString(totalStr + "\n睡眠总时长");

s.setSpan(new RelativeSizeSpan(2.7f), 0, totalStr.length(), 0);

s.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.black3)), totalStr.length(), s.length(), 0);

s.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.main)), 0, totalStr.length(), 0);

ringChart.setData(s, new float[]{0.5f, 0.5f, 0}, new int[]{R.color.c1, R.color.c8, R.color.c12});

vMark1 = findViewById(R.id.view_mark1);

vMark2 = findViewById(R.id.view_mark2);

vMark3 = findViewById(R.id.view_mark3);

GradientDrawable gd1 = (GradientDrawable) vMark1.getBackground();

gd1.setColor(getResources().getColor(R.color.c1));

GradientDrawable gd2 = (GradientDrawable) vMark2.getBackground();

gd2.setColor(getResources().getColor(R.color.c8));

GradientDrawable gd3 = (GradientDrawable) vMark3.getBackground();

gd3.setColor(getResources().getColor(R.color.c12));

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值