背景
最近在开发新项目时,使用了扫描二维码的功能,一般扫描二维码的效果是一条横线从上到下循环移动,这次却换成了网格图片。网上的大多数第三方库实现类似效果时 网格图片被拉伸变形。为了实现效果,只能动手写,话不多说,先看效果。(片尾附有代码地址)
横线效果
网格效果
基础属性
这里自定义了一些常见属性:
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)
代码简洁,不用区分是线性扫描还是网格扫描,都可以直接使用,使用时,只需传入需要的扫描图片即可。
项目地址:
以上就是android自定义view实现两种二维码的扫描效果的详细内容,更多关于android二维码扫描的资料请关注其它相关文章!