Android手把手编写儿童手机远程监控App之使用库zxing美化二维码

0 阅读7分钟

概述

上节嘟宝使用zxing开源库将嘟宝ID生成二维码,二维码是一种用来存储信息的二维条码,由黑白方块组成,不同排列代表不同数据。手机摄像头识别后,自动解码成文字。如下图:

Snipaste_2026-04-30_16-24-22.png

黑白方块组成的二维码,非常便于扫描识别,但于美观稍显不足,可将黑白方块更改颜色再加入Logo,生成的二维码就很好看。如上图,黑是前背景,白是后背景,如下图更改前后背景,增加中心logo图片。

Snipaste_2026-04-30_15-11-26.png

美化二维码

  • 创建QRCodeUtil类,用于创建不同样式的二维码
  • 创建showSimpleQRcode,用于显示普通二维码

普通二维码

右键com.zilong.dubao > New > Java Class 创建类QRCodeUtil 在这里插入图片描述 showSimpleQRcode函数传递两个参数

  • String content 二维码具体内容,如4a3ada95-765b-415b-b53b-d2baf1e4a4d7
  • 函数返回Bitmap,直接用于控件显示
public class QRCodeUtil {
    public static Bitmap showSimpleQRcode(String content){
        try {
            // 使用 BarcodeEncoder 生成二维码 Bitmap
            BarcodeEncoder barcodeEncoder = new BarcodeEncoder();
            Bitmap bitmap = barcodeEncoder.encodeBitmap(content, BarcodeFormat.QR_CODE, 600, 600);
            // 显示二维码
            return bitmap;
        } catch (Exception e) {
            e.printStackTrace();
            // 生成失败时的处理
            return null;
        }

    }
 }

MainActivity源码

package com.zilong.dubao;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Bitmap;
import android.os.Bundle;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ImageView qrCodeImageView = findViewById(R.id.qrCode);
        String dubaoId="4a3ada95-765b-415b-b53b-d2baf1e4a4d7";
        Bitmap bitmap=QRCodeUtil.showSimpleQRcode(dubaoId);
        qrCodeImageView.setImageBitmap(bitmap);

    }
}

activity_main源码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/qrCode"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_gravity="center" />
</LinearLayout>

效果如下:

Snipaste_2026-04-30_15-39-20.png

美化二维码前后背景

在QRCodeUtil里创建showForegroundColorQRcode,函数参数如下:

  • String content,二维码内容
  • int foregroundColor,二维码前背景
  • int backgroundColor,二维码后背景
  • 函数返回Bitmap,直接用于控件显示

showForegroundColorQRcode函数源码

public static Bitmap showForegroundColorQRcode(String content,int foregroundColor,int backgroundColor){
        try {
            // 1. 配置参数
            Map<EncodeHintType, Object> hints = new HashMap<>();
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 高容错(适合加Logo)
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            hints.put(EncodeHintType.MARGIN, 1); // 边距

            // 2. 生成原始二维码矩阵
            QRCodeWriter writer = new QRCodeWriter();
            BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, 600, 600, hints);

            // 3. 转Bitmap(自定义颜色)
            int width = bitMatrix.getWidth();
            int height = bitMatrix.getHeight();
            Bitmap qrBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
                    qrBitmap.setPixel(x, y, bitMatrix.get(x, y) ? foregroundColor : backgroundColor);
                }
            }
            return qrBitmap;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

MainActivity用法

 ImageView qrCodeImageView = findViewById(R.id.qrCode);
        String dubaoId="4a3ada95-765b-415b-b53b-d2baf1e4a4d7";
        int foreground = Color.parseColor("#1196F3"); // 前景蓝
        int background = Color.WHITE; // 背景白
        Bitmap bitmap=QRCodeUtil.showForegroundColorQRcode(dubaoId, foreground,background);
        qrCodeImageView.setImageBitmap(bitmap);

运行效果如下:

Snipaste_2026-04-30_15-54-00.png

美化二维码中间增加logo

在增加函数showLogoQRcode,用于在二维码中心增加logo,参数如下:

  • String content,二维码内容
  • Bitmap logo,中心logo图片
  • float logoSizeRatio,logo占整个二维码比例
  • 函数返回Bitmap,直接用于控件显示 showLogoQRcode函数具体实现
public static Bitmap showLogoQRcode(String content,Bitmap logo,float logoSizeRatio){
        try {
            // 1. 配置参数
            Map<EncodeHintType, Object> hints = new HashMap<>();
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 高容错(适合加Logo)
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            hints.put(EncodeHintType.MARGIN, 1); // 边距
            // 二维码大小
            int size=600;

            // 2. 生成原始二维码矩阵
            QRCodeWriter writer = new QRCodeWriter();
            BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, size, size, hints);

            // 3. 转Bitmap(自定义颜色)
            int width = bitMatrix.getWidth();
            int height = bitMatrix.getHeight();
            Bitmap qrBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
                    qrBitmap.setPixel(x, y, bitMatrix.get(x, y) ? Color.BLACK : Color.WHITE);
                }
            }
            // 4. 叠加Logo(圆形)
            if (logo != null) {
                int logoSize = (int) (size * logoSizeRatio);
                Bitmap scaledLogo = Bitmap.createScaledBitmap(logo, logoSize, logoSize, true);
                Bitmap circleLogo = getCircleBitmap(scaledLogo); // 圆形裁剪

                Bitmap resultBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
                Canvas canvas = new Canvas(resultBitmap);
                canvas.drawBitmap(qrBitmap, 0, 0, null);
                // 绘制Logo到中心
                int left = (size - logoSize) / 2;
                int top = (size - logoSize) / 2;
                canvas.drawBitmap(circleLogo, left, top, null);
                canvas.save();
                canvas.restore();

                // 回收
                qrBitmap.recycle();
                scaledLogo.recycle();
                return resultBitmap;
            }

            return qrBitmap;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }


    }
      private static Bitmap getCircleBitmap(Bitmap bitmap) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        canvas.drawCircle(bitmap.getWidth() / 2f, bitmap.getHeight() / 2f, bitmap.getWidth() / 2f, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);
        bitmap.recycle();
        return output;
    }

MainActivity用法

   ImageView qrCodeImageView = findViewById(R.id.qrCode);
        String dubaoId="4a3ada95-765b-415b-b53b-d2baf1e4a4d7";
        Bitmap logoBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
        Bitmap bitmap=QRCodeUtil.showLogoQRcode(dubaoId,logoBitmap,0.2f);
        qrCodeImageView.setImageBitmap(bitmap);

效果如下:

Snipaste_2026-04-30_16-06-48.png

终结美化,更改前后背景色与logo

在类QRCodeUtil增加新函数ShowQRCode,其参数如下

  • param content 二维码内容
  • param logo Logo位图
  • param logoSizeRatio Logo占二维码比例(建议 0.15~0.25)
  • param foregroundColor 前景色
  • param backgroundColor 背景色
  • return 生成的二维码Bitmap ShowQRCode函数源码
 public static Bitmap ShowQRCode(String content, Bitmap logo,
                                              float logoSizeRatio, int foregroundColor, int backgroundColor) {
        try {
            // 1. 配置参数
            Map<EncodeHintType, Object> hints = new HashMap<>();
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 高容错(适合加Logo)
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            hints.put(EncodeHintType.MARGIN, 1); // 边距
            // 二维码大小
            int size=600;

            // 2. 生成原始二维码矩阵
            QRCodeWriter writer = new QRCodeWriter();
            BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, size, size, hints);

            // 3. 转Bitmap(自定义颜色)
            int width = bitMatrix.getWidth();
            int height = bitMatrix.getHeight();
            Bitmap qrBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
                    qrBitmap.setPixel(x, y, bitMatrix.get(x, y) ? foregroundColor : backgroundColor);
                }
            }

            // 4. 叠加Logo(圆形)
            if (logo != null) {
                int logoSize = (int) (size * logoSizeRatio);
                Bitmap scaledLogo = Bitmap.createScaledBitmap(logo, logoSize, logoSize, true);
                Bitmap circleLogo = getCircleBitmap(scaledLogo); // 圆形裁剪

                Bitmap resultBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
                Canvas canvas = new Canvas(resultBitmap);
                canvas.drawBitmap(qrBitmap, 0, 0, null);
                // 绘制Logo到中心
                int left = (size - logoSize) / 2;
                int top = (size - logoSize) / 2;
                canvas.drawBitmap(circleLogo, left, top, null);
                canvas.save();
                canvas.restore();

                // 回收
                qrBitmap.recycle();
                scaledLogo.recycle();
                return resultBitmap;
            }

            return qrBitmap;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
      private static Bitmap getCircleBitmap(Bitmap bitmap) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        canvas.drawCircle(bitmap.getWidth() / 2f, bitmap.getHeight() / 2f, bitmap.getWidth() / 2f, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);
        bitmap.recycle();
        return output;
    }

MainActivity用法

 ImageView qrCodeImageView = findViewById(R.id.qrCode);
        String dubaoId="4a3ada95-765b-415b-b53b-d2baf1e4a4d7";
        Bitmap logoBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
        int foreground = Color.parseColor("#2196F3"); // 前景蓝
        int background = Color.YELLOW; // 背景白
        Bitmap qrBitmap = QRCodeUtil.ShowQRCode(
                dubaoId, logoBitmap, 0.2f, foreground, background);
        qrCodeImageView.setImageBitmap(qrBitmap);

效果如下:

Snipaste_2026-04-30_16-21-00.png 至此二维码美化完成。以下是QRCodeUtil全部内容。

package com.zilong.dubao;

import android.content.Context;
import android.graphics.*;
import android.os.Environment;

import com.google.zxing.*;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.journeyapps.barcodescanner.BarcodeEncoder;

import java.io.File;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Map;

public class QRCodeUtil {

    public static Bitmap showSimpleQRcode(String content){
        try {
            // 使用 BarcodeEncoder 生成二维码 Bitmap
            BarcodeEncoder barcodeEncoder = new BarcodeEncoder();
            Bitmap bitmap = barcodeEncoder.encodeBitmap(content, BarcodeFormat.QR_CODE, 600, 600);
            // 显示二维码
            return bitmap;
        } catch (Exception e) {
            e.printStackTrace();
            // 生成失败时的处理
            return null;
        }

    }

    public static Bitmap showForegroundColorQRcode(String content,int foregroundColor,int backgroundColor){
        try {
            // 1. 配置参数
            Map<EncodeHintType, Object> hints = new HashMap<>();
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 高容错(适合加Logo)
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            hints.put(EncodeHintType.MARGIN, 1); // 边距

            // 2. 生成原始二维码矩阵
            QRCodeWriter writer = new QRCodeWriter();
            BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, 600, 600, hints);

            // 3. 转Bitmap(自定义颜色)
            int width = bitMatrix.getWidth();
            int height = bitMatrix.getHeight();
            Bitmap qrBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
                    qrBitmap.setPixel(x, y, bitMatrix.get(x, y) ? foregroundColor : backgroundColor);
                }
            }
            return qrBitmap;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }
    public static Bitmap showLogoQRcode(String content,Bitmap logo,float logoSizeRatio){
        try {
            // 1. 配置参数
            Map<EncodeHintType, Object> hints = new HashMap<>();
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 高容错(适合加Logo)
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            hints.put(EncodeHintType.MARGIN, 1); // 边距
            // 二维码大小
            int size=600;

            // 2. 生成原始二维码矩阵
            QRCodeWriter writer = new QRCodeWriter();
            BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, size, size, hints);

            // 3. 转Bitmap(自定义颜色)
            int width = bitMatrix.getWidth();
            int height = bitMatrix.getHeight();
            Bitmap qrBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
                    qrBitmap.setPixel(x, y, bitMatrix.get(x, y) ? Color.BLACK : Color.WHITE);
                }
            }
            // 4. 叠加Logo(圆形)
            if (logo != null) {
                int logoSize = (int) (size * logoSizeRatio);
                Bitmap scaledLogo = Bitmap.createScaledBitmap(logo, logoSize, logoSize, true);
                Bitmap circleLogo = getCircleBitmap(scaledLogo); // 圆形裁剪

                Bitmap resultBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
                Canvas canvas = new Canvas(resultBitmap);
                canvas.drawBitmap(qrBitmap, 0, 0, null);
                // 绘制Logo到中心
                int left = (size - logoSize) / 2;
                int top = (size - logoSize) / 2;
                canvas.drawBitmap(circleLogo, left, top, null);
                canvas.save();
                canvas.restore();

                // 回收
                qrBitmap.recycle();
                scaledLogo.recycle();
                return resultBitmap;
            }

            return qrBitmap;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }


    }
        /**
         * 生成带Logo的彩色二维码(返回Bitmap)
         * @param content 二维码内容
         * @param logo Logo位图
         * @param logoSizeRatio Logo占二维码比例(建议 0.15~0.25)
         * @param foregroundColor 前景色
         * @param backgroundColor 背景色
         * @return 生成的二维码Bitmap
         */


        public static Bitmap ShowQRCode(String content, Bitmap logo,
                                              float logoSizeRatio, int foregroundColor, int backgroundColor) {
        try {
            // 1. 配置参数
            Map<EncodeHintType, Object> hints = new HashMap<>();
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 高容错(适合加Logo)
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            hints.put(EncodeHintType.MARGIN, 1); // 边距
            // 二维码大小
            int size=600;

            // 2. 生成原始二维码矩阵
            QRCodeWriter writer = new QRCodeWriter();
            BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, size, size, hints);

            // 3. 转Bitmap(自定义颜色)
            int width = bitMatrix.getWidth();
            int height = bitMatrix.getHeight();
            Bitmap qrBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
                    qrBitmap.setPixel(x, y, bitMatrix.get(x, y) ? foregroundColor : backgroundColor);
                }
            }

            // 4. 叠加Logo(圆形)
            if (logo != null) {
                int logoSize = (int) (size * logoSizeRatio);
                Bitmap scaledLogo = Bitmap.createScaledBitmap(logo, logoSize, logoSize, true);
                Bitmap circleLogo = getCircleBitmap(scaledLogo); // 圆形裁剪

                Bitmap resultBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
                Canvas canvas = new Canvas(resultBitmap);
                canvas.drawBitmap(qrBitmap, 0, 0, null);
                // 绘制Logo到中心
                int left = (size - logoSize) / 2;
                int top = (size - logoSize) / 2;
                canvas.drawBitmap(circleLogo, left, top, null);
                canvas.save();
                canvas.restore();

                // 回收
                qrBitmap.recycle();
                scaledLogo.recycle();
                return resultBitmap;
            }

            return qrBitmap;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 把Bitmap裁成圆形
     */
    private static Bitmap getCircleBitmap(Bitmap bitmap) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        canvas.drawCircle(bitmap.getWidth() / 2f, bitmap.getHeight() / 2f, bitmap.getWidth() / 2f, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);
        bitmap.recycle();
        return output;
    }

    /**
     * 保存Bitmap到本地(DCIM/QRCode)
     */
    public static File saveBitmapToFile(Context context, Bitmap bitmap, String fileName) {
        File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "QRCode");
        if (!dir.exists()) dir.mkdirs();
        File file = new File(dir, fileName + ".png");
        try (FileOutputStream out = new FileOutputStream(file)) {
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
            out.flush();
            return file;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}