Android二维码的基础使用(一):利用Zxing生成自定义二维码

概述

二维码的应用已经可以说是非常广泛了,那么如何在当前的app项目中生成自定义二维码,本文对采用Google开源库Zxing去生成二维码的流程进行简单说明。

系列文章:

Android二维码的基础使用(一):利用Zxing生成自定义二维码
Android二维码的基础使用(二):保存和分享
Android二维码的基础使用(三):二维码扫描Demo实现

使用

1. 引入jar包

build.gradle文件中引入jar包。

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

2. 基本使用

生成一个二维码主要包含如下几个步骤:

  1. 设置二维码的配置,如字符转码格式。容错率以及空白边距等等参数。
  2. 通过QRWriter生成位矩阵BitMatrix对象
  3. 创建像素数组,并根据位矩阵对象逐项赋值颜色。
  4. 根据像素数组创建bitmap对象生成二维码图片。

示例代码如下:

    /**
     * 生成简单二维码
     *
     * @param content                字符串内容
     * @param width                  二维码宽度
     * @param height                 二维码高度
     * @param characterSet          编码方式(一般使用UTF-8)
     * @param errorCorrectionLevel 容错率 L:7% M:15% Q:25% H:35%
     * @param margin                 空白边距(二维码与边框的空白区域)
     * @param colorBlack            黑色色块
     * @param colorWhite            白色色块
     * @return BitMap
     */
    fun createQRCodeBitmap(
        content: String?, width: Int, height: Int,
        characterSet: String?, errorCorrectionLevel: String?,
        margin: String?, colorBlack: Int, colorWhite: Int
    ): Bitmap? {
        // 字符串内容判空
        if (TextUtils.isEmpty(content)) {
            return null
        }
        // 宽和高>=0
        if (width < 0 || height < 0) {
            return null
        }
        return try {
            /** 1.设置二维码相关配置  */
            val hints =
                Hashtable<EncodeHintType, String?>()
            // 字符转码格式设置
            if (!TextUtils.isEmpty(characterSet)) {
                hints[EncodeHintType.CHARACTER_SET] = characterSet
            }
            // 容错率设置
            if (!TextUtils.isEmpty(errorCorrectionLevel)) {
                hints[EncodeHintType.ERROR_CORRECTION] = errorCorrectionLevel
            }
            // 空白边距设置
            if (!TextUtils.isEmpty(margin)) {
                hints[EncodeHintType.MARGIN] = margin
            }
            /** 2.将配置参数传入到QRCodeWriter的encode方法生成BitMatrix(位矩阵)对象  */
            val bitMatrix =
                QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints)

            /** 3.创建像素数组,并根据BitMatrix(位矩阵)对象为数组元素赋颜色值  */
            val pixels = IntArray(width * height)
            for (y in 0 until height) {
                for (x in 0 until width) {
                    //bitMatrix.get(x,y)方法返回true是黑色色块,false是白色色块
                    if (bitMatrix[x, y]) {
                        pixels[y * width + x] = colorBlack //黑色色块像素设置,可以通过传入不同的颜色实现彩色二维码,例如Color.argb(1,55,206,141)等设置不同的颜色。
                    } else {
                        pixels[y * width + x] = colorWhite // 白色色块像素设置
                    }
                }
            }
            /** 4.创建Bitmap对象,根据像素数组设置Bitmap每个像素点的颜色值,并返回Bitmap对象  */
            val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
            bitmap.setPixels(pixels, 0, width, 0, 0, width, height)
            bitmap
        } catch (e: WriterException) {
            e.printStackTrace()
            null
        }
        //调用示例代码
//        imageView.setImageBitmap(QRCodeBitmap.newInstance().createQRCodeBitmap("test",80,80,
//                "UTF-8","L","1", Color.BLACK,Color.WHITE));
    }

参数说明:

  • characterSet:编码方式,通常采用UTF-8,格式不对可能会导致乱码。
  • errorCorrectionLevel:容错率,即使二维码破损了一部分也能扫描的程度,容错率越高,二维码能存储的内容也会随之变小。主要等级分为:L:7% M:15% Q:25% H:35%。
  • 颜色:颜色对应二维码生成时的颜色显示,可以通过设置不用的颜色来实现彩色二维码,如Color.argb(1,55,206,141)

3. 二维码嵌入logo

常见的二维码中还可以嵌入logo,添加logo就是图片合成,将logo图片以一定比例合成在原二维码图片上,即将logo图片直接拼接在二维码的中心位置,示例代码如下:

 /***
     * 为二维码添加logo
     *
     * @param srcBitmap 二维码图片
     * @param logoBitmap logo图片
     * @param percent logo比例
     * @return 生成的最终的图片
     */
    fun addLogo(srcBitmap: Bitmap?, logoBitmap: Bitmap?, percent: Float): Bitmap? {
        //判断参数是否正确
        if (srcBitmap == null)
            return null
        if (logoBitmap == null)
            return srcBitmap
        //输入logo图片比例错误自动纠正为默认的0.2f
        var logoPercent = percent
        if (percent < 0 || percent > 1)
            logoPercent = 0.2f

        //分别获取bitmap图片的大小
        var sHeight = srcBitmap.height
        var sWidth = srcBitmap.width
        var lHeight = logoBitmap.height
        var lWidth = logoBitmap.width

        //获取缩放比例
        var scareWidth = sHeight * logoPercent / lWidth
        var scareHeight = sWidth * logoPercent / lHeight

        //使用canvas重新绘制bitmap
        var bitmap = Bitmap.createBitmap(sWidth, sHeight, Bitmap.Config.ARGB_8888)
        var canvas = Canvas(bitmap)
        canvas.drawBitmap(srcBitmap, 0f, 0f, null)
        canvas.scale(
            scareWidth,
            scareHeight,
            (sWidth / 2).toFloat(),
            (sHeight / 2).toFloat()
        )   //设置缩放中心基点
        canvas.drawBitmap(
            logoBitmap,
            (sWidth/2 - lWidth / 2).toFloat(),
            (sHeight/2 - lHeight / 2).toFloat(),
            null
        )
        return bitmap
    }

4. 添加图片展示效果

和生成不同颜色的二维码本质相同,其实现的基本逻辑就是在绘制二维码的时候使用图片的像素块去取代当前二维码的非白色的像素块,其他的步骤和基本生成二维码的流程没有区别,部分示例代码如下:

//bitmapOther为传入的需要展示的图片效果的图片,类型为bitmap
//先根据二维码的大小生成等大的bitmap,方便直接获取对应的像素块
var bitmapExtra: Bitmap? = null
if (bitmapOther != null) {
    bitmapExtra = Bitmap.createScaledBitmap(bitmapOther, width, height, false)
}

...

if (bitMatrix.get(x, y)) {// 像素块设置
    if (bitmapExtra != null) {
    //图片不为null,则将黑色色块换为新位图的像素。
        pixels[y * width + x] = bitmapExtra.getPixel(x, y);
    } else {
    //无图片时默认仍然为输入颜色像素块
        pixels[y * width + x] = colorBlack;
    }
} else {
    pixels[y * width + x] = colorWhite;// 白色色块像素设置
}

如果图片的大部分颜色都比较浅,使用上述方法会影响到扫描效果,如果需要使用二维码上附加图片效果,尽量使用颜色较深的图片。

后续文章

Android二维码的基础使用(二):保存和分享

参考文章及Demo

官方地址

demo地址

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

推荐阅读更多精彩内容