当前位置: 首页 > 编程日记 > 正文

android 每个块半径不同的扇形图,自定义view

1.首先看效果图

2.自定义PieChartView,继承自View,下边为PieChartView代码

package com.yingjinbao.im.peach.customview;

import android.content.Context;
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.view.View;

/**
* Created by wanger on 07/19/2018.
*/

public class PieChartView extends View {

private int mHeight, mWidth;//宽高
private Paint mPaint;//扇形的画笔
private Paint mTextPaint;//画文字的画笔

private int centerX, centerY;//中心坐标

private int maxNum = 4;//扇形图的最大块数,超出部分自动合并到最后一块上去

double total;//数据的总和
double[] datas;//数据集
String[] texts;//每个数据对应的文字集

//颜色 默认的颜色
private int[] mColors = {
Color.parseColor("#FFC65B"), Color.parseColor("#FD5998"),
Color.parseColor("#8971FB"), Color.parseColor("#676974")
};

private int mTextSize;//文字大小

private int radius = 1000;//半径

public PieChartView(Context context) {
super(context);
}

public PieChartView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}

//初始化
private void init() {
mTextSize = 25;

mPaint = new Paint();
//当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷的图形样式, 如圆形样Cap.ROUND,或方形样式Cap.SQUARE
mPaint.setStrokeCap(Paint.Cap.ROUND);
//设置是否使用抗锯齿功能,会消耗较大资源,绘制图形速度会变慢。
mPaint.setAntiAlias(true);

mTextPaint = new Paint();
//设置绘制文字的字号大小
mTextPaint.setTextSize(mTextSize);
//当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷的粗细度
mTextPaint.setStrokeWidth(3);
//设置是否使用抗锯齿功能,会消耗较大资源,绘制图形速度会变慢。
mTextPaint.setAntiAlias(true);
//设置绘制的颜色,使用颜色值来表示,该颜色值包括透明度和RGB颜色。
mTextPaint.setColor(Color.WHITE);
}


@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获取宽高 不要设置wrap_content
mHeight = MeasureSpec.getSize(heightMeasureSpec);
mWidth = MeasureSpec.getSize(widthMeasureSpec);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//无数据
if (datas == null || datas.length == 0) return;

centerX = (getRight() - getLeft()) / 2;
centerY = (getBottom() - getTop()) / 2;
int min = mHeight > mWidth ? mWidth : mHeight;
if (radius > min / 2) {
radius = (int) ((min - getPaddingTop() - getPaddingBottom()) / 3.5);
}

//画扇形
canvas.save();
drawCircle(canvas);
canvas.restore();


//线与文字
canvas.save();
drawLineAndText(canvas);
canvas.restore();

}


//画线与文字
private void drawLineAndText(Canvas canvas) {
int start = 0;
canvas.translate(centerX, centerY);//平移画布到中心
mPaint.setStrokeWidth(4);
for (int i = 0; i < (maxNum < datas.length ? maxNum : datas.length); i++) {

if (i == (maxNum < datas.length ? maxNum : datas.length) - 1){
drawLine(canvas, start, 360 - start, texts[i], mColors[i % mColors.length],i);
}else {
float angles = (float) ((datas[i] * 1.0f / total) * 360);
drawLine(canvas, start, angles, texts[i], mColors[i % mColors.length],i);
start += angles;
}
}
}

private void drawLine(Canvas canvas, int start, float angles, String text, int color,int position) {
mPaint.setColor(color);
//mTextPaint.setColor(color);
float stopX, stopY;
stopX = (float) ((radius + 40) * Math.cos((2 * start + angles) / 2 * Math.PI / 180));
stopY = (float) ((radius + 40) * Math.sin((2 * start + angles) / 2 * Math.PI / 180));

switch (position){
case 0:
canvas.drawLine((float) ((radius * 0.5) * Math.cos((2 * start + angles) / 2 * Math.PI / 180)),
(float) ((radius * 0.5) * Math.sin((2 * start + angles) / 2 * Math.PI / 180)),
stopX, stopY, mPaint);
break;
case 1:
canvas.drawLine((float) ((radius * 0.7) * Math.cos((2 * start + angles) / 2 * Math.PI / 180)),
(float) ((radius * 0.7) * Math.sin((2 * start + angles) / 2 * Math.PI / 180)),
stopX, stopY, mPaint);
break;
case 2:
canvas.drawLine((float) ((radius * 1.1) * Math.cos((2 * start + angles) / 2 * Math.PI / 180)),
(float) ((radius * 1.1) * Math.sin((2 * start + angles) / 2 * Math.PI / 180)),
stopX, stopY, mPaint);
break;
case 3:
canvas.drawLine((float) ((radius * 0.9) * Math.cos((2 * start + angles) / 2 * Math.PI / 180)),
(float) ((radius * 0.9) * Math.sin((2 * start + angles) / 2 * Math.PI / 180)),
stopX, stopY, mPaint);
break;
default:
canvas.drawLine((float) (radius * Math.cos((2 * start + angles) / 2 * Math.PI / 180)),
(float) (radius * Math.sin((2 * start + angles) / 2 * Math.PI / 180)),
stopX, stopY, mPaint);
break;
}
//canvas.drawLine(0, 0, stopX, stopY, mPaint);
//画横线
int dx;//判断横线是画在左边还是右边
int endX;
if (stopX > 0) {
endX = (int) (stopX + 110);
} else {
endX = (int) (stopX - 110);
}
//画横线
canvas.drawLine(stopX, stopY,
endX, stopY, mPaint
);
dx = (int) (endX - stopX);

//测量文字大小
Rect rect = new Rect();
mTextPaint.getTextBounds(text, 0, text.length(), rect);
int w = rect.width();
int h = rect.height();
int offset = 20;//文字在横线的偏移量
//画文字
canvas.drawText(text, 0, text.length(), dx > 0 ? stopX + offset : stopX - w - offset, stopY - 5, mTextPaint);

//测量百分比大小
String percentage = (datas[position] / total) * 100 + "";
percentage = percentage.substring(0, percentage.length() > 4 ? 4 : percentage.length()) + "%";
mTextPaint.getTextBounds(percentage, 0, percentage.length(), rect);
w = rect.width() - 10;
//画百分比
canvas.drawText(percentage, 0, percentage.length(), dx > 0 ? stopX + offset : stopX - w - offset, stopY + h, mTextPaint);

}

//画扇形
private void drawCircle(Canvas canvas) {
RectF rect = null;
int start = 0;
for (int i = 0; i < (maxNum < datas.length ? maxNum : datas.length); i++) {
if (i == 0){
rect = new RectF((float) (centerX - radius * 0.5), (float) (centerY - radius * 0.5),
(float) (centerX + radius * 0.5), (float) (centerY + radius * 0.5));
}else if (i == 1){
rect = new RectF((float) (centerX - radius * 0.7), (float) (centerY - radius * 0.7),
(float) (centerX + radius * 0.7), (float) (centerY + radius * 0.7));
}else if (i == 2){
rect = new RectF((float) (centerX - radius * 1.1), (float) (centerY - radius * 1.1),
(float) (centerX + radius * 1.1), (float) (centerY + radius * 1.1));
}else if (i == 3){
rect = new RectF((float) (centerX - radius * 0.9), (float) (centerY - radius * 0.9),
(float) (centerX + radius * 0.9), (float) (centerY + radius * 0.9));
}else {
rect = new RectF((float) (centerX - radius * 1), (float) (centerY - radius * 1),
(float) (centerX + radius * 1), (float) (centerY + radius * 1));
}

if (i == (maxNum < datas.length ? maxNum : datas.length) - 1){
float angles = 360 - start;
mPaint.setColor(mColors[i % mColors.length]);

if (i == 2){
canvas.drawArc(rect, start, angles, true, mPaint);

mPaint.setColor(Color.parseColor("#34374A"));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(8);
rect = new RectF((float) (centerX - radius * 1.03), (float) (centerY - radius * 1.03),
(float) (centerX + radius * 1.03), (float) (centerY + radius * 1.03));

canvas.drawArc(rect, start, angles, false, mPaint);
init();
}else {
canvas.drawArc(rect, start, angles, true, mPaint);
}

start += angles;
}else {
float angles = (float) ((datas[i] * 1.0f / total) * 360);
mPaint.setColor(mColors[i % mColors.length]);

if (i == 2){
canvas.drawArc(rect, start, angles, true, mPaint);

mPaint.setColor(Color.parseColor("#34374A"));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(8);
rect = new RectF((float) (centerX - radius * 1.03), (float) (centerY - radius * 1.03),
(float) (centerX + radius * 1.03), (float) (centerY + radius * 1.03));

canvas.drawArc(rect, start, angles, false, mPaint);
init();
}else {
canvas.drawArc(rect, start, angles, true, mPaint);
}


start += angles;
}
}
}

//setter
public void setColors(int[] mColors) {
this.mColors = mColors;
invalidate();
}

public void setTextSize(int mTextSize) {
this.mTextSize = mTextSize;
mTextPaint.setTextSize(mTextSize);
invalidate();
}

public void setRadius(int radius) {
this.radius = radius;
invalidate();
}

public void setMaxNum(int maxNum) {
this.maxNum = maxNum;
invalidate();
}

public void setDatas(double[] datas) {
this.datas = datas;
total = 0;
for (int i = 0;i < datas.length;i++){
total += datas[i];
}
}

public void setTexts(String[] texts) {
this.texts = texts;
}

}
3.使用,首先在XML文件中调用

之后,在activity中,只需找到组件,传入数据,调用 invalidate() 进行重绘即可。

转载于:https://www.cnblogs.com/wangxinqiang1995/p/9334511.html

相关文章:

人工智能的浪潮中,知识图谱何去何从?

漆桂林认为&#xff0c;目前知识图谱整个领域最关注的问题还是如何能够高效、低成本构建知识图谱&#xff0c;而这个问题对于研究人员来说&#xff0c;仍是一个非常大的挑战&#xff0c;比如现在大家都在关注如何在少量甚至无标注场景下进行知识图谱构建。 记者 | Jane 责编 |…

布Sendmail之网,安全则不漏(上)

Sendmail是一种古老的邮件服务器&#xff0c;但是它仍然存在着种种问题&#xff0c;最大的问题就是安全问题。由于Sendmail邮件服务器占据了很大的市场份额&#xff0c;因此&#xff0c;提高Sendmail的安全性就显得格外重要了。本篇拟从证书、Starttls、Sasl技术来探讨Sendmail…

英伟达发布新型GAN,豹子秒变沙皮狗!| 技术头条

作者 | 刘静编译 | 李尔客转自自图灵TOPIA&#xff08;ID:turingtopia&#xff09;5月9日&#xff0c;英伟达首席研究科学家刘明宇在社交网站公布了其最新研究成果&#xff1a;一种新型的GAN&#xff0c;在测试期间只需几张示例图像&#xff0c;就可以将图像转换为以前从未见过…

【Live555】live555源码详解(九):ServerMediaSession、ServerMediaSubsession、live555MediaServer

【Live555】live555源码详解系列笔记 继承协作关系图 下面红色表示本博客将要介绍的三个类所在的位置: ServerMediaSession、ServerMediaSubsession、DynamicRTSPServer DynamicRTSPServer是live555MediaServer中实现的类,用来创建RTSP服务器 17、ServerMediaSession Se…

windows下mysql和linux下mysql主从配置

1. linux下mysql安装版本5.6 windows下mysql版本5.7 不要问我为什么版本不一致 就是想这么搞 2. linux为主服务器 windows为从服务器 3.找到liunx下mysql配置文件 添加如下 然后重新启动 4.添加复制用户 5.查看master状态&#xff0c;记录下两个参数 mysql> show mas…

myeclipse快捷键大全

1.转变大写&#xff1a;ctrlshiftx; 2.转变小写&#xff1a;ctrlshifty; 3.关闭当前窗口&#xff1a;ctrlw; 4.关闭所有的窗口&#xff1a;ctrlshiftw; 5.帮助提示&#xff1a;这个可以选择自己喜欢的键位组合&#xff1a;我比较喜欢ctrlenter; 6.复制当前行&#xff1a;ctrlal…

算力觉醒后,智慧距离勃发就只差一个想法

“太阳把自己的能量以光的形式洒向地面&#xff0c;让植物得以利用光合作用生长成熟&#xff1b;繁茂的草木不仅为动物们提供了栖息的家园&#xff0c;更将太阳的馈赠化为甜蜜的果实&#xff0c;在滋养万灵的同时把自己对未来的希望变成种子&#xff0c;播撒到远方……形成下一…

【Ubuntu】将Ubuntu的源改为国内源

1、备份源 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak2、查询系统代号 $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.1 LTS Release: 20.04 Codename: focal我在Ubuntu20.4上做的测试&#xff0c;Ubun…

浏览器缓存和webpack缓存配置

网络请求会耗费大量时间和请求&#xff0c;如果可以重用为改变的网络资源&#xff0c;对于用户来说可以更快更流畅的查看网页&#xff0c;对于服务器来说减少了很多负荷&#xff0c;所以浏览器缓存是前端优化的重要内容。本文介绍了浏览器缓存的机制和缓存在webpack中的应用。 …

ipsec ***野蛮模式应用

IPSEC野蛮模式&#xff1a;简介&#xff1a;IKE 的协商模式 在RFC2409&#xff08;The Internet Key Exchange &#xff09;中规定&#xff0c;IKE 第一阶段的协商可以采用两种模式&#xff1a;主模式&#xff08;Main Mode &#xff09;和野蛮模式&#xff08;Aggressive Mode…

漫画:什么是LRU算法?

本期封面作者&#xff1a;A17————— 两个月前 —————用户信息当然是存在数据库里。但是由于我们对用户系统的性能要求比较高&#xff0c;显然不能每一次请求都去查询数据库。所以&#xff0c;小灰在内存中创建了一个哈希表作为缓存&#xff0c;每次查找一个用户的时候…

第15章节-Python3.5-Django实现用户登录与前端交互2 14

目的我想登陆成功后显示我的后台管理(实现过程): 新建home.html 在templates目录下代码如下: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body style"…

【GLib】GLib学习笔记(一):GLib、GObject、GType

1、GLib GLib是 Gtk 库和 Gnome 的基础。glib 可以在多个平台下使用&#xff0c;比如 Linux、Unix、Windows 等。GLib为许多标准的、常用的 C 语言结构提供了相应的替代物。 GLib是GTK的基础库&#xff0c;它由基础类型、对核心应用的支持、实用功能、数据类型和对象系统五个…

tomcat配置tomcat-redis-session-manager

为什么80%的码农都做不了架构师&#xff1f;>>> 今天写了半天程序&#xff0c;有点乏了。想想来配置一下tomcat-redis-session-manager吧&#xff0c;但是按照 官方文档配了总是tomcat启动错误。 java.lang.NoClassDefFoundError: org/apache/commons/pool/impl/Ge…

链式比较、奇怪的字母、有趣的import...Python冷知识(六)

本文转载自Python编程时光&#xff08;ID:Python-Time&#xff09;冷知识系列&#xff0c;已经更新至第六篇。谈谈 Python 那些不为人知的冷知识&#xff08;一&#xff09;谈谈 Python 那些不为人知的冷知识&#xff08;二&#xff09;谈谈 Python 那些不为人知的冷知识&#…

【GLib】GLib学习笔记(二):源码编译

一、源码下载 http://ftp.acc.umu.se/pub/GNOME/sources/glib/本人下载是最新版本(截至2020-08-26)&#xff1a;glib-2.65.2.tar.xz 二、安装依赖 1、安装依赖库 sudo apt install cmake sudo apt install zlib1g-dev sudo apt install meson sudo apt install ninja sudo …

java之类和对象

概述 面向过程&#xff1a;面向过程主要是把问题分解成多个不同的步骤&#xff0c;然后把各个步骤变成方法&#xff0c;它更强调过程。代表语言&#xff1a;c 面向对象&#xff1a;面向对象会把问题分解成各个对象&#xff0c;然后各个对象之间进行交互&#xff0c;每个对象内部…

【GLib】GLib学习笔记(三):gtypes、garray、gerror、goption

1、类型&#xff1a;glib/gtypes.h 1.1 基本类型&#xff1b; typedef char gchar; typedef short gshort; typedef long glong; typedef int gint; typedef gint gboolean;typedef unsigned char guchar; typedef unsigned short gushort; typedef unsigned lo…

Bert时代的创新:Bert应用模式比较及其它 | 技术头条

作者&#xff1a;张俊林&#xff0c;中国中文信息学会理事&#xff0c;中科院软件所博士。目前在新浪微博 AI Lab 担任资深算法专家。在此之前&#xff0c;张俊林曾经在阿里巴巴任资深技术专家并负责新技术团队&#xff0c;以及在百度和用友担任技术经理及技术总监等职务。他是…

HashSet 详解

为什么80%的码农都做不了架构师&#xff1f;>>> package com.sun;/* |——SortedSet接口——TreeSet实现类 Set接口——|——HashSet实现类|——LinkedHashSet实现类 HashSet 此类实现 Set 接口&#xff0c;由哈希表&#xff08;实际上是一个 HashMap 实例&#…

肖仰华:知识图谱落地,不止于“实现”

作者 | Just出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;“知识将比数据更重要&#xff0c;得知识者得天下”&#xff0c;去年十月&#xff0c;在 CSDN 对肖仰华教授的一篇约稿里&#xff0c;他指出数据的真正价值蕴含于其深加工的知识中。从 Google 于 2012 年提…

【摄像头】摄像头相关名词解释

1、白平衡 白平衡,字面上的理解是白色的平衡。白平衡是描述显示器中红、绿、蓝三基色混合生成后白色精确度的一项指标。 那什么是白色?这就涉及到一些色彩学的知识,白色是指反射到人眼中的光线由于蓝、绿、红三种色光比例相同且具有一定的亮度所形成的视觉反应。我们都知道…

金额跳动动画效果

前言 金额效果&#xff0c;因为觉得公司目前的金额太乏味&#xff0c;决定加点效果&#xff0c;也特此写了个小demo&#xff0c;代码非常简单&#xff0c;贴代码方便大家看看 通过 runtime 建立属性(setter/getter方法) /** 由于分类中要添加属性&#xff0c;所以通过runtime方…

POJ 3070 Fibonacci

裸奔的矩阵乘法&#xff0c;当模板了。 #include <iostream>#include <cstring>#include <cstdio>using namespace std;const int N 2;const int MOD 10000;struct Mat {long long mat[N][N];void init() {for(int i 0; i < N; i) {for(int j 0; j &l…

推荐一个小而美的Python代码格式化工具

代码可读性是评判代码质量的标准之一&#xff0c;有一个衡量代码质量的标准是 Martin 提出的 “WFT” 定律&#xff0c;即每分钟爆出 “WTF” 的次数。你在读别人代码或者做 Code Review 的时候有没有 “WTF” 冲动呢&#xff1f; 为了帮助开发者统一代码风格&#xff0c;Pytho…

【摄像头】摄像机工作原理

1、摄像机工作原理 外部光线穿过镜头(lens)后&#xff0c; 经过滤光片(color filter)滤波后照射到光学传感器(Sensor)上面&#xff0c; Sensor 将从 lens 上传导过来的光线转换为电信号&#xff0c;再通过内部的 AD 转换为数字信号。 如果 Sensor 没有集成 DSP&#xff0c;则通…

@程序员,别再自己闷头学了

60 年冬去春来&#xff0c;人工智能技术发展起起落落。现在是 2019 年&#xff0c;属于 AI 不可阻挡的新转机正强势袭来。 科技巨头一向是未来技术发展最重要的风向标。2011 年&#xff0c;随着 Google 将一线业务引入深度学习技术&#xff0c;落伍移动时代的微软也拉起了一支…

linux下的oracle10g rman备份

RMAN是Oracle提供的一个数据库备份和恢复工具&#xff0c;利用rman可以比较方便的对数据库进行备份。Oracle 数据库可运行在归档和非归档模式下&#xff0c;这两者的区别就在于对redo log的处理。归档模式下&#xff0c;当一个redo log 写满之后&#xff0c;就会把这个redo lo…

最全Python算法实现资源汇总!

整理 | Rachel责编 | Jane出品 | Python大本营&#xff08;ID&#xff1a;pythonnews&#xff09;【导语】数据结构与算法是所有人都要学习的基础课程&#xff0c;自己写算法的过程可以帮助我们更好地理解算法思路&#xff0c;不要轻视每一个算法&#xff0c;一些虽然看似容易&…

【摄像头】低照度和光圈

1、低照度 低照度摄像机是指在较低光照度的条件下仍然可以摄取清晰图像的摄像头。 照度,即光照强度,是一种物理术语,指单位面积上所接受可见光的能量。单位:勒克斯Lux,简作Lx。 照度和光圈大小的关系:镜头的光圈越大(F值越小),所需的照度越低。这个好理解,光圈大了进…