fix: 重写圆角二维码渲染

- 使用独立 Paint 对象,修复颜色问题
- 模块大小固定 16px,圆角 35%
- 白色圆角背景 + 黑色圆角模块
- 模块间 10% 缝隙

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
dongliang
2026-04-27 17:49:22 +09:30
parent 2ec738e3a4
commit 30f7ac1206

View File

@@ -88,30 +88,15 @@ class BindFragment : BaseFragment<FragmentBindBinding>() {
/**
* 将 ZXing BitMatrix 转换为圆角风格二维码 Bitmap
* 每个模块(小方块)都是圆角矩形,整体图片也是圆角
* 每个模块(小方块)都是圆角矩形,白色背景带圆角
*/
private fun bitMatrixToBitmap(matrix: BitMatrix): Bitmap {
val width = matrix.width
val height = matrix.height
val outputSize = 500 // 输出图片尺寸
val bitmap = Bitmap.createBitmap(outputSize, outputSize, Bitmap.Config.ARGB_8888)
val canvas = android.graphics.Canvas(bitmap)
val paint = android.graphics.Paint(android.graphics.Paint.ANTI_ALIAS_FLAG)
// 白色背景(圆角)
paint.color = 0xFFFFFFFF.toInt()
val bgRadius = outputSize * 0.08f
canvas.drawRoundRect(
android.graphics.RectF(0f, 0f, outputSize.toFloat(), outputSize.toFloat()),
bgRadius, bgRadius, paint
)
// 计算每个模块的尺寸和偏移
// 找到二维码实际内容的边界(去掉 ZXing 的空白边距)
var left = width; var top = height; var right = 0; var bottom = 0
for (y in 0 until height) {
for (x in 0 until width) {
// 找到二维码实际内容边界(去掉 ZXing 空白边距)
val w = matrix.width
val h = matrix.height
var left = w; var top = h; var right = 0; var bottom = 0
for (y in 0 until h) {
for (x in 0 until w) {
if (matrix[x, y]) {
if (x < left) left = x
if (x > right) right = x
@@ -120,32 +105,53 @@ class BindFragment : BaseFragment<FragmentBindBinding>() {
}
}
}
val qrWidth = right - left + 1
val qrHeight = bottom - top + 1
val qrCols = right - left + 1
val qrRows = bottom - top + 1
// 留出内边距
val padding = outputSize * 0.06f
val drawArea = outputSize - padding * 2
val moduleSize = drawArea / maxOf(qrWidth, qrHeight)
val offsetX = padding + (drawArea - qrWidth * moduleSize) / 2
val offsetY = padding + (drawArea - qrHeight * moduleSize) / 2
// 输出参数
val moduleSize = 16f // 每个模块像素大小
val padding = moduleSize * 2 // 内边距
val outputSize = (maxOf(qrCols, qrRows) * moduleSize + padding * 2).toInt()
// 绘制每个黑色模块为圆角矩形
paint.color = 0xFF000000.toInt()
val moduleRadius = moduleSize * 0.3f // 每个模块 30% 圆角
val gap = moduleSize * 0.08f // 模块间留小缝隙
val bitmap = Bitmap.createBitmap(outputSize, outputSize, Bitmap.Config.ARGB_8888)
val canvas = android.graphics.Canvas(bitmap)
for (y in top..bottom) {
for (x in left..right) {
if (matrix[x, y]) {
val px = offsetX + (x - left) * moduleSize + gap
val py = offsetY + (y - top) * moduleSize + gap
val rect = android.graphics.RectF(
px, py,
px + moduleSize - gap * 2,
py + moduleSize - gap * 2
// 白色圆角背景
val bgPaint = android.graphics.Paint(android.graphics.Paint.ANTI_ALIAS_FLAG).apply {
color = 0xFFFFFFFF.toInt()
style = android.graphics.Paint.Style.FILL
}
val bgRadius = outputSize * 0.08f
canvas.drawRoundRect(
android.graphics.RectF(0f, 0f, outputSize.toFloat(), outputSize.toFloat()),
bgRadius, bgRadius, bgPaint
)
// 黑色模块画笔
val modulePaint = android.graphics.Paint(android.graphics.Paint.ANTI_ALIAS_FLAG).apply {
color = 0xFF000000.toInt()
style = android.graphics.Paint.Style.FILL
}
// 居中偏移
val offsetX = padding + (maxOf(qrCols, qrRows) - qrCols) * moduleSize / 2
val offsetY = padding + (maxOf(qrCols, qrRows) - qrRows) * moduleSize / 2
// 模块圆角和缝隙
val cornerRadius = moduleSize * 0.35f
val inset = moduleSize * 0.1f
// 逐个绘制圆角模块
for (row in 0 until qrRows) {
for (col in 0 until qrCols) {
if (matrix[left + col, top + row]) {
val px = offsetX + col * moduleSize + inset
val py = offsetY + row * moduleSize + inset
val size = moduleSize - inset * 2
canvas.drawRoundRect(
android.graphics.RectF(px, py, px + size, py + size),
cornerRadius, cornerRadius, modulePaint
)
canvas.drawRoundRect(rect, moduleRadius, moduleRadius, paint)
}
}
}