علاوهبر ترکیبپذیر Canvas، Compose چندین گرافیک مفید دارد
Modifiers که به ترسیم محتوای سفارشی کمک میکند. این اصلاحکنندهها مفید هستند
زیرا میتوانند روی هر عنصر ترکیبی اعمال شوند.
اصلاحکنندههای طراحی
همه فرمانهای طراحی با اصلاحکننده طراحی در «نوشتن» انجام میشود. سه اصلاحکننده اصلی طراحی در Compose وجود دارد:
اصلاحگر پایه برای طراحی drawWithContent است، که در آن میتوانید
ترتیب طراحی «ترکیبی» خود و دستورات طراحی صادرشده در داخل
اصلاحگر را تعیین کنید. drawBehind یک پوشاننده مناسب برای drawWithContent است که
ترتیب ترسیم آن در پشت محتوای composable تنظیم شده است. drawWithCacheیا onDrawBehind یا onDrawWithContent را در داخل خود فرا میخواند - و سازوکاری برای ذخیره کردن اشیای ایجادشده در آنها ارائه میدهد.
Modifier.drawWithContent: انتخاب ترتیب قرعهکشی
Modifier.drawWithContent به شما امکان میدهد
عملیات DrawScope را قبل یا بعداز محتوای
ترکیبی اجرا کنید. حتماً drawContent را فراخوانی کنید تا محتوای واقعی
ترکیبی را ارائه کند. با این اصلاحگر، میتوانید ترتیب عملیات را تعیین کنید، اینکه
میخواهید محتوایتان قبلاز عملیات رسم سفارشیتان رسم شود یا بعداز آن.
برای مثال، اگر میخواستید یک گرادیان شعاعی را روی محتوای خود رندر کنید تا یک جلوه سوراخ کلید چراغ قوه در رابط کاربری ایجاد کنید، میتوانید کارهای زیر را انجام دهید:
var pointerOffset by remember { mutableStateOf(Offset(0f, 0f)) } Column( modifier = Modifier .fillMaxSize() .pointerInput("dragging") { detectDragGestures { change, dragAmount -> pointerOffset += dragAmount } } .onSizeChanged { pointerOffset = Offset(it.width / 2f, it.height / 2f) } .drawWithContent { drawContent() // draws a fully black area with a small keyhole at pointerOffset that’ll show part of the UI. drawRect( Brush.radialGradient( listOf(Color.Transparent, Color.Black), center = pointerOffset, radius = 100.dp.toPx(), ) ) } ) { // Your composables here }
Modifier.drawBehind: Drawing behind a composable
Modifier.drawBehind به شما امکان میدهد
عملیات DrawScope را در پشت محتوای قابلترکیب که روی صفحه کشیده شده است انجام دهید. اگر
به پیادهسازی Canvas نگاهی بیندازید، ممکن است متوجه شوید که این
فقط یک پوشاننده مناسب برای Modifier.drawBehind است.
برای کشیدن مستطیل گردشده در پشت Text:
Text( "Hello Compose!", modifier = Modifier .drawBehind { drawRoundRect( Color(0xFFBBAAEE), cornerRadius = CornerRadius(10.dp.toPx()) ) } .padding(4.dp) )
که نتیجه زیر را تولید میکند:
Modifier.drawWithCache: رسم و ذخیره کردن اشیای رسم
Modifier.drawWithCache اشیایی را که در آن ایجاد شدهاند در حافظه نهان نگه میدارد. تا زمانی که اندازه ناحیه طراحی یکسان باشد یا هر شیء وضعیتی که خوانده میشود تغییر نکرده باشد، اشیاء در حافظه نهان ذخیره میشوند. این اصلاحگر برای بهبود عملکرد فراخوانیهای طراحی مفید است زیرا
از نیاز به تخصیص مجدد اشیایی (مثل: Brush, Shader, Path و غیره)
که در طراحی ایجاد میشوند جلوگیری میکند.
یا اینکه میتوانید اشیاء را بااستفاده از remember، خارج از اصلاحکننده، ذخیره موقت کنید. بااینحال، این کار همیشه امکانپذیر نیست زیرا همیشه به ترکیببندی دسترسی ندارید. اگر از اشیا فقط برای رسم کردن استفاده میشود، استفاده از drawWithCache میتواند عملکرد بهتری داشته باشد.
برای مثال، اگر Brush را برای رسم گرادیان در پشت Text ایجاد کنید، بااستفاده از
drawWithCache، هدف Brush را تا زمانیکه اندازه ناحیه رسم تغییر کند
ذخیره میکند:
Text( "Hello Compose!", modifier = Modifier .drawWithCache { val brush = Brush.linearGradient( listOf( Color(0xFF9E82F0), Color(0xFF42A5F5) ) ) onDrawBehind { drawRoundRect( brush, cornerRadius = CornerRadius(10.dp.toPx()) ) } } )
اصلاحکنندههای گرافیکی
Modifier.graphicsLayer: اعمال تبدیلها روی عناصر ترکیبی
Modifier.graphicsLayer
اصلاحکنندهای است که باعث میشود محتوای composable در لایه ترسیم کشیده شود. لایه
چند عملکرد مختلف ارائه میدهد، ازجمله:
- جداسازی دستورالعملهای طراحی آن (مشابه
RenderNode). دستورالعملهای طراحی که بهعنوان بخشی از لایه ضبط شدهاند میتوانند بهطور کارآمد توسط خط لوله رندرینگ بدون اجرای مجدد کد برنامه مجدداً صادر شوند. - تبدیلهایی که برای همه دستورالعملهای طراحی موجود در یک لایه اعمال میشود.
- شطرنجیسازی برای قابلیتهای ترکیببندی. وقتی لایهای شطرنجی میشود، دستورالعملهای ترسیم آن اجرا میشود و خروجی در میانگیر خارج از صفحه ضبط میشود. ترکیب کردن چنین میانگیری برای فریمهای بعدی سریعتر از اجرای دستورالعملهای تکی است، اما وقتی تبدیلهایی مثل مقیاسبندی یا چرخش اعمال میشود، بهعنوان نقشه بیتی عمل خواهد کرد.
تبدیلها
Modifier.graphicsLayer برای دستورالعملهای ترسیم خود جداسازی ارائه میدهد؛
برای مثال، بااستفاده از Modifier.graphicsLayer میتوان تبدیلهای مختلفی را اعمال کرد. اینها را میتوان بدون نیاز به اجرای مجدد لامبدای طراحی، پویانمایی یا اصلاح کرد.
Modifier.graphicsLayer اندازه یا جای اندازهگیریشده
ترکیبپذیر را تغییر نمیدهد، زیرا فقط بر فاز ترسیم تأثیر میگذارد. این یعنی اگر composable شما درنهایت خارج از مرزهای چیدمانش ترسیم شود، ممکن است با composableهای دیگر همپوشانی داشته باشد.
تبدیلهای زیر را میتوان با این اصلاحکننده اعمال کرد:
مقیاس - افزایش اندازه
scaleX و scaleY محتوا را بهترتیب در جهت افقی یا عمودی بزرگ یا کوچک میکند. مقدار 1.0f نشاندهنده عدم تغییر در مقیاس است، مقدار
0.5f یعنی نصف اندازه.
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "Sunset", modifier = Modifier .graphicsLayer { this.scaleX = 1.2f this.scaleY = 0.8f } )
ترجمه
translationX و translationY را میتوان با graphicsLayer تغییر داد،
translationX composable را به چپ یا راست حرکت میدهد. translationY ترکیبپذیر را به بالا یا پایین منتقل میکند.
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "Sunset", modifier = Modifier .graphicsLayer { this.translationX = 100.dp.toPx() this.translationY = 10.dp.toPx() } )
چرخش
rotationX را برای چرخش افقی، rotationY را برای چرخش عمودی، و
rotationZ را برای چرخش در محور Z (چرخش استاندارد) تنظیم کنید. این مقدار برحسب درجه (۰-۳۶۰)
مشخص میشود.
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "Sunset", modifier = Modifier .graphicsLayer { this.rotationX = 90f this.rotationY = 275f this.rotationZ = 180f } )
مبدأ
transformOrigin را میتوان مشخص کرد. سپس از آن بهعنوان نقطهای که
تبدیلها از آنجا انجام میشود استفاده میشود. همه مثالها تاکنون از
TransformOrigin.Center استفاده کردهاند که در (0.5f, 0.5f) است. اگر مبدأ را در
(0f, 0f) مشخص کنید، تبدیلها از گوشه بالا سمت راست
عنصر ترکیبپذیر شروع میشود.
اگر مبدأ را با تبدیل rotationZ تغییر دهید، میتوانید ببینید که
عنصر حول گوشه بالا سمت چپ عنصر ترکیبشدنی میچرخد:
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "Sunset", modifier = Modifier .graphicsLayer { this.transformOrigin = TransformOrigin(0f, 0f) this.rotationX = 90f this.rotationY = 275f this.rotationZ = 180f } )
کلیپ و شکل
شکل مشخص میکند که محتوا هنگام clip = true به کدام خطوط کلی چسبانده شود. در این مثال، دو چارگوش را تنظیم میکنیم تا دو کلیپ متفاوت داشته باشند - یکی بااستفاده از متغیر کلیپ graphicsLayer و دیگری بااستفاده از بستهبندی مناسب Modifier.clip.
Column(modifier = Modifier.padding(16.dp)) { Box( modifier = Modifier .size(200.dp) .graphicsLayer { clip = true shape = CircleShape } .background(Color(0xFFF06292)) ) { Text( "Hello Compose", style = TextStyle(color = Color.Black, fontSize = 46.sp), modifier = Modifier.align(Alignment.Center) ) } Box( modifier = Modifier .size(200.dp) .clip(CircleShape) .background(Color(0xFF4DB6AC)) ) }
محتویات کادر اول (نوشتاری که میگوید «سلام Compose») به شکل دایره برش داده میشود:
اگر سپس translationY را به دایره صورتی بالا اعمال کنید، میبینید که مرزهای
«ترکیبپذیر» همچنان یکسان است، اما دایره زیر دایره پایینی (و خارج از مرزهای آن) ترسیم میشود.
برای برش دادن ترکیبپذیر به منطقهای که در آن ترسیم شده است، میتوانید
Modifier.clip(RectangleShape) دیگری را به ابتدای زنجیره اصلاحکننده اضافه کنید. محتوا
سپس در محدوده اصلی باقی میماند.
Column(modifier = Modifier.padding(16.dp)) { Box( modifier = Modifier .clip(RectangleShape) .size(200.dp) .border(2.dp, Color.Black) .graphicsLayer { clip = true shape = CircleShape translationY = 50.dp.toPx() } .background(Color(0xFFF06292)) ) { Text( "Hello Compose", style = TextStyle(color = Color.Black, fontSize = 46.sp), modifier = Modifier.align(Alignment.Center) ) } Box( modifier = Modifier .size(200.dp) .clip(RoundedCornerShape(500.dp)) .background(Color(0xFF4DB6AC)) ) }
آلفا
از Modifier.graphicsLayer میتوان برای تنظیم alpha (کدری) برای کل لایه استفاده کرد. 1.0f کاملاً مات است و 0.0f نامرئی است.
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "clock", modifier = Modifier .graphicsLayer { this.alpha = 0.5f } )
راهبرد ترکیببندی
کار با آلفا و شفافیت همیشه به سادگی تغییر یک مقدار آلفا نیست. علاوهبر تغییر آلفا،
گزینهای برای تنظیم CompositingStrategy در graphicsLayer نیز وجود دارد. CompositingStrategy تعیین میکند که محتوای ترکیبشدنی چگونه با محتوای دیگری که قبلاً روی صفحه کشیده شده است ترکیب (کنار هم قرار داده) شود.
استراتژیهای مختلف عبارتند از:
خودکار (پیشفرض)
استراتژی ترکیببندی توسط بقیه پارامترهای graphicsLayer تعیین میشود. اگر آلفا کمتر از
1.0f باشد یا RenderEffect تنظیم شده باشد، لایه را در میانگیری خارج از صفحه پرداز میکند. هرگاه آلفا کمتر از 1f باشد، یک لایه ترکیببندی بهطور خودکار ایجاد میشود تا محتوا را رندر کند و سپس این میانگیر خارج از صفحه را با آلفای مربوطه به مقصد بکشد. تنظیم
RenderEffect یا پیمایش اضافی همیشه محتوا را در
بافری خارج از صفحه صرفنظر از CompositingStrategy تنظیمشده پرداز میکند.
خارج از صفحه
محتوای composable همیشه قبلاز رندر شدن در مقصد، به بافت یا نقشه بیتی خارجاز صفحه شطرنجی میشود. این ویژگی برای اعمال عملیات BlendMode روی محتوای پوششی و برای عملکرد هنگام پرداز کردن مجموعههای پیچیده دستورالعملهای طراحی مفید است.
نمونهای از استفاده از CompositingStrategy.Offscreen با BlendModes است.
در مثال زیر، فرض کنید میخواهید بخشهایی از یک Image
ترکیبشدنی را با صدور فرمان ترسیم که از BlendMode.Clear استفاده میکند بردارید. اگر
compositingStrategy را روی CompositingStrategy.Offscreen تنظیم نکنید،
BlendMode با همه محتوای پسزمینه تعامل برقرار میکند.
Image( painter = painterResource(id = R.drawable.dog), contentDescription = "Dog", contentScale = ContentScale.Crop, modifier = Modifier .size(120.dp) .aspectRatio(1f) .background( Brush.linearGradient( listOf( Color(0xFFC5E1A5), Color(0xFF80DEEA) ) ) ) .padding(8.dp) .graphicsLayer { compositingStrategy = CompositingStrategy.Offscreen } .drawWithCache { val path = Path() path.addOval( Rect( topLeft = Offset.Zero, bottomRight = Offset(size.width, size.height) ) ) onDrawWithContent { clipPath(path) { // this draws the actual image - if you don't call drawContent, it wont // render anything this@onDrawWithContent.drawContent() } val dotSize = size.width / 8f // Clip a white border for the content drawCircle( Color.Black, radius = dotSize, center = Offset( x = size.width - dotSize, y = size.height - dotSize ), blendMode = BlendMode.Clear ) // draw the red circle indication drawCircle( Color(0xFFEF5350), radius = dotSize * 0.8f, center = Offset( x = size.width - dotSize, y = size.height - dotSize ) ) } } )
با تنظیم CompositingStrategy روی Offscreen، بافت خارج از صفحه
ایجاد میشود تا فرمانها را اجرا کند (BlendMode فقط روی
محتوای این عنصر ترکیبی اعمال میشود). سپس آن را روی آنچه ازقبل در صفحه
پردازش شده است پردازش میکند و بر محتوای ازقبل رسمشده تأثیر نمیگذارد.
اگر از CompositingStrategy.Offscreen استفاده نکرده باشید، نتایج اعمال
BlendMode.Clear همه پیکسلهای مقصد را پاک میکند، صرفنظر از
آنچه قبلاً تنظیم شده است - با این کار بافر پردازنده پنجره (سیاه)
نمایان میشود. بسیاری از
BlendModes که شامل آلفا هستند بدون میانگیر
خارج از صفحه طبق انتظار کار نخواهند کرد. به حلقه سیاه دور نشانگر دایره قرمز توجه کنید:
برای درک بهتر این موضوع: اگر برنامه پسزمینه پنجره نیمهشفافی داشت و شما از CompositingStrategy.Offscreen استفاده نمیکردید، BlendMode با کل برنامه تعامل برقرار میکرد. این کار تمام پیکسلها را پاک میکرد تا برنامه یا کاغذدیواری زیرین را نشان دهد، مانند این مثال:
شایان ذکر است که هنگام استفاده از CompositingStrategy.Offscreen، بافت خارج از صفحهای که به اندازه ناحیه طراحی است ایجاد میشود و دوباره روی صفحه رندر میشود. هر فرمان ترسیمی که با این استراتژی انجام شود، بهطور پیشفرض به این منطقه برش داده میشود. تکهکد زیر تفاوتها را هنگام جابهجایی به استفاده از بافتهای خارج از صفحه نشان میدهد:
@Composable fun CompositingStrategyExamples() { Column( modifier = Modifier .fillMaxSize() .wrapContentSize(Alignment.Center) ) { // Does not clip content even with a graphics layer usage here. By default, graphicsLayer // does not allocate + rasterize content into a separate layer but instead is used // for isolation. That is draw invalidations made outside of this graphicsLayer will not // re-record the drawing instructions in this composable as they have not changed Canvas( modifier = Modifier .graphicsLayer() .size(100.dp) // Note size of 100 dp here .border(2.dp, color = Color.Blue) ) { // ... and drawing a size of 200 dp here outside the bounds drawRect(color = Color.Magenta, size = Size(200.dp.toPx(), 200.dp.toPx())) } Spacer(modifier = Modifier.size(300.dp)) /* Clips content as alpha usage here creates an offscreen buffer to rasterize content into first then draws to the original destination */ Canvas( modifier = Modifier // force to an offscreen buffer .graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen) .size(100.dp) // Note size of 100 dp here .border(2.dp, color = Color.Blue) ) { /* ... and drawing a size of 200 dp. However, because of the CompositingStrategy.Offscreen usage above, the content gets clipped */ drawRect(color = Color.Red, size = Size(200.dp.toPx(), 200.dp.toPx())) } } }
ModulateAlpha
این راهبرد ترکیببندی آلفا را برای هریک از دستورالعملهای طراحی
ضبطشده در graphicsLayer تعدیل میکند. اگر RenderEffect تنظیم نشده باشد، میانگیر خارج از صفحه برای آلفای کمتر از ۱٫۰f ایجاد نمیکند، بنابراین میتواند برای پردازش آلفا کارآمدتر باشد. بااینحال، ممکن است نتایج متفاوتی برای محتوای همپوشان ارائه دهد. برای موارد استفادهای که ازقبل مشخص است
محتوا همپوشانی ندارد، این روش میتواند عملکرد بهتری نسبتبه
CompositingStrategy.Auto با مقادیر آلفای کمتر از ۱ ارائه دهد.
مثال زیر استراتژیهای ترکیببندی مختلف را نشان میدهد - اعمال کردن
آلفاهای مختلف روی بخشهای مختلف عناصر ترکیبشدنی، و اعمال کردن استراتژی
Modulate:
@Preview @Composable fun CompositingStrategy_ModulateAlpha() { Column( modifier = Modifier .fillMaxSize() .padding(32.dp) ) { // Base drawing, no alpha applied Canvas( modifier = Modifier.size(200.dp) ) { drawSquares() } Spacer(modifier = Modifier.size(36.dp)) // Alpha 0.5f applied to whole composable Canvas( modifier = Modifier .size(200.dp) .graphicsLayer { alpha = 0.5f } ) { drawSquares() } Spacer(modifier = Modifier.size(36.dp)) // 0.75f alpha applied to each draw call when using ModulateAlpha Canvas( modifier = Modifier .size(200.dp) .graphicsLayer { compositingStrategy = CompositingStrategy.ModulateAlpha alpha = 0.75f } ) { drawSquares() } } } private fun DrawScope.drawSquares() { val size = Size(100.dp.toPx(), 100.dp.toPx()) drawRect(color = Red, size = size) drawRect( color = Purple, size = size, topLeft = Offset(size.width / 4f, size.height / 4f) ) drawRect( color = Yellow, size = size, topLeft = Offset(size.width / 4f * 2f, size.height / 4f * 2f) ) } @Preview @Composable fun ModifierGraphicsLayerOutsets() { Column( modifier = Modifier .background(Color(0xFF0A0E14)) .padding(48.dp), verticalArrangement = Arrangement.spacedBy(48.dp), horizontalAlignment = Alignment.CenterHorizontally ) { val pillShape = RoundedCornerShape(percent = 50) // Without outsets: alpha = 0.5f creates an offscreen buffer that clips the 24.dp glow Box( modifier = Modifier .size( width = 140.dp, height = 56.dp ) .graphicsLayer( alpha = 0.5f, clip = false ) .dropShadow( shape = pillShape, shadow = Shadow(radius = 24.dp, color = Color.Cyan) ) .background(color = Color(0xFF141824), shape = pillShape), contentAlignment = Alignment.Center ) { Text( text = "✨ Glow", color = Color.White, fontSize = 18.sp ) } Box( modifier = Modifier .size( width = 140.dp, height = 56.dp ) .graphicsLayer( alpha = 0.5f, outsets = LayerOutsets(24.dp), clip = false ) .dropShadow( shape = pillShape, shadow = Shadow(radius = 24.dp, color = Color.Cyan) ) .background(color = Color(0xFF141824), shape = pillShape), contentAlignment = Alignment.Center ) { Text( text = "✨ Glow", color = Color.White, fontSize = 18.sp ) } } } val Purple = Color(0xFF7E57C2) val Yellow = Color(0xFFFFCA28) val Red = Color(0xFFEF5350)
بیرونزدگیهای لایه
وقتی عنصر ترکیبی در بافر خارج از صفحه رسم میشود (برای مثال، وقتی alpha
کمتر از 1.0f باشد، RenderEffect تنظیم شود، یا از CompositingStrategy.Offscreen
استفاده شود)، بافت خارج از صفحه بهطور پیشفرض به محدوده چیدمان اندازهگیریشده عنصر ترکیبی
تبدیل میشود. هرگونه طراحی یا سایه داخل لایه که خارج از مرزهای چیدمان ترکیبپذیر گسترش مییابد (مانند درخشش بیرونی که با Modifier.dropShadow رسم شده است) بهطور ضمنی در مرز میانگیر خارج از صفحه بریده میشود.
بهجای افزودن Modifier.padding() (که اندازهگیری چیدمان عناصر میانای کاربر مجاور را تغییر میدهد)، LayerOutsets را به پارامتر outsets از Modifier.graphicsLayer ارسال کنید. این کار مرزهای دیداری میانگیر خارج از صفحه را در هر طرف گسترش میدهد، بدون اینکه اندازه چیدمان اندازهگیریشده ترکیبپذیر را تغییر دهد. توجه داشته باشید که
LayerOutsets شکل کلیپ لایه یا حدود سایه را گسترش نمیدهد، که
براساس اندازه اصلی اندازهگیریشده عنصر ترکیبی باقی میماند (بنابراین clip = false
را در graphicsLayer نگه دارید تا از چسبیدن به حدود اصلی جلوگیری کنید):
Box( modifier = Modifier .size( width = 140.dp, height = 56.dp ) .graphicsLayer( alpha = 0.5f, outsets = LayerOutsets(24.dp), clip = false ) .dropShadow( shape = pillShape, shadow = Shadow(radius = 24.dp, color = Color.Cyan) ) .background(color = Color(0xFF141824), shape = pillShape), contentAlignment = Alignment.Center ) { Text( text = "✨ Glow", color = Color.White, fontSize = 18.sp ) }
LayerOutsets (بالا، برشخورده در مرزهای چیدمان مستطیلی ترکیبپذیر) درمقابل با LayerOutsets(24.dp) (پایین، برشنخورده)نوشتن محتوای عنصر ترکیبی در بیتمپ
یک مورد استفاده رایج، ایجاد Bitmap از یک ترکیبپذیر است. برای کپی کردن
محتوای composable در Bitmap، بااستفاده از
rememberGraphicsLayer()، GraphicsLayer ایجاد کنید.
بااستفاده از drawWithContent() و graphicsLayer.record{}، فرمانهای طراحی را به لایه جدید هدایت کنید. سپس لایه را در بوم نمایان بااستفاده از
drawLayer بکشید:
val coroutineScope = rememberCoroutineScope() val graphicsLayer = rememberGraphicsLayer() Box( modifier = Modifier .drawWithContent { // call record to capture the content in the graphics layer graphicsLayer.record { // draw the contents of the composable into the graphics layer this@drawWithContent.drawContent() } // draw the graphics layer on the visible canvas drawLayer(graphicsLayer) } .clickable { coroutineScope.launch { val bitmap = graphicsLayer.toImageBitmap() // do something with the newly acquired bitmap } } .background(Color.White) ) { Text("Hello Android", fontSize = 26.sp) }
میتوانید بیتمپ را در دیسک ذخیره کنید و آن را همرسانی کنید. برای جزئیات بیشتر، قطعه کد نمونه کامل را ببینید. قبلاز تلاش برای ذخیره کردن در دیسک، حتماً اجازههای روی دستگاه را بررسی کنید.
اصلاحگر طراحی سفارشی
برای ایجاد اصلاحکننده سفارشی خودتان، میانای DrawModifier را پیادهسازی کنید. این کار به شما امکان میدهد به ContentDrawScope دسترسی داشته باشید که همان چیزی است که هنگام استفاده از Modifier.drawWithContent() نمایان میشود. سپس میتوانید عملیاتهای رایج طراحی را به اصلاحکنندههای طراحی سفارشی استخراج کنید تا کد را پاکسازی کنید و پوشانندههای مناسبی ارائه دهید؛ برای مثال، Modifier.background() یک DrawModifier مناسب است.
برای مثال، اگر میخواهید Modifier را پیادهسازی کنید که محتوا را بهصورت عمودی برمیگرداند، میتوانید یکی را بهصورت زیر ایجاد کنید:
class FlippedModifier : DrawModifier { override fun ContentDrawScope.draw() { scale(1f, -1f) { this@draw.drawContent() } } } fun Modifier.flipped() = this.then(FlippedModifier())
سپس از این اصلاحکننده معکوسشده که روی Text اعمال شده است استفاده کنید:
Text( "Hello Compose!", modifier = Modifier .flipped() )
منابع بیشتر
برای مثالهای بیشتر درباره استفاده از graphicsLayer و طراحی سفارشی،
منابع زیر را بررسی کنید:
توصیهشده برای شما
- توجه: وقتی جاوا اسکریپت خاموش باشد، نوشتار پیوند نمایش داده میشود
- گرافیک در Compose
- سفارشیسازی تصویر {:#customize-image}
- Kotlin برای Jetpack Compose