偶然想到BimapShader 用法,发现实现水印功能,是分分钟的。所以不到十分钟,实现了,效果还不错。
啥是水印?
这个可以不用多说了,在文档的应用中是非常常用的。证明文档的所有权。通常是不可更改的。
为啥选用Drawable 实现
从Drawable 的注释可知,Drawable 相对于View 来说比较轻量,仔细体会可绘制的。不能和用户交互,也不能接受事件,静静的绘制。由于水印的场景确实不需要交互,而且可以方便的使用。所以作为Drawable 再好不过了
开始实现
- 接下来重头戏,想想水印是同一副图案出现n次,文字当然也可说是图案。如果采用canvas直接绘制图案。真的不好控制,麻烦。如果使用BitmapShader 那就容易多了。特别是Shader.TileMode.REPEAT 见识就是量身定做的。特别说一下TileMode还有TileMode.CLAMP,TileMode.MIRROR 两种。那怎么使用呢?当然是绘制一个RectF,这又不得不说Drawble 天生就是用来的。因为Drawable 的一个很重要方法,setBounds,用来确定绘制大小和位置。所以在绘制时候,直接调用getBounds() 就可使用。这里也是参考ShapeDrawable,BitmapDrawble 源码得到的。一般水印都是斜着的这怎么实现呢?两种方式,绘制的图案旋转,2,bitmapShader 旋转绘制图案。
- 拆解实现,首先要得到我们要绘制的图案。这里采用标准方式生成。
fun makeMark(): Bitmap {
val p = Paint().apply {
isAntiAlias = true
style = Paint.Style.STROKE
color = Color.parseColor("#f5b8c2")
textSize = 30f
}
val w = p.measureText(waterMark) + 20
val bitmap = Bitmap.createBitmap(w.toInt(), 40, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
canvas.save()
canvas.translate(10f, 5f)
canvas.drawText(waterMark, 0f, p.textHeight() - p.descent(), p)
canvas.restore()
return bitmap
}
以上代码可看到,通过水印文字的宽高,加上一定padding,通过canvas绘制到bitmap上,接下来绘制水印的画笔
private val paint: Paint by lazy {
Paint().apply {
isAntiAlias = true
style = Paint.Style.FILL
}
}
init {
val bs = BitmapShader(makeMark(), Shader.TileMode.REPEAT, Shader.TileMode.REPEAT)
val m = Matrix()
m.postRotate(45f)
bs.setLocalMatrix(m)
paint.shader = bs
}
常规设置paint 之后,给设置BitmapShader,然后通过Martix旋转45度。接下来是绘制
override fun draw(canvas: Canvas) {
canvas.drawRect(bounds, paint)
}
简单到不可相信,真的就只有一行代码。由于简单实现代码略粗糙,多多包涵。
我是源码
网友评论