最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Android编程使用自定义View实现水波进度效果示例
时间:2017-02-10 编辑:简简单单 来源:一聚教程网
本文实例讲述了Android编程使用自定义View实现水波进度效果。分享给大家供大家参考,具体如下:
首先上效果图:
简介:
1.自动适应屏幕大小;
2.水波自动横向滚动;
3.各种绘制参数可通过修改常量进行控制。
代码不多,注释也比较详细,全部贴上:
(一)自定义组件:
代码如下 | 复制代码 |
/** * 水波进度效果. */ publicclassWaterWaveViewextendsView { //边框宽度 privateintSTROKE_WIDTH; //组件的宽,高 privateintwidth, height; /** * 进度条最大值和当前进度值 */ privatefloatmax, progress; /** * 绘制波浪的画笔 */ privatePaint progressPaint; //波纹振幅与半径之比。(建议设置:<0.1) privatestaticfinalfloatA =0.05f; //绘制文字的画笔 privatePaint textPaint; //绘制边框的画笔 privatePaint circlePaint; /** * 圆弧圆心位置 */ privateintcenterX, centerY; //内圆所在的矩形 privateRectF circleRectF; publicWaterWaveView(Context context) { super(context); init(); } publicWaterWaveView(Context context, AttributeSet attrs) { super(context, attrs); init(); } publicWaterWaveView(Context context, AttributeSet attrs,intdefStyleAttr) { super(context, attrs, defStyleAttr); init(); } //初始化 privatevoidinit() { progressPaint =newPaint(); progressPaint.setColor(Color.parseColor("#77cccc88")); progressPaint.setAntiAlias(true); textPaint =newPaint(); textPaint.setColor(Color.WHITE); textPaint.setAntiAlias(true); circlePaint =newPaint(); circlePaint.setStyle(Paint.Style.STROKE); circlePaint.setAntiAlias(true); circlePaint.setColor(Color.parseColor("#33333333")); autoRefresh(); } @Override protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if(width ==0|| height ==0) { width = getWidth(); height = getHeight(); //计算圆弧半径和圆心点 intcircleRadius = Math.min(width, height) >>1; STROKE_WIDTH = circleRadius /10; circlePaint.setStrokeWidth(STROKE_WIDTH); centerX = width /2; centerY = height /2; VALID_RADIUS = circleRadius - STROKE_WIDTH; RADIANS_PER_X = (float) (Math.PI / VALID_RADIUS); circleRectF =newRectF(centerX - VALID_RADIUS, centerY - VALID_RADIUS, centerX + VALID_RADIUS, centerY + VALID_RADIUS); } } privateRect textBounds =newRect(); //x方向偏移量 privateintxOffset; @Override protectedvoidonDraw(Canvas canvas) { super.onDraw(canvas); //绘制圆形边框 canvas.drawCircle(centerX, centerY, VALID_RADIUS + (STROKE_WIDTH >>1), circlePaint); //绘制水波曲线 canvas.drawPath(getWavePath(xOffset), progressPaint); //绘制文字 textPaint.setTextSize(VALID_RADIUS >>1); String text1 = String.valueOf(progress); //测量文字长度 floatw1 = textPaint.measureText(text1); //测量文字高度 textPaint.getTextBounds("8",0,1, textBounds); floath1 = textBounds.height(); floatextraW = textPaint.measureText("8") /3; canvas.drawText(text1, centerX - w1 /2- extraW, centerY + h1 /2, textPaint); textPaint.setTextSize(VALID_RADIUS /6); textPaint.getTextBounds("M",0,1, textBounds); floath2 = textBounds.height(); canvas.drawText("M", centerX + w1 /2- extraW +5, centerY - (h1 /2- h2), textPaint); String text3 ="共"+ String.valueOf(max) +"M"; floatw3 = textPaint.measureText(text3,0, text3.length()); textPaint.getTextBounds("M",0,1, textBounds); floath3 = textBounds.height(); canvas.drawText(text3, centerX - w3 /2, centerY + (VALID_RADIUS >>1) + h3 /2, textPaint); String text4 ="流量剩余"; floatw4 = textPaint.measureText(text4,0, text4.length()); textPaint.getTextBounds(text4,0, text4.length(), textBounds); floath4 = textBounds.height(); canvas.drawText(text4, centerX - w4 /2, centerY - (VALID_RADIUS >>1) + h4 /2, textPaint); } //绘制水波的路径 privatePath wavePath; //每一个像素对应的弧度数 privatefloatRADIANS_PER_X; //去除边框后的半径(即内圆半径) privateintVALID_RADIUS; /** * 获取水波曲线(包含圆弧部分)的Path. * * @param xOffset x方向像素偏移量. */ privatePath getWavePath(intxOffset) { if(wavePath ==null) { wavePath =newPath(); }else{ wavePath.reset(); } float[] startPoint =newfloat[2];//波浪线起点 float[] endPoint =newfloat[2];//波浪线终点 for(inti =0; i <= VALID_RADIUS *2; i +=2) { floatx = centerX - VALID_RADIUS + i; floaty = (float) (centerY + VALID_RADIUS * (1.0f + A) *2* (0.5f - progress / max) + VALID_RADIUS * A * Math.sin((xOffset + i) * RADIANS_PER_X)); //只计算内圆内部的点,边框上的忽略 if(calDistance(x, y, centerX, centerY) > VALID_RADIUS) { if(x < centerX) { continue;//左边框,继续循环 }else{ break;//右边框,结束循环 } } //第1个点 if(wavePath.isEmpty()) { startPoint[0] = x; startPoint[1] = y; wavePath.moveTo(x, y); }else{ wavePath.lineTo(x, y); } endPoint[0] = x; endPoint[1] = y; } if(wavePath.isEmpty()) { if(progress / max >=0.5f) { //满格 wavePath.moveTo(centerX, centerY - VALID_RADIUS); wavePath.addCircle(centerX, centerY, VALID_RADIUS, Path.Direction.CW); }else{ //空格 returnwavePath; } }else{ //添加圆弧部分 floatstartDegree = calDegreeByPosition(startPoint[0], startPoint[1]);//0~180 floatendDegree = calDegreeByPosition(endPoint[0], endPoint[1]);//180~360 wavePath.arcTo(circleRectF, endDegree -360, startDegree - (endDegree -360)); } returnwavePath; } privatefloatcalDistance(floatx1,floaty1,floatx2,floaty2) { return(float) Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); } //根据当前位置,计算出进度条已经转过的角度。 privatefloatcalDegreeByPosition(floatcurrentX,floatcurrentY) { floata1 = (float) (Math.atan(1.0f * (centerX - currentX) / (currentY - centerY)) / Math.PI *180); if(currentY < centerY) { a1 +=180; }elseif(currentY > centerY && currentX > centerX) { a1 +=360; } returna1 +90; } publicvoidsetMax(intmax) { this.max = max; invalidate(); } //直接设置进度值(同步) publicvoidsetProgressSync(floatprogress) { this.progress = progress; invalidate(); } /** * 自动刷新页面,创造水波效果。组件销毁后该线城将自动停止。 */ privatevoidautoRefresh() { newThread(newRunnable() { @Override publicvoidrun() { while(!detached) { xOffset += (VALID_RADIUS >>4); SystemClock.sleep(100); postInvalidate(); } } }).start(); } //标记View是否已经销毁 privatebooleandetached =false; @Override protectedvoidonDetachedFromWindow() { super.onDetachedFromWindow(); detached =true; } } |
(二)使用方法:
在xml布局中引入上述组件,然后在activity或fragment中设置属性:
代码如下 | 复制代码 |
WaterWaveView bar = (WaterWaveView) getActivity().findViewById(R.id.water_wave_view); bar.setMax(500); bar.setProgressSync(361.8f); |
相关文章
- android之视频播放系统VideoView和自定义VideoView控件的应用 07-10
- Android自定义录制视频功能 04-28
- Android自定义闹钟功能 04-27
- Android自定义View实现随手势滑动控件 04-16
- Android自定义谷歌风格ProgressBar 04-13
- Android编程实现自定义toast示例 03-06