Painter kustom

Di Compose, objek Painter digunakan untuk mewakili sesuatu yang dapat digambar (pengganti Drawable API yang ditentukan di Android) dan memengaruhi pengukuran dan tata letak composable yang sesuai yang menggunakannya. BitmapPainter mengambil ImageBitmap yang dapat menggambar Bitmap di layar.

Untuk sebagian besar kasus penggunaan, penggunaan painterResource() di atas akan menampilkan painter yang benar untuk aset (yaitu BitmapPainter atau VectorPainter). Untuk informasi selengkapnya tentang perbedaan antara keduanya - baca bagian ImageBitmap vs ImageVector.

Painter berbeda dengan DrawModifier, yang benar-benar menggambar dalam batas yang diberikan kepadanya dan tidak berpengaruh pada pengukuran atau tata letak composable.

Untuk membuat painter kustom, perluas class Painter, dan implementasikan metode onDraw, yang memungkinkan akses ke DrawScope untuk menggambar grafis kustom. Anda juga dapat mengganti intrinsicSize, yang akan digunakan untuk memengaruhi Composable yang ada di dalamnya:

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
    }
}

Sekarang setelah memiliki Painter kustom, kita dapat menempatkan gambar apa pun di atas gambar sumber sebagai berikut:

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()
)

Output dari penggabungan dua gambar dengan painter kustom dapat dilihat di bawah:

Painter Kustom yang menempatkan dua gambar di atas satu sama lain
Gambar 1: Painter Kustom yang menempatkan dua gambar di atas satu sama lain

Painter kustom juga dapat digunakan dengan Modifier.paint(customPainter) untuk menggambar konten ke composable sebagai berikut:

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 **/ }