android - 如何在jetpack compose中创建水印文字效果

标签 android kotlin android-jetpack-compose watermark jetpack

我想在我的应用程序中使用文本创建水印效果,如下图所示。 我通过使用 Canvas 和位图实现了这一点,还有其他可靠的方法吗?

这是我的可组合函数

@Composable
fun WaterMark(
  modifier: Modifier = Modifier,
  content: (@Composable BoxScope.() -> Unit)? = null,
) {

  val watermarkText: String = "some mutable text"

  val paint = Paint(Paint.ANTI_ALIAS_FLAG)
  paint.textSize = LocalContext.current.dpToPx(24).toFloat()
  paint.color = PSCoreColours.psCoreColours.onSurface.hashCode()
  paint.textAlign = Paint.Align.LEFT
  paint.alpha = (255 * 0.25).toInt()
  val baseline: Float = -paint.ascent()
  val image: Bitmap = Bitmap.createBitmap(paint.measureText(watermarkText).toInt(),
    (baseline + paint.descent()).toInt(),
    Bitmap.Config.ARGB_8888)

  val canvas = android.graphics.Canvas(image)
  canvas.drawText(watermarkText, 0f, baseline, paint)
  val rotationMatrix: Matrix = Matrix().apply { postRotate(-45f) }

  val rotatedImage: Bitmap = Bitmap.createBitmap(image, 0, 0, image.width, image.height, rotationMatrix, true)

  val pattern: ImageBitmap = rotatedImage.asImageBitmap()

  Box {
    content?.let { it() }
    Canvas(
      modifier = modifier
    ) {
      val totalWidth = size.width / pattern.width
      val totalHeight = size.height / pattern.height
      var x = 0f
      var y = 0f
      for (i in 0..totalHeight.toInt()) {
        y = (i * pattern.height).toFloat()
        for (j in 0..totalWidth.toInt()) {
          x = (j * pattern.width).toFloat()
          drawImage(
            pattern,
            colorFilter = null,
            topLeft = Offset(x, y),
          )
        }
      }
    }
  }
}

最佳答案

您可以为此在 compose 中进行自定义布局

private const val SPACING = 100

@Composable
fun Watermark(
  content: @Composable BoxScope.() -> Unit,
) {
  Box {
    content()

    Layout(
      content = {
        // Repeating the placeables, 6 should do for now but we should be able to calculate this too
        repeat(6) { 
          Text(
            text = watermarkText,
            ..
          )
        }
      }
    ) { measurables, constraints ->
      // Measuring all the placables
      val placeables: List<Placeable> = measurables
        .map { measurable -> measurable.measure(constraints) }
        
      layout(constraints.maxWidth, constraints.maxHeight) {
        // Calculating the max width of a placable
        val maxWidth: Double = placeables.maxOf { it.width }.toDouble()

        // Calculating the max width of a tile given the text is rotated
        val tileSize: Int = (constraints.maxWidth / atan(maxWidth)).toInt()
        
        placeables
          .chunked(2)  // Placing 2 columns 
          .forEachIndexed { index, (first, second) ->
            val indexedTileSize: Int = index * tileSize
            first.placeRelativeWithLayer(-SPACING, indexedTileSize + SPACING) { rotationZ = -45f }
            second.placeRelativeWithLayer(tileSize, indexedTileSize) { rotationZ = -45f }
        }
      }
    }
  }
}

关于android - 如何在jetpack compose中创建水印文字效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73656656/

相关文章:

android - 改造错误:-预期为BEGIN_ARRAY,但在路径$处为BEGIN_OBJECT

安卓 Kotlin 。使用 fragment 将数据绑定(bind)到 recyclerview 时出现问题

android - 导航参数双重错误: Can't escape identifier `0.0` because it contains illegal characters

kotlin - 修改器的属性是什么,我需要更改以使角变圆且宽度更小?喷气背包组合

kotlin - 为什么记得不将 StateFlow 转换为特定类型?

java - 在 HTTPResponse Android 中进行重定向

java - 如何让Viewholder RecyclerViewAdapterAdapter中的OnClick调用Activity的函数

尽管在纵向 View 中录制,但使用 mediaRecorder 和表面 View 录制的 Android 视频无法在横向 View 中播放

android - 从 DatePicker 和 TimePicker 获取值

android-studio - 如何在 JetPack Compose 中显示 .svg 图像 URL?