如何在JetPack组成的QR码渲染文本
#android #jetpack #组成

a QR代码(快速安息代码)是一种条形码,表示为黑白正方形的矩阵。 QR码使表示文本,例如以图像格式表示文本,例如电话号码,URL和其他信息。

Jetpack Compose(Google的新的UI工具包用于Android应用程序)中,创建一个可用于渲染可以绘制到指定边界区域的映像和UI元素的实例非常容易。默认情况下,撰写中有许多Painter子类,但我们将重点放在BitmapPainter上。

添加Zxing核心依赖性

第一步是生成将在我们的UI中渲染的QR代码位图映像。为此,我们将使用Google使用koude3库。 Zxing是用于Java和Android的开源条形码扫描LIBARY。将依赖关系添加到模块级别(在一个简单的项目中,这将是应用程序)build.gradle file:

dependencies {
    ...
    implementation "com.google.zxing:core:3.5.1"
}

定义画家功能

让我们定义一种特殊类型的可复合函数,该功能返回值并具有骆驼壳命名,而不是我们通常的可复合函数,该功能用 pascalcase naming和返回无值(单位)。这将返回将传递给我们的Image综合函数时将渲染QR码的BitmapPainter

@Composable
fun rememberQrBitmapPainter(
    content: String,
    size: Dp = 150.dp,
    padding: Dp = 0.dp
): BitmapPainter {
    return BitmapPainter()
}

我们的rememberQrBitmapPainter采用了一个content: String,该content: String表示我们要在QR代码,size:Dp中编码的文本值,该QR代表QR的大小(宽度x高),该QR指定为设备无关的像素值(以确保我们具有锋利在不同像素密度的不同设备上的图像)和padding:Dp表示我们想要围绕生成的代码的空间边框的数量。填充设置为默认值为0,以覆盖/删除ZXing库生成QR位图时添加的默认填充。

让我们在我们的功能中添加4个新变量;
density使用LocalDensity local来检索设备的当前屏幕密度信息。 Density接口提供了有用的扩展功能,用于执行简单操作,例如获取与我们之前指定的.dp值相当的设备像素等效。
sizePxpaddingPx变量分别表示大小和填充的像素。
bitmap可变状态变量保存QR码的位图。为了防止在状态更改(重组)重新绘制UI时,我们的位图被重新计算,我们将其用内容键将其包裹起来。内容密钥允许我们在QR包含更改的值时重新计算位图。

@Composable
fun rememberQrBitmapPainter(
    content: String,
    size: Dp = 150.dp,
    padding: Dp = 0.dp
): BitmapPainter {

    val density = LocalDensity.current
    val sizePx = with(density) { size.roundToPx() }
    val paddingPx = with(density) { padding.roundToPx() }

    var bitmap by remember(content) {
        mutableStateOf<Bitmap?>(null)
    }

    return BitmapPainter()
}

QR代码是一个矩阵,由多个像素组成,如果在UI线程上计算的值,则可能导致您的UI口吃或挂起;因此,我们将使用LaunchedEffectIO CoroutineDispatcher来卸载UI线程QR码的位图所需的工作:

LaunchedEffect(bitmap) {
    if (bitmap != null) return@LaunchedEffect

    launch(Dispatchers.IO) {
       val qrCodeWriter = QRCodeWriter()

       val encodeHints = mutableMapOf<EncodeHintType, Any?>()
           .apply {
              this[EncodeHintType.MARGIN] = paddingPx
           }

       val bitmapMatrix = try {
           qrCodeWriter.encode(
              content, BarcodeFormat.QR_CODE,
              sizePx, sizePx, encodeHints
            )
       } catch (ex: WriterException) {
          null
       }
    }
}

在这里,我们创建了一个QRCodeWriter实例,该实例将用于编码QR。 encodeHints变量是EncodeHintType到值的映射,用于配置QRCodeWriter。通过编码内容字符串并指定QR的高度和宽度来创建bitmapMatrix

我们需要从bitmapmatrix创建一个位图,并为每个像素(白色或黑色)设置颜色:

val matrixWidth = bitmapMatrix?.width ?: sizePx
val matrixHeight = bitmapMatrix?.height ?: sizePx

val newBitmap = Bitmap.createBitmap(
    bitmapMatrix?.width ?: sizePx,
    bitmapMatrix?.height ?: sizePx,
    Bitmap.Config.ARGB_8888,
)

for (x in 0 until matrixWidth) {
    for (y in 0 until matrixHeight) {
       val shouldColorPixel = bitmapMatrix?.get(x, y) ?: false
       val pixelColor = if (shouldColorPixel) Color.BLACK else Color.WHITE

       newBitmap.setPixel(x, y, pixelColor)
     }
}

bitmap = newBitmap

在我们的最后一步中,我们返回一个BitmapPainter的实例,其中计算出的位图作为参数传递。如果尚未计算位图,我们将通过透明颜色的空位图相等的位图。然后使用Bitmap.asImagePainter()扩展功能将位图转换为图像位图。

return remember(bitmap) {
   val currentBitmap = bitmap ?: Bitmap.createBitmap(
       sizePx, sizePx,
       Bitmap.Config.ARGB_8888,
   ).apply { eraseColor(Color.TRANSPARENT) }

   BitmapPainter(currentBitmap.asImageBitmap())
}

您将如何使用它:

Image(
    painter = rememberQrBitmapPainter("https://dev.to"),
    contentDescription = "DEV Communit Code",
    contentScale = ContentScale.FillBounds,
    modifier = Modifier.size(135.dp),
)

将所有我们得到的一切都放在一起:QRPainter.kt

希望您发现这篇文章有用,并感谢您的阅读。