نقاش سفارشی

در Compose، از یک شیء Painter برای نمایش چیزی که می‌توان رسم کرد (جایگزینی برای APIهای Drawable تعریف‌شده در اندروید) استفاده می‌شود و بر اندازه‌گیری و طرح‌بندی Composable مربوطه که از آن استفاده می‌کند، تأثیر می‌گذارد. یک BitmapPainter یک ImageBitmap می‌گیرد که می‌تواند یک Bitmap روی صفحه رسم کند.

در بیشتر موارد استفاده، استفاده از painterResource() در بالا، نقاش صحیح برای دارایی (یعنی BitmapPainter یا VectorPainter ) را برمی‌گرداند. برای اطلاعات بیشتر در مورد تفاوت‌های بین این دو، بخش ImageBitmap در مقابل ImageVector را مطالعه کنید.

یک Painter با DrawModifier متفاوت است، که کاملاً در محدوده‌ای که به آن داده شده رسم می‌کند و هیچ تاثیری بر اندازه یا طرح‌بندی composable ندارد.

برای ایجاد یک نقاش سفارشی، کلاس Painter را ارث‌بری کنید و متد onDraw را پیاده‌سازی کنید که امکان دسترسی به DrawScope برای ترسیم گرافیک‌های سفارشی را فراهم می‌کند. همچنین می‌توانید مقدار intrinsicSize را که برای تأثیرگذاری بر Composable موجود در آن استفاده می‌شود، override کنید:

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

حالا که Painter سفارشی خودمان را داریم، می‌توانیم هر تصویری را به صورت زیر روی تصویر اصلی خود قرار دهیم:

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

خروجی ترکیب دو تصویر با یک نقاش سفارشی را می‌توانید در زیر مشاهده کنید:

نقاش سفارشی که دو تصویر را روی هم قرار می‌دهد
شکل 1 : نقاش سفارشی که دو تصویر را روی هم قرار می‌دهد

یک نقاش سفارشی همچنین می‌تواند با استفاده از Modifier.paint(customPainter) برای ترسیم محتوا به یک composable به صورت زیر استفاده شود:

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

{% کلمه به کلمه %} {% فعل کمکی %} {% کلمه به کلمه %} {% فعل کمکی %}