首页 > 学院 > 开发设计 > 正文

自定义View之炫丽的进度条

2019-11-08 00:31:57
字体:
来源:转载
供稿:网友

Android自定义View之炫丽的进度条

好久没有写Blog了,昨天意外看到自己无意中写的一篇文章,访问量都有1k+,突然之间觉得写博客,分享知识是一件多么幸福的事情!今天我给大家分享一个自定义view来绘制一个项目中经常用的炫丽立体效果的进度条.虽然不怎么有难度,但是项目中经常用到,希望能帮助大家项目中的一些问题,帮到大家。 这里写图片描述

代码下载地址:http://download.csdn.net/detail/zgkxzx/9762403

实现原理 主要是通过Paint的setXfermode(Xfermode xfermode) 图像混合模式,关于paint的混合模式的知识,小编就不在这里科普了,自己到百度上面谷歌一下就知道了。下面我们找重点的地方讲解。如下,多种混合模式的效果图: 这里写图片描述 这里,我们用的的模式是SRC_IN,从效果图中,我们很清晰看出,当SRC是蓝色正方形图片,DST为橙色圆形图片时,SRC_IN效果,即为当SRC与DST重叠发生,交集部分为两图交集区域,并展现出SRC交集区域。这里,我们项目中SRC为 这里写图片描述 DST资源为通过画布画的扇形图像,由于图片源SRC是一张切图,我们不容易控制进度,那么我们通过控制扇形的区域,来实现整体画布的进度条的控制。如下图,没有找到比较好的作图工具,自己用Galaxy Note机手绘图形进行分析(画的不好,不要吐槽~~)。 这里写图片描述 当DST扇形(红色区域)在画布上扫过,与SRC的交集部分,即画布上面最终展现的区域(紫色区域),这里的扇形起始边是-270度。我们可以根据实际需要进行调整。

好了,我们不多说了,直接上源码分析。

代码实现

自定义View的步骤一般是onMeasure,onLayout,onDraw,这里我们只需要测量和绘制就行了。

第一步:初始化参数

//背景图片和进度条图片 PRivate Bitmap bgBmp; private Bitmap bgProcess; private PorterDuffXfermode mMode; private Paint mXferPaint; private RectF mOval; private Paint mTextPaint; //百分比 private int mPercent; //边长 private int sideLength; //缩放比例 private float scale = 1.0f; private void init() { bgBmp = BitmapFactory.decodeResource(getResources(), R.mipmap.ring_bg); if (processImg != null) { bgProcess = ((BitmapDrawable) processImg).getBitmap(); } else bgProcess = BitmapFactory.decodeResource(getResources(), R.mipmap.ring_bg_1); mMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN); mXferPaint = new Paint(); mXferPaint.setColor(Color.GREEN); mXferPaint.setXfermode(mMode); mXferPaint.setAntiAlias(true); mOval = new RectF(); mOval.left = 0; mOval.top = 0; mPercent = 0; mTextPaint = new Paint(); mTextPaint.setColor(textColor); mTextPaint.setTextSize(textSize); mTextPaint.setAntiAlias(true); Typeface font = Typeface.createFromAsset(context.getAssets(), textFont != null ? textFont : DEFAULR_FONT); mTextPaint.setTypeface(font); }

在初始化中,主要是对需要绘画的几个画笔进行了初始化。这里比较重要的是我们用的的PorterDuffXfermode混合图像模式,在这里采用了SRC_IN模式。画笔画出的扇形和原始进度条图片发生交集后,显示原始进度条图片的部分。在设计进度条之前,小编考虑到可扩展性,本来是准备采用DST_IN模式,这样进度条显示部分为交集的扇形部分,这样进度条的颜色通过xml倒是很方便配置,但是进度条通过drawArc方法画出来的是屏幕效果图,效果没有切片能展现立体的效果。

第二步:onMeasure方法实现测量

int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int width; int height; int bgWidth = bgBmp.getWidth(); int bgHight = bgBmp.getHeight(); if (widthMode == MeasureSpec.EXACTLY) { width = widthSize; } else { width = bgWidth; } if (heightMode == MeasureSpec.EXACTLY) { height = heightSize; } else { height = bgHight; } //得到边长,这里默认进度条为正方形的控件 sideLength = Math.min(width, height); //计算比例缩放系数 scale = (float) sideLength / bgWidth; setMeasuredDimension(sideLength, sideLength);

在测量部分,如果采用包裹方式,控件的大小为原切片背景大大小;如果EXACTLY方式,那么原切片货更加精确的长宽进行比例缩放。

第三步:关键部分onDraw方法的实现

//矩阵运算 主要是根据xml的设置对原切片进行比例缩放 Matrix matrix = new Matrix(); matrix.postScale(scale, scale); mXferPaint.setXfermode(null); canvas.drawBitmap(bgBmp, matrix, mXferPaint); //将绘制操作保存到新的图层(离屏缓存) int saveCount = canvas.saveLayer(0, 0, sideLength, sideLength, null, Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG); mOval.left = 0; mOval.top = 0; mOval.right = sideLength; mOval.bottom = sideLength; mXferPaint.setXfermode(null); //绘制扇形区域,关于-235,290这个角度,根据实际切片的角度填写,找美工妹子要就行了~~~ canvas.drawArc(mOval, -235, 290 * mPercent / MAX_PROCESS, true, mXferPaint); mXferPaint.setXfermode(mMode); canvas.drawBitmap(bgProcess, matrix, mXferPaint); //绘制进度字 String text = mPercent + ""; canvas.drawText(text, 0, text.length(), sideLength / 2 - ViewUtil.getTextWidth(mTextPaint, text) / 2, sideLength / 2 + ViewUtil.getTextHeight(mTextPaint, text) / 2, mTextPaint); canvas.restoreToCount(saveCount);

至此,代码部分也说完了,此自定义view并不怎么复杂,但是工程中经常用到,希望能帮到大家,一起学习进步… 本来是准备代码在Github和csdn各上传一份便于大家参考,可惜最近Github连接不上去了。 代码下载地址:http://download.csdn.net/detail/zgkxzx/9762403


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表