如图:

自定义属性,在values文件夹下创建 attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="SuperCircleView">
<!-- 圆的半径 -->
<attr name="min_circle_radio" format="integer"/>
<!-- 圆环的宽度 -->
<attr name="ring_width" format="float"/>
<!-- 内圆的颜色 -->
<attr name="circle_color" format="color"/>
<!-- 外圆的颜色 -->
<attr name="max_circle_color" format="color"/>
<!-- 圆环的默认颜色 -->
<attr name="ring_normal_color" format="color"/>
<!-- 圆环要显示的彩色的区域(随着数值的改变,显示不同大小的彩色区域)-->
<attr name="ring_color_select" format="integer"/>
<!-- 绘制内容的数值 -->
<attr name="maxValue" format="integer" />
<attr name="value" format="integer" />
</declare-styleable> </resources>

  自定义view

package com.chuanye.huanxingtu;

import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
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.graphics.SweepGradient;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.TextView; public class SuperCircleView extends View { private final String TAG = "SuperCircleView"; private ValueAnimator valueAnimator;
private int mViewCenterX; //view宽的中心点(可以暂时理解为圆心)
private int mViewCenterY; //view高的中心点(可以暂时理解为圆心) private int mMinRadio; //最里面白色圆的半径
private float mRingWidth; //圆环的宽度
private int mMinCircleColor; //最里面圆的颜色
private int mRingNormalColor; //默认圆环的颜色
private Paint mPaint;
private int color[] = new int[3]; //渐变颜色 private RectF mRectF; //圆环的矩形区域
private int mSelectRing = 0; //要显示的彩色区域(岁数值变化)
private int mMaxValue; public SuperCircleView(Context context) {
super(context);
Log.i(TAG,"SuperCircleView--->1SuperCircleView");
} public SuperCircleView(Context context, AttributeSet attrs) {
super(context, attrs);
Log.i(TAG,"SuperCircleView--->2SuperCircleView");
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SuperCircleView);
//最里面白色圆的半径
mMinRadio = a.getInteger(R.styleable.SuperCircleView_min_circle_radio, 300);
//圆环宽度
mRingWidth = a.getFloat(R.styleable.SuperCircleView_ring_width, 40); //最里面的圆的颜色(绿色)
mMinCircleColor = a.getColor(R.styleable.SuperCircleView_circle_color, context.getResources().getColor(R.color.green));
// mMinCircleColor = a.getColor(R.styleable.SuperCircleView_circle_color, context.getResources().getColor(R.color.green));
//圆环的默认颜色(圆环占据的是里面的圆的空间)
mRingNormalColor = a.getColor(R.styleable.SuperCircleView_ring_normal_color, context.getResources().getColor(R.color.gray));
//圆环要显示的彩色的区域
mSelectRing = a.getInt(R.styleable.SuperCircleView_ring_color_select, 0); mMaxValue = a.getInt(R.styleable.SuperCircleView_maxValue, 100); a.recycle(); //抗锯齿画笔
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
//防止边缘锯齿
mPaint.setAntiAlias(true);
//需要重写onDraw就得调用此
this.setWillNotDraw(false); //圆环渐变的颜色
color[0] = Color.parseColor("#FFD300");
color[1] = Color.parseColor("#FF0084");
color[2] = Color.parseColor("#16FF00");
} public SuperCircleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
Log.i(TAG,"SuperCircleView--->3SuperCircleView"); } @Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
Log.i(TAG,"SuperCircleView--->onLayout");
//view的宽和高,相对于父布局(用于确定圆心)
int viewWidth = getMeasuredWidth();
int viewHeight = getMeasuredHeight();
mViewCenterX = viewWidth / 2;
mViewCenterY = viewHeight / 2;
//画矩形
mRectF = new RectF(mViewCenterX - mMinRadio - mRingWidth / 2, mViewCenterY - mMinRadio - mRingWidth / 2, mViewCenterX + mMinRadio + mRingWidth / 2, mViewCenterY + mMinRadio + mRingWidth / 2);
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.i(TAG,"SuperCircleView--->onDraw");
mPaint.setColor(mMinCircleColor);
canvas.drawCircle(mViewCenterX, mViewCenterY, mMinRadio, mPaint);
//画默认圆环
drawNormalRing(canvas);
//画彩色圆环
drawColorRing(canvas);
} /**
* 画默认圆环
*
* @param canvas
*/
private void drawNormalRing(Canvas canvas) {
Paint ringNormalPaint = new Paint(mPaint);
ringNormalPaint.setStyle(Paint.Style.STROKE);
ringNormalPaint.setStrokeWidth(mRingWidth);
ringNormalPaint.setColor(mRingNormalColor);//圆环默认颜色为灰色
canvas.drawArc(mRectF, 360, 360, false, ringNormalPaint);
} /**
* 画彩色圆环
*
* @param canvas
*/
private void drawColorRing(Canvas canvas) {
Paint ringColorPaint = new Paint(mPaint);
ringColorPaint.setStyle(Paint.Style.STROKE);
ringColorPaint.setStrokeWidth(mRingWidth);
ringColorPaint.setShader(new SweepGradient(mViewCenterX, mViewCenterX, color, null));
//逆时针旋转90度
canvas.rotate(-90, mViewCenterX, mViewCenterY);
canvas.drawArc(mRectF, 360, mSelectRing, false, ringColorPaint);
ringColorPaint.setShader(null);
} //***************************************用于更新圆环表示的数值*****************************************************
/**
* 设置当前值
*
* @param value
*/
public void setValue(int value, TextView textView) {
if (value > mMaxValue) {
value = mMaxValue;
}
int start = 0;
int end = value;
startAnimator(start, end, 2000,textView);
} private void startAnimator(int start, int end, long animTime, final TextView textView) {
valueAnimator = ValueAnimator.ofInt(start, end);
valueAnimator.setDuration(animTime);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Log.i(TAG, "onAnimationUpdate: animation.getAnimatedValue()::"+animation.getAnimatedValue());
int i = Integer.valueOf(String.valueOf(animation.getAnimatedValue()));
textView.setText(i + "");
//每个单位长度占多少度
mSelectRing=(int) (360 * (i / 100f));
Log.i(TAG, "onAnimationUpdate: mSelectRing::"+mSelectRing);
invalidate();
}
});
valueAnimator.start();
} }

  布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:gravity="center"
tools:context=".Main1Activity">
<FrameLayout
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_gravity="center"> <com.chuanye.huanxingtu.SuperCircleView
android:id="@+id/superview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:maxValue="100"
app:value="20"
app:ring_width="60" /> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="60dp"
android:text="信息完成度"
android:textColor="#CFD5DE"
android:textSize="18sp" /> <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:orientation="horizontal"> <TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textColor="#506946"
android:textSize="80sp" /> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="%"
android:textSize="28sp" />
</LinearLayout>
</FrameLayout> </LinearLayout>

  MainActivity中

package com.chuanye.huanxingtu;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView; import java.util.Random; public class Main1Activity extends AppCompatActivity {
private static final String TAG = "Main1Activity";
SuperCircleView mSuperCircleView;
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main1); textView = findViewById(R.id.tv);
mSuperCircleView = findViewById(R.id.superview);
mSuperCircleView.setValue(100, textView);
mSuperCircleView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//随机设定圆环大小
int i = new Random().nextInt(100) + 1;
Log.i(TAG, "onClick: i::" + i);
mSuperCircleView.setValue(i, textView);
}
}); }
}

  完成

参考于://https://blog.csdn.net/zhangqunshuai/article/details/80733982

Android中自定义环形图2的更多相关文章

  1. Android中自定义环形图

    如图: 自定义view package com.riverlet.ringview; import android.animation.ObjectAnimator; import android.c ...

  2. [转]Android中自定义checkbox样式

    android中自定义checkbox的图片和大小   其实很简单,分三步: 1.在drawable中创建文件checkbox_selector.xml: <?xml version=" ...

  3. 转--Android中自定义字体的实现方法

    1.Android系统默认支持三种字体,分别为:“sans”, “serif”, “monospace 2.在Android中可以引入其他字体 . 复制代码 代码如下: <?xml versio ...

  4. Android中自定义ActionBar的背景色等样式style

    Android中想要去自定义ActionBar的背景色等样式. [折腾过程] 1.自己找代码,发现对应的配置的地方了: AndroidManifest.xml ? 1 2 <applicatio ...

  5. Android中自定义veiw使用Java中的回调方法

    //------------------MainActivity----中---------------------------------- import android.os.Bundle;imp ...

  6. android开发:Android 中自定义View的应用

    大家好我们今天的教程是在Android 教程中自定义View 的学习,对于初学着来说,他们习惯了Android 传统的页面布局方式,如下代码: <?xml version="1.0&q ...

  7. Android中自定义组合控件

    Android中自定义控件的情况非常多,一般自定义控件可以分为两种:继承控件及组合控件.前者是通过继承View或其子类,重写方法实现自定义的显示及事件处理方式:后者是通过组合已有的控件,来实现结构的简 ...

  8. Android中自定义ListView实现上拉加载更多和下拉刷新

    ListView是Android中一个功能强大而且很常用的控件,在很多App中都有ListView的下拉刷新数据和上拉加载更多这个功能.这里我就简单记录一下实现过程. 实现这个功能的方法不止一个,Gi ...

  9. Android中自定义View和自定义动画

    Android FrameWork 层给我们提供了很多界面组件,但是在实际的商业开发中这些组件往往并不能完全满足我们的需求,这时候我们就需要自定义我们自己的视图和动画. 我们要重写系统的View就必须 ...

随机推荐

  1. Python进阶-I 初识函数(function)

    函数 在java中叫方法. 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print() ...

  2. 1. vue 的安装

    兼容性 Vue 不支持 IE8 及以下版本,因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性.但它支持所有兼容 ECMAScript 5 的浏览器. 安装: 1.直接用 < ...

  3. 模拟赛 T1 费马小定理+质因数分解+exgcd

    求:$a^{bx \%p}\equiv 1(\mod p)$ 的一个可行的 $x$. 根据欧拉定理,我们知道 $a^{\phi(p)}\equiv 1(\mod p)$ 而在 $a^x\equiv 1 ...

  4. ABP .net framework版 的发布

    先正常的发布流程走 特别的如下图

  5. 30-ESP8266 SDK开发基础入门篇--SPI

    这节只是做记录, 整个的教程呢,重新整理下 教程有点乱,需要再细分一下 这节只是做一下我使用其SPI的记录 还是老样子,看人家LUA源码里面怎么使用的 注意哈,对于8266 SDK的学习我还是建议大家 ...

  6. c# HttpClient的HTTP/2支持

    HTTP/2 是 HTTP 协议的主要修订版.HTTP/2 的一些显著功能是支持标头压缩和通过同一连接完全多路复用流.虽然 HTTP/2 保留了 HTTP 的语义(HTTP 标头.方法等),但它在数据 ...

  7. bzoj2287【POJ Challenge】消失之物 缺一01背包

    bzoj2287[POJ Challenge]消失之物 缺一01背包 链接 bzoj 思路 分治solve(l,r,arr)表示缺少物品\([l,r]\)的dp数组arr. 然后solve(l,mid ...

  8. VS Code 安装与配置(使用MSYS2环境与mingw-w64 编译环境)

     更正了顺序,之前不知道怎么回事,内容顺序乱了 力求完美.详细,所以希望懂的人留言指点一下. 目前已经开始添加原理解释,希望大家能分享一些gcc gdb C语言等方面优秀链接 后续会慢慢增添内容,修正 ...

  9. Centos目录及其常用处理命令

    1.Centos之常见目录作用介绍[1] 我们先切换到系统根目录 / 看看根目录下有哪些目录 [root@localhost ~]# cd / [root@localhost /]# ls bin   ...

  10. quantmod

    -quantmod(数据和图形) -TTR(技术分析) -blooter(账户管理) -FinancialInstrument(金融产品) -quantstrast(策略模型) -Performanc ...