如图:

自定义属性,在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. JavaWeb中的监听器

    JavaWeb中的监听器 l  事件源:三大域! ServletContext ¨       生命周期监听:ServletContextListener,它有两个方法,一个在出生时调用,一个在死亡时 ...

  2. 排序算法-插入排序(Java)

    package com.rao.linkList; import java.util.Arrays; /** * @author Srao * @className InsertSort * @dat ...

  3. Babel7 转码

    ES6 (ES2015)更新了很多新的js语法, 也添加了一些新的API, 但不是所有的浏览器对这些新特性都支持的很好, 通过babel可以高版本的js转成低版本的js (ES 5.1), 同时对于J ...

  4. django @login_required登录限制(2)-返回登陆成功后的页面

    本次要实现的功能是,访问未登录的视图函数,需要先跳转到登录页面,登陆成功在跳转回来. 之前在网上找了很多资料,都没有找到解决方案. 跳转到登录页面很好弄,就是登陆成功跳转回来出了问题,原因是登录后的p ...

  5. 关于codeforces加载慢

    昨天cdx报名cf,打开网页10多分钟才交了.... 今天问了wxy,百度了一下,以前也搜过,然后就忘记了. 今天记一下.  1.右键单击开始按钮,打开资源管理器,在资源管理器的地址栏中填写" ...

  6. 安卓设备连接Mac的简单方法

    mac设备是苹果出品的桌面系统,以高冷而闻名,不同于我们平常使用的windows系统,mac系统对软件硬件的兼容性很差,将iOS 设备(iPhone.iPad和iPod)连接至Mac是一件很简单的事, ...

  7. Salesforce 开发整理(六) Visualforce分页

    分页的实现总体上分真分页和假分页. 所谓真分页指页面上列出来的数据就是实际查询的数据,假分页则是无论页面上一次显示多少条记录,实际上后台已经加载了所有的记录,分页只是为了展示给用户查看.今天分享一个V ...

  8. docker Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post

    利用docker构建时,报错 + docker pull maven:3-alpine Got permission denied while trying to connect to the Doc ...

  9. spring boot 启动遇到报错:Failed to configure a DataSource

    spring  boot 启动遇到报错,具体如下 Description: Failed to configure a DataSource: 'url' attribute is not speci ...

  10. A Philosophy of Software Design

    关于复杂性,尚无统一的定义,从不同的角度可以给出不同的答案.可以用数量来度量,比如芯片集成的电子器件越多越复杂(不一定对):按层次性[2]度量,复杂度在于层次的递归性和不可分解性.在信息论中,使用熵来 ...