Android自定義View實現(xiàn)兩種二維碼的掃描效果
背景
最近在開發(fā)新項目時,使用了掃描二維碼的功能,一般掃描二維碼的效果是一條橫線從上到下循環(huán)移動,這次卻換成了網(wǎng)格圖片。網(wǎng)上的大多數(shù)第三方庫實現(xiàn)類似效果時 網(wǎng)格圖片被拉伸變形。為了實現(xiàn)效果,只能動手寫,話不多說,先看效果。(片尾附有代碼地址)
橫線效果
網(wǎng)格效果
基礎(chǔ)屬性
這里自定義了一些常見屬性:
scan_image | 掃描圖片資源 |
---|---|
scan_duration | 掃描一次時間 ms |
scan_width | 正方形掃描框?qū)挾?/td> |
scan_bg_color | 除正方形掃描框之外的背景顏色 |
scan_rect_width | 正方形掃描框邊框?qū)挾?/td> |
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實現(xiàn)比較簡單。
/** * 畫四個角 */ 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()) }
這里通過調(diào)用postInvalidateDelayed 不停延遲繪制圖片來實現(xiàn)掃描圖的移動效果。
特點
像zxing 等三方庫 直接使用掃描圖片來繪制效果,由于掃描框是正方形,如果網(wǎng)格掃描圖是長方形圖片,則會導致被拉伸為正方形顯示,圖片變形。為了解決網(wǎng)格圖的變形問題,這里對圖片進行縮放處理,避免變形。
val scaleHeight = mScanWidth.toFloat() / mLineBitmap!!.width * mLineBitmap!!.height mLineBitmap = Bitmap.createScaledBitmap(mLineBitmap!!, mScanWidth, scaleHeight.toInt(), true)
代碼簡潔,不用區(qū)分是線性掃描還是網(wǎng)格掃描,都可以直接使用,使用時,只需傳入需要的掃描圖片即可。
項目地址:github.com/AndroidYou/ScanCodeView
以上就是Android自定義View實現(xiàn)兩種二維碼的掃描效果的詳細內(nèi)容,更多關(guān)于Android二維碼掃描的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android中利用xml文件布局修改Helloworld程序
這篇文章主要介紹了Android中利用xml文件布局修改Helloworld程序 的相關(guān)資料,需要的朋友可以參考下2016-07-07Android開發(fā)之DatePickerDialog、TimePickerDialog時間日期對話框用法示例
這篇文章主要介紹了Android開發(fā)之DatePickerDialog、TimePickerDialog時間日期對話框用法,結(jié)合實例形式分析了Android使用DatePickerDialog、TimePickerDialog顯示日期時間相關(guān)操作技巧,需要的朋友可以參考下2019-03-03Android跨進程傳遞大數(shù)據(jù)的方法實現(xiàn)
這篇文章主要介紹了Android跨進程傳遞大數(shù)據(jù)的方法實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-03-03僅5步搞定Android開發(fā)環(huán)境部署 Android開發(fā)環(huán)境搭建教程
僅5步搞定Android開發(fā)環(huán)境部署,這篇文章主要為大家詳細介紹了Android開發(fā)環(huán)境搭建教程,感興趣的小伙伴們可以參考一下2016-02-02Android RecyclerView自定義上拉和下拉刷新效果
這篇文章主要為大家詳細介紹了Android RecyclerView自定義上拉和下拉刷新效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-02-02