Android自定义View实现两种二维码的扫描效果

这篇文章主要为大家详细介绍了Android如何自定义View实现两种二维码的扫描效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

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

横线效果

网格效果

基础属性
这里自定义了一些常见属性:

绘制背景色
首先定义正方形扫描框矩形的位置,这么默认使用屏幕中心的位置

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二维码扫描的资料请关注vb.net教程C#教程python教程SQL教程access 2010教程xin3721自学网

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值