Android 自定义view --圆形百分比(进度条)
转载请注明出处:http://blog.csdn.net/wingichoy/article/details/50334595
注:本文由于是在学习过程中写的,存在大量问题(overdraw onDraw new对象),请读者们不要被误导!!解决办法见后面的博客。
起因
最近公司项目有需求需要用到轻量级图表如下图,是一些简单的扇形图,圆形图,折线图,虽然有好用的三方库MPChart
(教程地址http://blog.csdn.net/wingichoy/article/details/50428246),
但是过于庞大,像这样的简约的界面明显不合适,又因为许久没有坚持写博客,觉得自己很是堕落,深知自学不易,于是便想写一些博客来帮助后来像我一样的初学者,所以便想把这些效果写一个系列。其中包括:
1.圆形百分比图表
2.简易折线图图表
3.简易柱状图图表
效果图
说了这么多没有效果图还是废话,效果图如下:
预备知识
本篇博客的预备知识内容有:
1.自定义属性
2.自定义view
关于以上两点,可以查看 Hongyang大神的博客:自定义View(一)
知识点补充
如果你已经掌握了以上的基本知识,那么可以开始本篇博客的内容啦。但是还是有几点内容补充。
1.MeasureSpec对象包含了测量的模式和大小。他是一个32位的int值,其中高两位为测量的模式,低30位是测量的大小。采用位运算和运行效率有关。所以可以从一个MeasureSpec对象分别获取模式和值 如:
//获取模式 值为 EXACTLY AT_MOST UNSPECIFIED
int specMode = MeasureSpec.getMode(measureSpec);
//获取测量值
int specSize = MeasureSpec.getSize(measureSpec);2.画扇形,调用drawArc()方法,其中第一个参数是圆所在的矩形,第二个参数是开始的弧度,值得主意的是,最顶的弧度是270度,而地图东方向的弧度为0.第三个参数是需要画的弧度,第四个参数是一个布尔值,表示是否连接圆心,画为扇形,第五个是Paint,即所需要的画笔。
canvas.drawArc(rect, 270, mEndAngle, true, sectorPaint);
现在开始吧
1.首先分析需求,我们的圆形进度总共分为三层,
最底层是一个大园形,作为底色。
第二层是一个扇形,大小跟底色一样,用来表示进度。
第三层是一个小圆形,比背景色小,用于实现弧线的效果。
2.新建一个类叫做CirclePercentView.java 他继承与View类重写他的构造函数,来获取他的自定义属性。
public CirclePercentView(Context context) {
this(context, null);
}
public CirclePercentView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CirclePercentView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// 获取自定义属性
TypedArray a=context.obtainStyledAttributes(attrs,R.styleable.CirclePercentView, defStyleAttr, 0);
//获取色带的宽度
mStripeWidth = a.getDimension(R.styleable.CirclePercentView_stripeWidth, PxUtils.dpToPx(30, context));
//获取当前的百分比
mCurPercent = a.getInteger(R.styleable.CirclePercentView_percent, 0);
//获取小园的颜色
mSmallColor = a.getColor(R.styleable.CirclePercentView_smallColor,0xffafb4db);
//获取大圆的颜色
mBigColor = a.getColor(R.styleable.CirclePercentView_bigColor,0xff6950a1);
//获取中心文字的大小
mCenterTextSize = a.getDimensionPixelSize(R.styleable.CirclePercentView_centerTextSize,PxUtils.spToPx(20,context));
//获取园的半径
mRadius = a.getDimensionPixelSize(R.styleable.CirclePercentView_radius,PxUtils.dpToPx(100,context));
}
3.获取到了自定义属性以后,我们来测量这个view,告诉系统这个view有多大
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//获取测量模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
//获取测量大小
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
//如果为确定大小值,则圆的半径为宽度/2
if (widthMode == MeasureSpec.EXACTLY && heightMode == MeasureSpec.EXACTLY) {
mRadius = widthSize / 2;
x = widthSize / 2;
y = heightSize / 2;
mWidth = widthSize;
mHeight = heightSize;
}
//如果为wrap_content 那么View大小为圆的半径大小*2
if(widthMode == MeasureSpec.AT_MOST&&heightMode ==MeasureSpec.AT_MOST){
mWidth = (int) (mRadius*2);
mHeight = (int) (mRadius*2);
x = mRadius;
y = mRadius;
}
//设置视图的大小
setMeasuredDimension(mWidth,mHeight);
}
4.测量完成后,我们就要开始画view了。首先画大圆,之后画扇形图,最后画小圆盖住
就有了圆形进度条的效果,之后把百分比进度文字画在上面就大功告成啦。
具体步骤如图:
@Override
protected void onDraw(Canvas canvas) {
mEndAngle = (int) (mCurPercent * 3.6);
//绘制大圆
Paint bigCirclePaint = new Paint();
//消除锯齿
bigCirclePaint.setAntiAlias(true);
bigCirclePaint.setColor(mBigColor);
//x,y 为圆心坐标 mRadius为半径
canvas.drawCircle(x, y, mRadius, bigCirclePaint);
//饼状图
Paint sectorPaint = new Paint();
sectorPaint.setColor(mSmallColor);
sectorPaint.setAntiAlias(true);
RectF rect = new RectF(0, 0, mWidth, mHeight);
//参数说明见知识补充
canvas.drawArc(rect, 270, mEndAngle, true, sectorPaint);
//绘制小圆
Paint smallCirclePaint = new Paint();
smallCirclePaint.setAntiAlias(true);
smallCirclePaint.setColor(mBigColor);
//圆心是相同的 不过半径有差别,这个差别就是我们的 色带宽度
canvas.drawCircle(x, y, mRadius - mStripeWidth, smallCirclePaint);
//绘制文本
Paint textPaint = new Paint();
String text = mCurPercent + "%";
textPaint.setTextSize(mCenterTextSize);
//测量字符串长度
float textLength = textPaint.measureText(text);
textPaint.setColor(Color.WHITE);
//把文本画在圆心居中
canvas.drawText(text, x - textLength/2, y, textPaint);
}
值得注意的是,在编写的过程中,文字的位置总是不对,但是根据画图计算,
公式是没错的,最后才发现我先测量了字符串长度,又修改了字体的大小导致偏差。所以一定要注意这些细节,先改变字体大小,再去测量。
5.添加setPercent方法
public void setPercent(int percent) {
//百分比不可能超过100 如果超过100则抛出异常
if (percent > 100) {
throw new IllegalArgumentException("percent must less than 100!");
}
setCurPercent(percent);
}
//内部设置百分比 用于动画效果
private void setCurPercent(int percent) {
mPercent = percent;
new Thread(new Runnable() {
@Override
public void run() {
for(int i =0;i<mPercent;i++){
try {
Thread.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
mCurPercent = i;
CirclePercentView.this.postInvalidate();
}
}
}).start();
}
这里在setPercent改变的时候,开启一个线程,来不断重绘view,达到一个动画效果。其实view的动画效果就是不停地重绘
(即执行onDraw(),因为每次执行onDraw()里面的参数会变化,所以会看到不同的画面)。这样便完成了一个轻量级的圆形百分比进度条自定义View。
你可以在https://github.com/githubwing/CirclePercentView克隆到源码。(求star)
你还可以看本系列第二篇博客:简易折线图,链接:http://blog.csdn.net/wingichoy/article/details/50434634。
Android 自定义view --圆形百分比(进度条)的更多相关文章
- css3圆形百分比进度条的实现原理
原文地址:css3圆形百分比进度条的实现原理 今天早上起来在查看jquery插件机制的时候,一不小心点进了css3圆形百分比进度条的相关文章,于是一发不可收拾,开始折腾了... 关于圆形圈的实现,想必 ...
- HTML5圆形百分比进度条插件circleChart
在页面中引入jquery和circleChart.min.js文件. <script src="path/to/jquery.min.js"></script&g ...
- Android 自定义 View 圆形进度条总结
Android 自定义圆形进度条总结 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 微信公众号:牙锅子 源码:CircleProgress 文中如有纰漏,欢迎大家留言指出. 最近 ...
- Android自定义一款带进度条的精美按键
Android中自定义View并没有什么可怕的,拿到一个需要自定义的View,首先要做的就是把它肢解,然后思考每一步是怎样实现的,按分析的步骤一步一步的编码实现,最后你就会发现达到了你想要的效果.本文 ...
- 简单说说Android自定义view学习推荐的方式
这几天比较受关注,挺开心的,嘿嘿. 这里给大家总结一下学习自定义view的一些技巧. 以后写自定义view可能不会写博客了,但是可以开源的我会把源码丢到github上我的地址:https://git ...
- Android 自定义View合集
自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/ ...
- Android 自定义圆形旋转进度条,仿微博头像加载效果
微博 App 的用户头像有一个圆形旋转进度条的加载效果,看上去效果非常不错,如图所示: 据说 Instagram 也采用了这种效果.最近抽空研究了一下,最后实现的效果是这样: 基本上能模拟出个大概,代 ...
- 我的Android进阶之旅------>Android自定义View实现带数字的进度条(NumberProgressBar)
今天在Github上面看到一个来自于 daimajia所写的关于Android自定义View实现带数字的进度条(NumberProgressBar)的精彩案例,在这里分享给大家一起来学习学习!同时感谢 ...
- BitBlt()函数实现带数字百分比进度条控件、静态文本(STATIC)控件实现的位图进度条、自定义进度条控件实现七彩虹颜色带数字百分比
Windows API BitBlt()函数实现带数字百分比进度条控件. 有两个例子:一用定时器实现,二用多线程实现. 带有详细注解. 此例是本人原创,绝对是网上稀缺资源(本源码用Windows AP ...
随机推荐
- Android适配难题全面总结
支持多种屏幕 Android 可在各种具有不同屏幕尺寸和密度的设备上运行.对于 应用,Android 系统在不同设备中提供一致的开发环境, 可以处理大多数工作,将每个应用的用户界面调整为适应其显示的 ...
- 亲密接触Redis-第二天(Redis Sentinel)
简介 经过上次轻松搭建了一个Redis的环境并用Java代码调通后,这次我们要来看看Redis的一些坑以及Redis2.8以后带来的一个新的特性即支持高可用特性功能的Sentinel(哨兵). Red ...
- NSDictionary writeToFile:atomically: 时失败
一.现象:如下图,当NSDictionary调用 writeToFile:atomically: 时,如果容器里面包含的对象(即通过 objectForKey: 拿到的对象),为非property l ...
- [线程]Thead 中传参数RuntimeError: thread.__init__() not called
在写一个多线程类的时候调用报错 RuntimeError: thread.__init__() not called class NotifyTread(threading.Thread): def ...
- Android Multimedia框架总结(九)Stagefright框架之数据处理及到OMXCodec过程
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼:http://blog.csdn.net/hejjunlin/article/details/52532085 不知不觉到第九篇了,感觉还有 ...
- xlsx批量转为utf8的csv
xlsx批量转为utf8的csv(金庆的专栏)策划的配置表为 xlsx 表格,可以有注释,公式.服务器和客户端使用的配置文件需要转成 csv 文件.使用 WPS 另存无法批量转换,并且结果不是utf8 ...
- Socket实现单客户端与服务器对话功能
单客户端,顾名思义,就是客户端只有一个用户去访问服务器,然后服务器根据该客户请求返回信息,先看下效果图: 服务端(左)和客户端(右): 注意,我是用了两个eclipse,一个只放服务端文件,一个只放客 ...
- Dynamics CRM2015 Update1 新功能之表单增强功能
CRM2015 Update 1发布后,系统的界面的变化很大,仔细观察后会发现表单窗体也有些不同了,在CRM2015 Update1的官方介绍中对此变化的解释是起用了新的窗体呈现引擎,让界面更好看加载 ...
- Java实现内部类
内部类是java中非常方便的一种机制,内部类所在的类称为宿主类,即内部类只能被它的宿主类使用,用这个特性,可以很好的控制类的可见性. 接下来看一个例子: package for_apro; impor ...
- Android 自定义View-android学习之旅(十四)
自定义View的步骤 当andoid提供的系统组件不满足要求时候,完全可以集成View来派生自定义组件. 首定定义一个继承View的子类,然后重写他一个或几个方法. 重写的方法介绍 构造器:这是定制V ...