Özel boyacı

Compose'da, çizilebilecek bir şeyi (Android'de tanımlanan Drawable API'lerinin yerine geçer) temsil etmek ve bunu kullanan ilgili composable'ın ölçümünü ve düzenini etkilemek için Painter nesnesi kullanılır . BitmapPainter, ekranda Bitmap çizebilen bir ImageBitmap alır.

Çoğu kullanım alanında painterResource() işlevi, öğe için doğru boyayı (ör. BitmapPainter veya VectorPainter) döndürür. İkisi arasındaki farklar hakkında daha fazla bilgi için ImageBitmap ve ImageVector karşılaştırması bölümünü okuyun.

Painter, DrawModifier'den farklıdır. , yalnızca kendisine verilen sınırlar içinde çizim yapar ve composable'ın ölçümünü veya düzenini etkilemez.

Özel bir boyayıcı oluşturmak için Painter sınıfını genişletin ve özel grafikler çizmek için DrawScope'ye erişim sağlayan onDraw yöntemini uygulayın. Ayrıca, içinde bulunduğu composable'ı etkilemek için kullanılacak intrinsicSize değerini de geçersiz kılabilirsiniz:

class OverlayImagePainter constructor(
    private val image: ImageBitmap,
    private val imageOverlay: ImageBitmap,
    private val srcOffset: IntOffset = IntOffset.Zero,
    private val srcSize: IntSize = IntSize(image.width, image.height),
    private val overlaySize: IntSize = IntSize(imageOverlay.width, imageOverlay.height)
) : Painter() {

    private val size: IntSize = validateSize(srcOffset, srcSize)
    override fun DrawScope.onDraw() {
        // draw the first image without any blend mode
        drawImage(
            image,
            srcOffset,
            srcSize,
            dstSize = IntSize(
                this@onDraw.size.width.roundToInt(),
                this@onDraw.size.height.roundToInt()
            )
        )
        // draw the second image with an Overlay blend mode to blend the two together
        drawImage(
            imageOverlay,
            srcOffset,
            overlaySize,
            dstSize = IntSize(
                this@onDraw.size.width.roundToInt(),
                this@onDraw.size.height.roundToInt()
            ),
            blendMode = BlendMode.Overlay
        )
    }

    /**
     * Return the dimension of the underlying [ImageBitmap] as it's intrinsic width and height
     */
    override val intrinsicSize: Size get() = size.toSize()

    private fun validateSize(srcOffset: IntOffset, srcSize: IntSize): IntSize {
        require(
            srcOffset.x >= 0 &&
                srcOffset.y >= 0 &&
                srcSize.width >= 0 &&
                srcSize.height >= 0 &&
                srcSize.width <= image.width &&
                srcSize.height <= image.height
        )
        return srcSize
    }
}

Özel Painter oluşturduğumuza göre artık kaynak resmimizin üzerine aşağıdaki gibi herhangi bir resmi yerleştirebiliriz:

val rainbowImage = ImageBitmap.imageResource(id = R.drawable.rainbow)
val dogImage = ImageBitmap.imageResource(id = R.drawable.dog)
val customPainter = remember {
    OverlayImagePainter(dogImage, rainbowImage)
}
Image(
    painter = customPainter,
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Crop,
    modifier = Modifier.wrapContentSize()
)

Aşağıdaki resimde, iki görüntünün özel bir boyayıcıyla birleştirilmesinin sonucu gösterilmektedir:

İki resmi üst üste yerleştiren özel boyama aracı
Şekil 1: İki resmi üst üste bindiren özel boyayıcı

Özel bir boyayıcı, içeriği bir composable'a çizmek için Modifier.paint(customPainter) ile de kullanılabilir:

val rainbowImage = ImageBitmap.imageResource(id = R.drawable.rainbow)
val dogImage = ImageBitmap.imageResource(id = R.drawable.dog)
val customPainter = remember {
    OverlayImagePainter(dogImage, rainbowImage)
}
Box(
    modifier =
    Modifier.background(color = Color.Gray)
        .padding(30.dp)
        .background(color = Color.Yellow)
        .paint(customPainter)
) { /** intentionally empty **/ }