نقاش سفارشی

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

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

یک Painter با یک DrawModifier متفاوت است، که به شدت در محدوده‌هایی که به آن داده شده است ترسیم می‌کند و تأثیری بر اندازه‌گیری یا چیدمان ترکیب‌پذیر ندارد.

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

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

{% کلمه به کلمه %} {% آخر کلمه %} {% کلمه به کلمه %} {% آخر کلمه %}