二维码,是连接线下与线上最便捷的通道。作为 Android 开发人员,我们如何从 URL 快速生成二维码?本文将从一个真实需求出发,介绍二维码的生成、样式美化、截图保存等完整技术流程。含源码、边距优化、UI圆角封装、Dialog截图技巧。
一、故事的起点:扫码跳转,最简单的入口
“能不能直接生成一个二维码?我们把活动链接放进去,用户扫一下就进页面。”
这句话来自产品经理的一次例会。起初,这只是一个很小的建议,但当我们从运营推广场景、用户便捷交互、品牌美化呈现等多个维度考量后,发现它非常有价值。
于是,一个二维码生成器的小任务摆在了我们 Android 开发面前。
产品需求总结
功能点 | 描述 |
---|---|
输入 | 一个 URL 字符串 |
输出 | 高质量二维码 |
要求 1 | 不允许出现多余白边 |
要求 2 | 支持尺寸自定义 |
要求 3 | 支持嵌入至美观 UI 样式中 |
要求 4 | 可截图保存分享 |
二、技术选型与依赖引入
为什么选择 ZXing?
在二维码领域,Google 的 ZXing 是最常用的开源解决方案,成熟、稳定、文档齐全,支持多种编码格式,且体积小巧。
// app/build.gradle
implementation 'com.google.zxing:core:3.4.1'
三、二维码生成核心逻辑(Java版)
避免白边的关键参数
hints.put(EncodeHintType.MARGIN, 0); // 设置边距为0
完整封装实现(自动裁剪+透明背景)
public static Bitmap generateQRCode(String url, int width, int height) {
try {
QRCodeWriter writer = new QRCodeWriter();
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.MARGIN, 0); // 去除边距
BitMatrix bitMatrix = writer.encode(url, BarcodeFormat.QR_CODE, width, height, hints);
int[] rect = bitMatrix.getEnclosingRectangle(); // 获取有效二维码区域
int resultWidth = rect[2];
int resultHeight = rect[3];
BitMatrix croppedMatrix = new BitMatrix(resultWidth, resultHeight);
for (int x = 0; x < resultWidth; x++) {
for (int y = 0; y < resultHeight; y++) {
if (bitMatrix.get(x + rect[0], y + rect[1])) {
croppedMatrix.set(x, y);
}
}
}
Bitmap bitmap = Bitmap.createBitmap(resultWidth, resultHeight, Bitmap.Config.ARGB_8888);
for (int x = 0; x < resultWidth; x++) {
for (int y = 0; y < resultHeight; y++) {
bitmap.setPixel(x, y, croppedMatrix.get(x, y) ? Color.BLACK : Color.TRANSPARENT);
}
}
return bitmap;
} catch (WriterException e) {
Log.e("QRCode", "二维码生成失败", e);
return null;
}
}
示例调用:
ImageView iv = findViewById(R.id.ivQRCode);
Bitmap qr = generateQRCode("https://example.com", 500, 500);
iv.setImageBitmap(qr);
四、二维码UI美化:圆角边框+背景透明
自定义Drawable实现圆角边框(渐变边框 + 半透明背景)
<!-- res/drawable/bg_qrcode_border.xml -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 半透明黑色底 -->
<item>
<shape android:shape="rectangle">
<solid android:color="#66000000" />
<corners android:radius="20dp" />
</shape>
</item>
<!-- 渐变描边 -->
<item android:left="1dp" android:top="1dp" android:right="1dp" android:bottom="1dp">
<shape android:shape="rectangle">
<stroke android:width="2dp">
<gradient
android:startColor="#48CA94"
android:endColor="#1CB9BB"
android:angle="90" />
</stroke>
<corners android:radius="20dp" />
</shape>
</item>
</layer-list>
ImageView 示例引用
<ImageView
android:id="@+id/ivQRCode"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center"
android:background="@drawable/bg_qrcode_border"
android:scaleType="fitCenter" />
五、封装为工具类,便于调用复用
public class QRCodeUtil {
public static Bitmap createQRCode(String content, int width, int height) {
return generateQRCode(content, width, height);
}
}
调用方式:
Bitmap bitmap = QRCodeUtil.createQRCode("https://example.com", 500, 500);
imageView.setImageBitmap(bitmap);
六、DialogFragment 中截图保存二维码
为什么要截图?
有时二维码展示在 DialogFragment
或嵌套布局中,直接保存二维码不方便,可将整个 View 渲染成 Bitmap。
public static Bitmap getBitmapFromView(View view) {
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
保存至本地文件示例
File file = new File(context.getExternalCacheDir(), "qrcode.png");
try (FileOutputStream out = new FileOutputStream(file)) {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
} catch (IOException e) {
e.printStackTrace();
}
七、实用拓展功能推荐
拓展项 | 描述 |
---|---|
嵌入Logo | 中心嵌入品牌Logo,增强品牌识别度 |
分享功能 | 支持微信、钉钉、QQ 等渠道分享 |
动态二维码 | URL 带时间戳或加密参数,提升安全性 |
颜色渐变二维码 | 黑色改为品牌色,提升视觉美感 |
八、常见问题 FAQ
1. 白边裁不掉?
确认 EncodeHintType.MARGIN=0
且手动裁剪 getEnclosingRectangle
。
2. 透明背景二维码无法截图?
使用 ARGB_8888 创建 Bitmap,透明区域需显示为透明色 Color.TRANSPARENT
。
3. 如何设置圆角背景?
使用 layer-list
包裹两个 shape
,一个为透明底,一个为描边渐变。
九、总结
通过这篇文章,我们完成了一个从「产品需求 ➝ 技术实现 ➝ 美化封装 ➝ 分享保存」的完整闭环。
- ✅ 掌握 ZXing 生成二维码的关键技巧
- ✅ 优化二维码显示边距,确保清晰美观
- ✅ 实现 UI 圆角与渐变样式
- ✅ 支持 Dialog 弹窗截图保存
- ✅ 封装工具类,提升复用效率
希望本文能帮你:
快速上线二维码功能,用细节打磨产品体验。
如果你觉得本文有帮助,欢迎点赞、收藏、转发,你的支持是我持续更新的动力💡!