feat: 二维码圆角风格 - 每个模块都是圆角矩形
- 白色背景圆角 8% - 每个黑色模块圆角 30% - 模块间有微小缝隙,更精致 - 自动裁剪 ZXing 空白边距 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -86,35 +86,71 @@ class BindFragment : BaseFragment<FragmentBindBinding>() {
|
||||
}
|
||||
}
|
||||
|
||||
/** 将 ZXing BitMatrix 转换为圆角 Android Bitmap */
|
||||
/**
|
||||
* 将 ZXing BitMatrix 转换为圆角风格二维码 Bitmap
|
||||
* 每个模块(小方块)都是圆角矩形,整体图片也是圆角
|
||||
*/
|
||||
private fun bitMatrixToBitmap(matrix: BitMatrix): Bitmap {
|
||||
val width = matrix.width
|
||||
val height = matrix.height
|
||||
// 先生成方形 Bitmap
|
||||
val pixels = IntArray(width * 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) {
|
||||
pixels[y * width + x] = if (matrix[x, y]) {
|
||||
0xFF000000.toInt() // 黑色模块
|
||||
} else {
|
||||
0xFFFFFFFF.toInt() // 白色背景
|
||||
if (matrix[x, y]) {
|
||||
if (x < left) left = x
|
||||
if (x > right) right = x
|
||||
if (y < top) top = y
|
||||
if (y > bottom) bottom = y
|
||||
}
|
||||
}
|
||||
}
|
||||
val squareBitmap = Bitmap.createBitmap(pixels, width, height, Bitmap.Config.ARGB_8888)
|
||||
val qrWidth = right - left + 1
|
||||
val qrHeight = bottom - top + 1
|
||||
|
||||
// 绘制圆角
|
||||
val output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
||||
val canvas = android.graphics.Canvas(output)
|
||||
val paint = android.graphics.Paint(android.graphics.Paint.ANTI_ALIAS_FLAG)
|
||||
val rect = android.graphics.RectF(0f, 0f, width.toFloat(), height.toFloat())
|
||||
val radius = width * 0.12f // 12% 圆角(参照 iPhone 风格)
|
||||
canvas.drawRoundRect(rect, radius, radius, paint)
|
||||
paint.xfermode = android.graphics.PorterDuffXfermode(android.graphics.PorterDuff.Mode.SRC_IN)
|
||||
canvas.drawBitmap(squareBitmap, 0f, 0f, paint)
|
||||
squareBitmap.recycle()
|
||||
// 留出内边距
|
||||
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
|
||||
|
||||
return output
|
||||
// 绘制每个黑色模块为圆角矩形
|
||||
paint.color = 0xFF000000.toInt()
|
||||
val moduleRadius = moduleSize * 0.3f // 每个模块 30% 圆角
|
||||
val gap = moduleSize * 0.08f // 模块间留小缝隙
|
||||
|
||||
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
|
||||
)
|
||||
canvas.drawRoundRect(rect, moduleRadius, moduleRadius, paint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bitmap
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user