自定义ZXing Android Embedded扫描框样式

前言:

非常多应用需要集成二维码扫描功能,需要自定义样式的话目前只有自己手动绘制,这里只简单做个例子,个性化需求需要自己再根据需求绘制

compile'com.journeyapps:zxing-android-embedded:3.6.0'

compile'com.google.zxing:core:3.3.0'

eg:


代码:

直接上代码,重点在onDraw方法中,注释比较详细了,没有封装,有兴趣的小伙伴可以封装一下,偷懒的同学可以直接使用。

/**

* Created by Administrator on 2018/3/8.

*/

internal class CustomViewfinderView(context:Context, attrs: AttributeSet) : ViewfinderView(context, attrs) {

/* ****************************************** 边角线相关属性 ************************************************/

    /**

* "边角线长度/扫描边框长度"的占比 (比例越大,线越长)

*/

    var mLineRate =0.05f

    /**

* 边角线厚度 (建议使用dp)

*/

    var mLineDepth =TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2f, resources.displayMetrics)

/**

* 边角线颜色

*/

    var mLineColor = getContext().resources.getColor(R.color.colorAccent)

/* ******************************************* 扫描线相关属性 ************************************************/

    /**

* 扫描线起始位置

*/

    var mScanLinePosition =0

    /**

* 扫描线厚度

*/

    var mScanLineDepth =TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2f, resources.displayMetrics)

/**

* 扫描线每次重绘的移动距离

*/

    var mScanLineDy =TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3f, resources.displayMetrics)

/**

* 线性梯度

*/

    lateinit var mLinearGradient:LinearGradient

    /**

* 线性梯度位置

*/

    var mPositions =floatArrayOf(0f, 0.5f, 1f)

/**

* 线性梯度各个位置对应的颜色值

*/

    lateinit var nowScanRect:Rect

    var buttonRect:RectF? =null

    var laserColor_center = getContext().resources.getColor(R.color.colorAccent)

var laserColor_light = getContext().resources.getColor(R.color.colorAccent_light)

var tip = "tip"

var text_btn = "个性化需求"

var screenWidth =0

    var screenHeight =0

    //扫描线渐变色

    var mScanLineColor =intArrayOf(laserColor_light, laserColor_center, laserColor_light)

init {

val manager = (getContext()as Activity).windowManager

        val outMetrics = DisplayMetrics()

manager.defaultDisplay.getMetrics(outMetrics)

screenWidth = outMetrics.widthPixels

        screenHeight = outMetrics.heightPixels

        var w =screenWidth *3 /5

        var marginL =screenWidth /5

        var marginT =screenHeight /4

        nowScanRect = Rect(marginL, marginT, w + marginL, w + marginT)

}

fun drawText(canvas:Canvas, mScanRect:Rect) {

val mTxetPaint = Paint()

mTxetPaint.apply {

            color =context.resources.getColor(R.color.common_white)

textSize =DisplayUtils.dp2px(context, 14f).toFloat()

style =Paint.Style.FILL

            textAlign =Paint.Align.CENTER

        }

        canvas.drawText(tip, (screenWidth /2).toFloat(), (mScanRect.top -DisplayUtils.dp2px(context, 22f)).toFloat(), mTxetPaint)

}

fun drawButton(canvas:Canvas, mScanRect:Rect) {

val buttonPaint = Paint()

buttonPaint.apply {

            isAntiAlias =true

            color =context.resources.getColor(R.color.common_white)

strokeWidth =1f

            style =Paint.Style.STROKE

        }

        var height =DisplayUtils.dp2px(context, 40f)

var left = mScanRect.left + (mScanRect.right - mScanRect.left) /6

        var top = mScanRect.bottom +DisplayUtils.dp2px(context, 48f)

var right = mScanRect.right - (mScanRect.right - mScanRect.left) /6

        var bottom = mScanRect.bottom +DisplayUtils.dp2px(context, 48f) + height

buttonRect = RectF(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat())

buttonRect?.let {

            canvas.drawRoundRect(it, DisplayUtils.dp2px(context, 20f).toFloat(), DisplayUtils.dp2px(context, 20f).toFloat(), buttonPaint)

}

        buttonPaint.apply {

            color =context.resources.getColor(R.color.common_white)

textSize =DisplayUtils.dp2px(context, 14f).toFloat()

style =Paint.Style.FILL

            textAlign =Paint.Align.CENTER

        }

        var fontMetrics = buttonPaint.fontMetricsInt

        // var baseLine = buttonRect.centerY() + (fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.descent

        buttonRect?.let {

            val baseLine = (it.top +it.bottom - fontMetrics.top - fontMetrics.bottom) /2

            canvas.drawText(text_btn, it.centerX(), baseLine, buttonPaint)

}

    }

@SuppressLint("DrawAllocation")

override fun onDraw(canvas:Canvas) {

refreshSizes()

if (framingRect ==null ||previewFramingRect ==null) {

return

        }

//  framingRect = nowScanRect

        val frame =nowScanRect

        val previewFrame =previewFramingRect

        val width = canvas.width

        val height = canvas.height

        // Draw the exterior (i.e. outside the framing rect) darkened

        paint.color =if (resultBitmap !=null)resultColor else maskColor

        canvas.drawRect(0f, 0f, width.toFloat(), frame.top.toFloat(), paint)

canvas.drawRect(0f, frame.top.toFloat(), frame.left.toFloat(), (frame.bottom +1).toFloat(), paint)

canvas.drawRect((frame.right +1).toFloat(), frame.top.toFloat(), width.toFloat(), (frame.bottom +1).toFloat(), paint)

canvas.drawRect(0f, (frame.bottom +1).toFloat(), width.toFloat(), height.toFloat(), paint)

//  drawText(canvas, frame)

drawButton(canvas, frame)

//绘制4个角

        paint.color =mLineColor

        // 定义画笔的颜色

//左上-横线

        canvas.drawRect(frame.left.toFloat() -mLineDepth,

                frame.top.toFloat() -mLineDepth,

                frame.left + frame.width() *mLineRate,

                frame.top.toFloat(), paint)

//左上-纵线

        canvas.drawRect(frame.left.toFloat() -mLineDepth, frame.top.toFloat(), frame.left.toFloat(), frame.top + frame.height() *mLineRate, paint)

//右上-横线

        canvas.drawRect(frame.right - frame.width() *mLineRate, frame.top.toFloat() -mLineDepth, frame.right.toFloat() +mLineDepth, frame.top.toFloat(), paint)

//右上-纵线

        canvas.drawRect(frame.right.toFloat(), frame.top.toFloat() -mLineDepth, frame.right.toFloat() +mLineDepth, frame.top + frame.height() *mLineRate, paint)

//左下-横线

        canvas.drawRect(frame.left.toFloat() -mLineDepth, frame.bottom.toFloat(), frame.left + frame.width() *mLineRate, frame.bottom.toFloat() +mLineDepth, paint)

//左下-纵线

        canvas.drawRect(frame.left.toFloat() -mLineDepth, frame.bottom - frame.height() *mLineRate, frame.left.toFloat(), frame.bottom.toFloat(), paint)

//右下-横线

        canvas.drawRect(frame.right - frame.width() *mLineRate, frame.bottom.toFloat(), frame.right.toFloat() +mLineDepth, frame.bottom.toFloat() +mLineDepth, paint)

//右下-纵线

        canvas.drawRect(frame.right.toFloat(), frame.bottom - frame.height() *mLineRate, frame.right.toFloat() +mLineDepth, frame.bottom.toFloat() +mLineDepth, paint)

if (resultBitmap !=null) {

// Draw the opaque result bitmap over the scanning rectangle

            paint.alpha =ViewfinderView.CURRENT_POINT_OPACITY

            canvas.drawBitmap(resultBitmap, null, frame, paint)

}else {

//  drawLaserLine(canvas,frame)

// 绘制扫描线

            mScanLinePosition +=mScanLineDy.toInt()

if (mScanLinePosition > frame.height()) {

mScanLinePosition =0

            }

mLinearGradient = LinearGradient(frame.left.toFloat(), (frame.top +mScanLinePosition).toFloat(), frame.right.toFloat(), (frame.top +mScanLinePosition).toFloat(), mScanLineColor, mPositions, Shader.TileMode.CLAMP)

paint.shader =mLinearGradient

            canvas.drawRect(frame.left.toFloat(), (frame.top +mScanLinePosition).toFloat(), frame.right.toFloat(), frame.top.toFloat() +mScanLinePosition.toFloat() +mScanLineDepth, paint)

paint.shader =null

            val scaleX = frame.width() / previewFrame.width().toFloat()

val scaleY = frame.height() / previewFrame.height().toFloat()

val currentPossible =possibleResultPoints

            val currentLast =lastPossibleResultPoints

            val frameLeft = frame.left

            val frameTop = frame.top

            if (currentPossible.isEmpty()) {

lastPossibleResultPoints =null

            }else {

possibleResultPoints = ArrayList(5)

lastPossibleResultPoints = currentPossible

paint.alpha =ViewfinderView.CURRENT_POINT_OPACITY

                paint.color =resultPointColor

                for (pointin currentPossible) {

canvas.drawCircle((frameLeft + (point.x * scaleX).toInt()).toFloat(), (frameTop + (point.y * scaleY).toInt()).toFloat(), ViewfinderView.POINT_SIZE.toFloat(), paint)

}

}

if (currentLast !=null) {

paint.alpha =ViewfinderView.CURRENT_POINT_OPACITY /2

                paint.color =resultPointColor

                val radius =ViewfinderView.POINT_SIZE /2.0f

                for (pointin currentLast) {

canvas.drawCircle((frameLeft + (point.x * scaleX).toInt()).toFloat(), (frameTop + (point.y * scaleY).toInt()).toFloat(), radius, paint)

}

}

}// Request another update at the animation interval, but only repaint the laser line, // not the entire viewfinde

// rmask.

        postInvalidateDelayed(CUSTOME_ANIMATION_DELAY, frame.left, frame.top, frame.right, frame.bottom)

}

    interface InputView {

fun inputClick()

}

var inputView: InputView? =null

    fun setInputView(doInput: () ->Unit) {

this.inputView =object : InputView {

override fun inputClick() {

doInput()

}

}

}

override fun onTouchEvent(event:MotionEvent?):Boolean {

when (event?.action) {

MotionEvent.ACTION_DOWN -> {

val x = event?.x

                val y = event?.y

                buttonRect?.let {

                    if (it.contains(x, y)) {

inputView?.inputClick()

}

}

            }

}

return super.onTouchEvent(event)

}

companion object {

/**

* 重绘时间间隔

*/

        val CUSTOME_ANIMATION_DELAY:Long =16

    }

}

使用:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:app="http://schemas.android.com/apk/res-auto"

    android:layout_width="match_parent"

    android:layout_height="match_parent">

<com.journeyapps.barcodescanner.BarcodeView

        android:id="@+id/zxing_barcode_surface"

        android:layout_width="match_parent"

        android:layout_height="match_parent" />

<com.young.demo.CustomViewfinderView

        android:id="@+id/zxing_viewfinder_view"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        />

</FrameLayout>

so easy!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容