先看下最终的效果
静态:
动态:
一、开始实现
新建一个DoughnutProgress继承View
public class DoughnutProgress extends View { }
先给出一些常量、变量以及公共方法的代码,方便理解后面的代码
private static final int DEFAULT_MIN_WIDTH = 400; //View默认最小宽度 private static final int RED = 230, GREEN = 85, BLUE = 35; //基础颜色,这里是橙红色 private static final int MIN_ALPHA = 30; //最小不透明度 private static final int MAX_ALPHA = 255; //最大不透明度 private static final float doughnutRaduisPercent = 0.65f; //圆环外圆半径占View最大半径的百分比 private static final float doughnutWidthPercent = 0.12f; //圆环宽度占View最大半径的百分比 private static final float MIDDLE_WAVE_RADUIS_PERCENT = 0.9f; //第二个圆出现时,第一个圆的半径百分比 private static final float WAVE_WIDTH = 5f; //波纹圆环宽度 //圆环颜色 private static int[] doughnutColors = new int[]{ Color.argb(MAX_ALPHA, RED, GREEN, BLUE), Color.argb(MIN_ALPHA, RED, GREEN, BLUE), Color.argb(MIN_ALPHA, RED, GREEN, BLUE)}; private Paint paint = new Paint(); //画笔 private float width; //自定义view的宽度 private float height; //自定义view的高度 private float currentAngle = 0f; //当前旋转角度 private float raduis; //自定义view的最大半径 private float firstWaveRaduis; private float secondWaveRaduis; // private void resetParams() { width = getWidth(); height = getHeight(); raduis = Math.min(width, height)/2; } private void initPaint() { paint.reset(); paint.setAntiAlias(true); }
重写onMeasure方法,为什么要重写onMeasure方法可以看我的上一篇文章,点这里
/** * 当布局为wrap_content时设置默认长宽 * * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(measure(widthMeasureSpec), measure(heightMeasureSpec)); } private int measure(int origin) { int result = DEFAULT_MIN_WIDTH; int specMode = MeasureSpec.getMode(origin); int specSize = MeasureSpec.getSize(origin); if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return result; }
下面就是最重要的重写onDraw方法,大致流程如下
在开始绘制之前,先初始化width、height、raduis, 以及将View的中心作为原点
resetParams(); //将画布中心设为原点(0,0), 方便后面计算坐标 canvas.translate(width / 2, height / 2);
实现静态的渐变圆环
1、画渐变圆环
float doughnutWidth = raduis * doughnutWidthPercent;//圆环宽度 //圆环外接矩形 RectF rectF = new RectF( -raduis * doughnutRaduisPercent, -raduis * doughnutRaduisPercent, raduis * doughnutRaduisPercent, raduis * doughnutRaduisPercent); initPaint(); paint.setStrokeWidth(doughnutWidth); paint.setStyle(Paint.Style.STROKE); paint.setShader(new SweepGradient(0, 0, doughnutColors, null)); canvas.drawArc(rectF, 0, 360, false, paint);
通过修改doughnutColors可以实现不同的渐变效果
2、画圆环旋转头部的圆
//画旋转头部圆 initPaint(); paint.setStyle(Paint.Style.FILL); paint.setColor(Color.argb(MAX_ALPHA, RED, GREEN, BLUE)); canvas.drawCircle(raduis * doughnutRaduisPercent, 0, doughnutWidth / 2, paint);
此时运行代码得到效果如下图:
我们还可以在绘制圆环之前通过旋转画布得到不同初始状态
canvas.rotate(-45, 0, 0);
canvas.rotate(-180, 0, 0);
此时聪明的你应该已经想到怎么让这个圆环旋转起来了吧^_^
对!正如你所想的,就是通过canvas.rotate方法不停地旋转画布(这个“地”是这么用的吧o(╯□╰)o)
让圆环旋转起来
在绘制圆环之前加上下面的代码:
//转起来 canvas.rotate(-currentAngle, 0, 0); if (currentAngle >= 360f){ currentAngle = currentAngle - 360f; } else{ currentAngle = currentAngle + 2f; }
然后再让一个线程循环刷新就好了
private Thread thread = new Thread(){ @Override public void run() { while(true){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } postInvalidate(); } } };
试试!转起来了吗O(∩_∩)O~
下面是比较有意思的部分,实现类似水波涟漪的效果
分析水波涟漪效果的实现原理(画了张草图方便理解):
假设淡黄色背景区域为整个View的大小
黑色圆圈为View内的最大圆(半径为R3)
橙色圆环代表渐变圆环
红色圆圈代表圆环的外圆(半径为R1)
紫色圆圈是干啥子的,待会儿再介绍~(半径为R2)
通过观察实现的最终效果,可以发现有个圆的半径从R1逐渐增大R3,不透明度逐渐减小到0。
那是不是这样周而复始就可以实现最终的效果了呢?
没那么简单。。。
仔细观察发现,第二个圆不是等到第一个圆的半径增大到R3才开始出现的,而是在将要消失的时候就出现了,有一段时间是两个圆同时存在的。
那么我们就假设当第一个圆的半径增大到R2,第二个圆开始出现。
开始想象两个圆的循环运行模型~~~
我的方案是:
绘制两个圆,每个圆的半径都从R1增大到R1+2x(R2-R1),不透明度还是从R1到R3的过程中逐渐变为0,也就是当圆的半径大于R3时,不透明度就为0了(不可见了),将第一个圆半径初始值设为R1,第二个圆半径初始值设为R2。这样两个圆半径同时逐渐增大,当半径大于 R1+2x(R2-R1)时又重新回到R1大小继续增大,就实现了类似水波涟漪的效果了。
//实现类似水波涟漪效果 initPaint(); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(5); secondWaveRaduis = calculateWaveRaduis(secondWaveRaduis); firstWaveRaduis = calculateWaveRaduis(secondWaveRaduis + raduis*(MIDDLE_WAVE_RADUIS_PERCENT - doughnutRaduisPercent) - raduis*doughnutWidthPercent/2); paint.setColor(Color.argb(calculateWaveAlpha(secondWaveRaduis), RED, GREEN, BLUE)); canvas.drawCircle(0, 0, secondWaveRaduis, paint); //画第二个圆(初始半径较小的) initPaint(); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(5); paint.setColor(Color.argb(calculateWaveAlpha(firstWaveRaduis), RED, GREEN, BLUE)); canvas.drawCircle(0, 0, firstWaveRaduis, paint); //画第一个圆(初始半径较大的) /** * 计算波纹圆的半径 * @param waveRaduis * @return */ private float calculateWaveRaduis(float waveRaduis){ if(waveRaduis < raduis*doughnutRaduisPercent + raduis*doughnutWidthPercent/2){ waveRaduis = raduis*doughnutRaduisPercent + raduis*doughnutWidthPercent/2; } if(waveRaduis > raduis*MIDDLE_WAVE_RADUIS_PERCENT + raduis*(MIDDLE_WAVE_RADUIS_PERCENT - doughnutRaduisPercent) - raduis*doughnutWidthPercent/2){ waveRaduis = waveRaduis - (raduis*MIDDLE_WAVE_RADUIS_PERCENT + raduis*(MIDDLE_WAVE_RADUIS_PERCENT - doughnutRaduisPercent) - raduis*doughnutWidthPercent/2) + raduis*doughnutWidthPercent/2 + raduis*doughnutRaduisPercent; } waveRaduis += 0.6f; return waveRaduis; } /** * 根据波纹圆的半径计算不透明度 * @param waveRaduis * @return */ private int calculateWaveAlpha(float waveRaduis){ float percent = (waveRaduis-raduis*doughnutRaduisPercent-raduis*doughnutWidthPercent/2)/(raduis-raduis*doughnutRaduisPercent-raduis*doughnutWidthPercent/2); if(percent >= 1f){ return 0; }else{ return (int) (MIN_ALPHA*(1f-percent)); } }
以上就是本文的全部内容,希望对大家的学习Android软件编程有所帮助。
本文向大家介绍Android自定义View之酷炫数字圆环,包括了Android自定义View之酷炫数字圆环的使用技巧和注意事项,需要的朋友参考一下 先看下最终的效果 一、开始实现 新建一个DoughnutView继承View 先重写onMeasure方法。 下面就是最重要的重写onDraw方法,大致流程如下 1、画白色圆环(背景),记得改下Activity背景色不然白色圆环看不出来。 2、画彩
本文向大家介绍Android自定义View制作动态炫酷按钮实例解析,包括了Android自定义View制作动态炫酷按钮实例解析的使用技巧和注意事项,需要的朋友参考一下 普通按钮也就那么几种样式,看着都审美疲劳,先放效果图: 你会不会以为这个按钮是集结了很多动画的产物,我告诉你,并没有。所有的实现都是基于自定义View,采用最底层的onDraw一点一点的画出来的。没有采用一丁点的动画。虽然演示时
本文向大家介绍Android自定义View画圆功能,包括了Android自定义View画圆功能的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Android自定义View画圆的具体代码,供大家参考,具体内容如下 引入布局 自定义View的java类,继承View 效果图: 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
本文向大家介绍Android自定义View实现圆环交替效果,包括了Android自定义View实现圆环交替效果的使用技巧和注意事项,需要的朋友参考一下 下面请先看效果图: 看上去是不很炫的样子,它的实现上也不是很复杂,重点在与onDraw()方法的绘制。 首先是我们的attrs文件: 接下来是我们重写View类的自定义View类: 最后是我们的布局文件: 总结 好了,到这里我们的效果就算大工
本文向大家介绍Android自定义View之圆形进度条式按钮,包括了Android自定义View之圆形进度条式按钮的使用技巧和注意事项,需要的朋友参考一下 介绍 今天上班的时候有个哥们问我怎么去实现一个按钮式的进度条,先来看看他需要实现的效果图。 和普通的圆形进度条类似,只是中间的地方有两个状态表示,未开始,暂停状态。而且他说圆形进度的功能已经实现了。那么我们只需要对中间的两个状态做处理就行了。
本文向大家介绍Android自定view画圆效果,包括了Android自定view画圆效果的使用技巧和注意事项,需要的朋友参考一下 这是一个自定义view画圆,对于初学自定义view的小伙伴这是一个很好的帮助。 看图 代码: 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。