镂空的文字反色的加载进度按钮的实现

最近突然要用到带有进度的下载按钮,暂时找不到满意的轮子,自己动手丰衣足食。
两个主要特性:

  • 文字反色
  • 按钮镂空透明

图片名称

文字的反色处理,有两种方案。
一种是使用两层布局,两层布局分别使用反色来处理,再通过clipPath切割上层布局,切割掉的部分漏出下层的反色布局,以此来实现进度反色的效果。
第二种则是使用canvas绘图,通过xfermode叠加绘制来实现镂空效果。

这里使用第二种方案,原因如下:
1.布局叠加无法实现反色部分透明,无法看到按钮下的布局。
2.太low

实现文字反色比较简单,通过XOR类型的文字paint叠加绘制到底层button上就可以了。

paintTxt.xfermode = PorterDuffXfermode(PorterDuff.Mode.XOR)

注意要先绘button,再绘text。

当然本篇的核心并不在如何使用canvas来绘制控件,而是如何绘制出底部透明镂空的view,恩,奇技淫巧.

首先看一下这个button的特性:
1.文字反色
2.镂空的部位透明
3.边框
4.圆角
5.进度

这里的圆角和透明是个关键,设计的时候卡在了这里好久。

绘制步骤分为4个
需要定义四个paint分别对应四次绘制
paint的定义放在构造方法中,绘制在onDraw方法中
reactF是组件将要绘制的矩形区域,在onMeasure中测量得到。
maskReacF是组件第二部裁剪绘制的矩形区域,左边界根据进度控制,上右下和组件边界相同。

一、绘制中心颜色

paint定义

paintBg.color = color
paintBg.isAntiAlias = true

绘制

canvas.drawRoundRect(rectF, radius, radius, paintBg)

我是图

二、根据进度裁剪中心颜色

paint定义

paintFront.color = color
paintFront.isAntiAlias = true
paintFront.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)

绘制

maskRectF.left = rectF.left + progress * (rectF.right - rectF.left)
canvas.drawRect(maskRectF, paintFront)

我是图

三、绘制边框

paint定义

paintBorder.color = color
paintBorder.isAntiAlias = true
paintBorder.strokeWidth = borderWidth
paintBorder.style = Paint.Style.STROKE

绘制

canvas.drawRoundRect(rectF, radius, radius, paintBorder)

我是图

四、绘制文字

paint定义

paintTxt.color = color
paintTxt.textSize = textSize
paintTxt.isAntiAlias = true
paintTxt.xfermode = PorterDuffXfermode(PorterDuff.Mode.XOR)
paintTxt.textAlign = Paint.Align.LEFT

绘制

val text = "暂停"
paintTxt.getTextBounds(text, 0, text.length, txtRect)
val textX = (viewWidth / 2) - txtRect.centerX()
val textY = (viewHeight / 2) - txtRect.centerY()
canvas.drawText(text, textX.toFloat(), textY.toFloat(), paintTxt)

我是图

搞定。

接下来把一些参数(尺寸,颜色,边框,圆角,状态,进度等)进行封装,留出接口供业务调用即可,这里不再赘述。

轮子地址:https://github.com/NightFarmer/ProgressView

文章目录
,