Özel boyacı

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

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

Painter, kendisine verilen sınırlar içinde kesin olarak çizim yapan ve composable'ın ölçümü veya düzeni üzerinde etkisi olmayan DrawModifier öğesinden farklıdır.

Özel bir boya oluşturmak için Painter sınıfını genişletin ve özel grafikler çizmek için DrawScope'ye erişime izin veren onDraw yöntemini uygulayın. Ayrıca, intrinsicSize değerini geçersiz kılabilirsiniz. Bu değer, içinde bulunduğu Composable'ı etkilemek için kullanılır:

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 öğemizi oluşturduğumuza göre, kaynak resmimizin üzerine herhangi bir resmi aşağıdaki şekilde 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()
)

İki resmin özel bir ressamla birleştirilmesinin sonucu aşağıda gösterilmiştir:

İki resmi üst üste yerleştiren özel boya
Şekil 1: İki görüntüyü üst üste bindiren özel Painter

İçeriği aşağıdaki gibi bir composable'a çizmek için Modifier.paint(customPainter) ile özel bir painter da 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 **/ }