背景
最近在开发新项目时,使用了扫描二维码的功能,一般扫描二维码的效果是一条横线从上到下循环移动,这次却换成了网格图片。网上的大多数第三方库实现类似效果时 网格图片被拉伸变形。为了实现效果,只能动手写,话不多说,先看效果。(片尾附有代码地址)
横线效果

网格效果

基础属性
这里自定义了一些常见属性:
| scan_image | 扫描图片资源 |
|---|---|
| scan_duration | 扫描一次时间 ms |
| scan_width | 正方形扫描框宽度 |
| scan_bg_color | 除正方形扫描框之外的背景颜色 |
| scan_rect_width | 正方形扫描框边框宽度 |
| scan_rect_color | 正方形扫描框边框颜色 |
| scan_border_width | 扫描框四个边角线的宽度 |
| scan_border_length | 扫描框四个边角线的长度 |
| scan_border_color | 扫描框四个边角线的颜色 |
绘制背景色
首先定义正方形扫描框矩形的位置,这么默认使用屏幕中心的位置
private fun createrect() {
val leftoffset = (width - mscanwidth) / 2f
val topoffset = (height - mscanwidth) / 2f
mrectframerect =
rectf(leftoffset, topoffset, leftoffset + mscanwidth, topoffset + mscanwidth)
val scaleheight = mscanwidth.tofloat() / mlinebitmap!!.width * mlinebitmap!!.height
mlinebitmap =
bitmap.createscaledbitmap(mlinebitmap!!, mscanwidth, scaleheight.toint(), true)
}
绘制背景色
/**
* 绘制背景色
*/
private fun drawscanbackground(canvas: canvas?) {
mpaint?.style = paint.style.fill
mpaint?.color = mbackgroundcolor
val canvaswidth = canvas?.width
val canvasheight = canvas?.height
mpaint?.let {
canvas?.drawrect(0f, 0f, canvaswidth!!.tofloat(), mrectframerect!!.top, it)
canvas?.drawrect(
0f,
mrectframerect!!.top - mborderwidth / 2,
mrectframerect!!.left,
mrectframerect!!.bottom + mborderwidth / 2,
it
)
canvas?.drawrect(
mrectframerect!!.right,
mrectframerect!!.top - mborderwidth / 2,
canvaswidth!!.tofloat(),
mrectframerect!!.bottom,
it
)
canvas?.drawrect(
0f,
mrectframerect!!.bottom - mborderwidth / 2,
canvaswidth!!.tofloat(),
canvasheight!!.tofloat(),
it
)
}
}
将阴影部分分为四块,使用canvas.drawrect分别绘制。

绘制边框线
/**
* 画边框线
*/
private fun drawborderline(canvas: canvas?) {
mpaint?.color = mrectcolor
mpaint?.style = paint.style.stroke
mpaint?.strokewidth = mrectwidth.tofloat()
mrectframerect?.let { mpaint?.let { it1 -> canvas?.drawrect(it, it1) } }
}
通过上面定义的扫描框矩形,绘制扫描框的边框线。
绘制四个边角线
四个边角线为折线,使用自定义view中的path实现比较简单。
/**
* 画四个角
*/
private fun drawbordercorner(canvas: canvas?) {
mpaint?.color = mbordercolor
mpaint?.style = paint.style.stroke
val connerwidth = mborderwidth / 2
mpaint?.strokewidth = mborderwidth.tofloat()
mpath.reset()
//左上
mpath.moveto(mrectframerect!!.left, mrectframerect!!.top - connerwidth + mborderlength)
mpath.lineto(mrectframerect!!.left, mrectframerect!!.top)
mpath.lineto(mrectframerect!!.left - connerwidth + mborderlength, mrectframerect!!.top)
//右上
mpath.moveto(mrectframerect!!.right + connerwidth - mborderlength, mrectframerect!!.top)
mpath.lineto(mrectframerect!!.right, mrectframerect!!.top)
mpath.lineto(mrectframerect!!.right, mrectframerect!!.top - mborderwidth + mborderlength)
//左下
mpath.moveto(mrectframerect!!.left, mrectframerect!!.bottom + mborderwidth - mborderlength)
mpath.lineto(mrectframerect!!.left, mrectframerect!!.bottom)
mpath.lineto(mrectframerect!!.left - mborderwidth + mborderlength, mrectframerect!!.bottom)
//右下
mpath.moveto(mrectframerect!!.right, mrectframerect!!.bottom + mborderwidth - mborderlength)
mpath.lineto(mrectframerect!!.right, mrectframerect!!.bottom)
mpath.lineto(mrectframerect!!.right + mborderwidth - mborderlength, mrectframerect!!.bottom)
canvas?.drawpath(mpath, mpaint!!)
}
扫描线绘制及移动
绘制扫描线使用了canvas.drawbitmap 方法 ,通过裁剪显示位置绘制扫描图片。
/**
* 绘制扫描线
*/
private fun drawscanline(canvas: canvas?) {
canvas?.save()
canvas?.restore()
val dstgridrectf = rectf(
mrectframerect!!.left,
mrectframerect!!.top,
mrectframerect!!.right,
mrectframerect!!.top + mmovestep
)
val srcrect = rect(
0,
(mlinebitmap!!.height - dstgridrectf.height()).toint(),
mlinebitmap!!.width,
mlinebitmap!!.height
)
mlinebitmap?.let {
canvas?.drawbitmap(it, srcrect, dstgridrectf, mpaint)
}
mmovestep += dp2px(3f)
if (mmovestep >= mscanwidth + mlinebitmap!!.height / 2) {
mmovestep = 0f
}
postinvalidatedelayed(mdelaytimes.tolong())
}
这里通过调用postinvalidatedelayed 不停延迟绘制图片来实现扫描图的移动效果。
特点
像zxing 等三方库 直接使用扫描图片来绘制效果,由于扫描框是正方形,如果网格扫描图是长方形图片,则会导致被拉伸为正方形显示,图片变形。为了解决网格图的变形问题,这里对图片进行缩放处理,避免变形。
val scaleheight = mscanwidth.tofloat() / mlinebitmap!!.width * mlinebitmap!!.height
mlinebitmap =
bitmap.createscaledbitmap(mlinebitmap!!, mscanwidth, scaleheight.toint(), true)
代码简洁,不用区分是线性扫描还是网格扫描,都可以直接使用,使用时,只需传入需要的扫描图片即可。
项目地址:github.com/androidyou/scancodeview
以上就是android自定义view实现两种二维码的扫描效果的详细内容,更多关于android二维码扫描的资料请关注代码网其它相关文章!
发表评论