بسیاری از برنامهها باید بتوانند دقیقاً آنچه را که روی صفحه کشیده میشود کنترل کنند. این کار میتواند به کوچکی قرار دادن یک جعبه یا دایره در جای مناسب روی صفحه باشد، یا میتواند یک چیدمان پیچیده از عناصر گرافیکی در سبکهای مختلف باشد.
طراحی ساده با اصلاحکنندهها و DrawScope
روش اصلی برای رسم چیزی سفارشی در Compose استفاده از اصلاحکنندهها است، مثل
Modifier.drawWithContent،
Modifier.drawBehind، و
Modifier.drawWithCache.
برای مثال، برای رسم کردن چیزی در پشت عنصر ترکیبی، میتوانید از
drawBehind اصلاحگر برای شروع اجرای فرمانهای رسم استفاده کنید:
Spacer( modifier = Modifier .fillMaxSize() .drawBehind { // this = DrawScope } )
اگر تنها چیزی که نیاز دارید یک عنصر ترکیبی است که رسم میکند، میتوانید از عنصر ترکیبی
Canvas استفاده کنید. ترکیبپذیر Canvas یک
پیچک راحت در اطراف Modifier.drawBehind است. Canvas را در چیدمانتان قرار میدهید، همانطور که با هر عنصر دیگر «واسط کاربر Compose» این کار را انجام میدهید. در
Canvas، میتوانید عناصر را با کنترل دقیق بر سبک و
مکان آنها بکشید.
همه اصلاحکنندههای طراحی DrawScope، محیط طراحی محدودهای را که وضعیت خود را حفظ میکند آشکار میکنند. با این کار میتوانید پارامترهای گروهی از عناصر گرافیکی را تنظیم کنید. DrawScope چندین فیلد مفید ارائه میدهد، مثل size،
یک شیء Size که ابعاد فعلی DrawScope را مشخص میکند.
برای کشیدن چیزی، میتوانید از یکی از توابع طراحی متعدد در DrawScope استفاده کنید. برای مثال، کد زیر مستطیلی را در گوشه بالا سمت راست صفحهنمایش رسم میکند:
Canvas(modifier = Modifier.fillMaxSize()) { val canvasQuadrantSize = size / 2F drawRect( color = Color.Magenta, size = canvasQuadrantSize ) }
برای کسب اطلاعات بیشتر درباره اصلاحکنندههای مختلف طراحی، به اسناد اصلاحکنندههای گرافیک مراجعه کنید.
سیستم مختصات
برای رسم کردن چیزی روی صفحهنمایش، باید انحراف (x و y) و اندازه
موردتان را بدانید. در بسیاری از روشهای طراحی در DrawScope، موقعیت و اندازه
توسط مقادیر پارامتر پیشفرض ارائه میشود. پارامترهای پیشفرض معمولاً عنصر را در نقطه [0, 0] روی بوم نقاشی قرار میدهند و size پیشفرضی ارائه میدهند که کل ناحیه طراحی را پر میکند، مانند مثال بالا - میبینید که مستطیل در بالا سمت راست قرار گرفته است. برای تنظیم اندازه و موقعیت
موردتان، باید سیستم مختصات در «نوشتن» را درک کنید.
مبدأ سیستم مختصات ([0,0]) در سمت راستترین پیکسل در
ناحیه طراحی قرار دارد. با حرکت بهسمت راست، x افزایش مییابد و با حرکت بهسمت پایین، y افزایش مییابد.
برای مثال، اگر میخواهید خط موربی از گوشه بالا سمت راست
ناحیه بوم نقاشی به گوشه پایین سمت چپ بکشید، میتوانید از تابع
DrawScope.drawLine() استفاده کنید و انحراف شروع و پایان را با
موقعیتهای x و y مربوطه مشخص کنید:
Canvas(modifier = Modifier.fillMaxSize()) { val canvasWidth = size.width val canvasHeight = size.height drawLine( start = Offset(x = canvasWidth, y = 0f), end = Offset(x = 0f, y = canvasHeight), color = Color.Blue ) }
تبدیلهای پایه
DrawScope تبدیلهایی ارائه میدهد تا مکان یا نحوه اجرای دستورات طراحی را تغییر دهد.
مقیاس
از
DrawScope.scale()
برای افزایش اندازه عملیات طراحی با یک عامل استفاده کنید. عملیاتی مثل
scale() بر همه عملیاتهای طراحی در لامبدای مربوطه اعمال میشود. برای مثال، کد زیر scaleX را ۱۰ برابر و scaleY را ۱۵ برابر افزایش میدهد:
Canvas(modifier = Modifier.fillMaxSize()) { scale(scaleX = 10f, scaleY = 15f) { drawCircle(Color.Blue, radius = 20.dp.toPx()) } }
ترجمه Google
از
DrawScope.translate()
برای جابهجا کردن عملیات طراحی به بالا، پایین، چپ، یا راست استفاده کنید. برای مثال، کد زیر طراحی را ۱۰۰ پیکسل به راست و ۳۰۰ پیکسل به بالا حرکت میدهد:
Canvas(modifier = Modifier.fillMaxSize()) { translate(left = 100f, top = -300f) { drawCircle(Color.Blue, radius = 200.dp.toPx()) } }
چرخاندن
از
DrawScope.rotate()
برای چرخاندن عملیات طراحی حول یک نقطه محوری استفاده کنید. برای مثال، کد زیر مستطیلی را ۴۵ درجه میچرخاند:
Canvas(modifier = Modifier.fillMaxSize()) { rotate(degrees = 45F) { drawRect( color = Color.Gray, topLeft = Offset(x = size.width / 3F, y = size.height / 3F), size = size / 3F ) } }
rotate() برای اعمال چرخش به محدوده طراحی کنونی استفاده میکنیم که مستطیل را ۴۵ درجه میچرخاند.
حاشیه
از DrawScope.inset() برای تنظیم پارامترهای پیشفرض کنونی
DrawScope استفاده کنید، مرزهای طراحی را تغییر دهید و طراحیها را
براساس آن ترجمه کنید:
Canvas(modifier = Modifier.fillMaxSize()) { val canvasQuadrantSize = size / 2F inset(horizontal = 50f, vertical = 30f) { drawRect(color = Color.Green, size = canvasQuadrantSize) } }
این کد عملاً به دستورات طراحی حاشیه اضافه میکند:
چندین تبدیل
برای اعمال چندین تبدیل روی طراحیهایتان، از تابع
DrawScope.withTransform() استفاده کنید که یک تبدیل واحد ایجاد میکند و
اعمال میکند که همه تغییرات موردنظرتان را ترکیب میکند. استفاده از
withTransform() کارآمدتر از انجام تماسهای تودرتو با تبدیلهای
تکی است، زیرا همه تبدیلها بهصورت همزمان در یک
عملیات واحد انجام میشوند، بهجای اینکه Compose مجبور باشد هریک از
تبدیلهای تودرتو را محاسبه و ذخیره کند.
برای مثال، کد زیر هم ترجمه و هم چرخش را روی مستطیل اعمال میکند:
Canvas(modifier = Modifier.fillMaxSize()) { withTransform({ translate(left = size.width / 5F) rotate(degrees = 45F) }) { drawRect( color = Color.Gray, topLeft = Offset(x = size.width / 3F, y = size.height / 3F), size = size / 3F ) } }
withTransform برای اعمال هم چرخش و هم انتقال استفاده کنید، مستطیل را بچرخانید و آن را به چپ منتقل کنید.عملیات رایج طراحی
کشیدن نوشتار
برای رسم نوشتار در «نگارش»، معمولاً میتوانید از Text composable استفاده کنید. بااینحال،
اگر در DrawScope هستید یا میخواهید نوشتارتان را بهصورت دستی با
سفارشیسازی بکشید، میتوانید از
DrawScope.drawText()
روش استفاده کنید.
برای رسم نوشتار، بااستفاده از rememberTextMeasurer TextMeasurer ایجاد کنید
و drawText را با اندازهگیر فراخوانی کنید:
val textMeasurer = rememberTextMeasurer() Canvas(modifier = Modifier.fillMaxSize()) { drawText(textMeasurer, "Hello") }
اندازهگیری نوشتار
کشیدن نوشتار کمی متفاوت از دیگر فرمانهای طراحی است. معمولاً، شما به فرمان طراحی اندازه (عرض و ارتفاع) را میدهید تا شکل/تصویر را با آن اندازه رسم کند. در نوشتار، چند پارامتر وجود دارد که اندازه نوشتار پردازششده را کنترل میکند، مثل اندازه قلم، قلم، حروف پیوسته، و فاصله بین حروف.
با «نوشتن»، میتوانید از TextMeasurer برای دسترسی به اندازه اندازهگیریشده نوشتار، بسته به عوامل بالا، استفاده کنید. اگر میخواهید پشت نوشتار پسزمینهای بکشید، میتوانید از اطلاعات اندازهگیریشده برای دریافت اندازه ناحیهای که نوشتار اشغال میکند استفاده کنید:
val textMeasurer = rememberTextMeasurer() Spacer( modifier = Modifier .drawWithCache { val measuredText = textMeasurer.measure( AnnotatedString(longTextSample), constraints = Constraints.fixedWidth((size.width * 2f / 3f).toInt()), style = TextStyle(fontSize = 18.sp) ) onDrawBehind { drawRect(pinkColor, size = measuredText.size.toSize()) drawText(measuredText) } } .fillMaxSize() )
این تکهکد پسزمینهای صورتی برای نوشتار تولید میکند:
تنظیم محدودیتها، اندازه قلم، یا هر داراییای که بر اندازه اندازهگیریشده تأثیر میگذارد
منجر به گزارش اندازه جدید میشود. میتوانید اندازه ثابتی برای width
و height تنظیم کنید و نوشتار از TextOverflow تنظیمشده پیروی میکند. برای
مثال، کد زیر نوشتار را در ⅓ ارتفاع و ⅓ عرض
فضای ترکیبشدنی پرداز میکند و TextOverflow را روی TextOverflow.Ellipsis تنظیم میکند:
val textMeasurer = rememberTextMeasurer() Spacer( modifier = Modifier .drawWithCache { val measuredText = textMeasurer.measure( AnnotatedString(longTextSample), constraints = Constraints.fixed( width = (size.width / 3f).toInt(), height = (size.height / 3f).toInt() ), overflow = TextOverflow.Ellipsis, style = TextStyle(fontSize = 18.sp) ) onDrawBehind { drawRect(pinkColor, size = measuredText.size.toSize()) drawText(measuredText) } } .fillMaxSize() )
اکنون نوشتار در محدودیتها با یک بیضی در انتها رسم میشود:
TextOverflow.Ellipsis با محدودیتهای ثابت در اندازهگیری نوشتار.کشیدن تصویر
برای رسم ImageBitmap با DrawScope، تصویر را بااستفاده از
ImageBitmap.imageResource() بار کنید و سپس drawImage را فراخوانی کنید:
val dogImage = ImageBitmap.imageResource(id = R.drawable.dog) Canvas(modifier = Modifier.fillMaxSize(), onDraw = { drawImage(dogImage) })
ImageBitmap در «بوم نقاشی».کشیدن شکلهای پایه
در DrawScope، توابع زیادی برای رسم شکل وجود دارد. برای رسم شکل، از یکی
از توابع رسم ازپیشتعریفشده، مثل drawCircle، استفاده کنید:
val purpleColor = Color(0xFFBA68C8) Canvas( modifier = Modifier .fillMaxSize() .padding(16.dp), onDraw = { drawCircle(purpleColor) } )
API |
خروجی |
|
|
|
|
|
|
|
|
|
|
|
|
|
رسم کردن مسیر
مسیر مجموعهای از دستورالعملهای ریاضی است که پساز اجرا شدن به طراحی منجر میشود. DrawScope میتواند بااستفاده از روش DrawScope.drawPath() مسیری را رسم کند.
برای مثال، فرض کنید میخواهید مثلثی بکشید. بااستفاده از اندازه ناحیه طراحی میتوانید مسیری با توابعی مثل lineTo() و moveTo() تولید کنید.
سپس، با این مسیر تازه ایجادشده با drawPath() تماس بگیرید تا مثلثی ایجاد شود.
Spacer( modifier = Modifier .drawWithCache { val path = Path() path.moveTo(0f, 0f) path.lineTo(size.width / 2f, size.height / 2f) path.lineTo(size.width, 0f) path.close() onDrawBehind { drawPath(path, Color.Magenta, style = Stroke(width = 10f)) } } .fillMaxSize() )
Path در «نوشتن».دسترسی به Canvas شیء
با DrawScope، به شیء Canvas دسترسی مستقیم ندارید. میتوانید از
DrawScope.drawIntoCanvas() برای
دسترسی به خود شیء Canvas استفاده کنید که میتوانید توابع را در آن فراخوانی کنید.
برای مثال، اگر Drawable سفارشی دارید که میخواهید روی
بوم نقاشی کنید، میتوانید به بوم نقاشی دسترسی پیدا کنید و Drawable#draw() را فراخوانی کنید و
شیء Canvas را ارسال کنید:
val drawable = ShapeDrawable(OvalShape()) Spacer( modifier = Modifier .drawWithContent { drawIntoCanvas { canvas -> drawable.setBounds(0, 0, size.width.toInt(), size.height.toInt()) drawable.draw(canvas.nativeCanvas) } } .fillMaxSize() )
Drawable.بیشتر بدانید
برای اطلاعات بیشتر درباره «کشیدن در نوشتن»، به منابع زیر نگاهی بیندازید:
- «اصلاحکنندههای گرافیک» - با انواع مختلف اصلاحکنندههای طراحی آشنا شوید.
- قلممو - با نحوه سفارشیسازی کردن نقاشی محتوا آشنا شوید.
- چیدمانها و گرافیکهای سفارشی در «نوشتن» - «نشست توسعهدهندگان Android» 2022 - با نحوه ساختن میانای کاربری سفارشی در «نوشتن» با «چیدمانها» و «گرافیکها» آشنا شوید.
- نمونه JetLagged - نمونهای از Compose که نحوه رسم نمودار سفارشی را نشان میدهد.
توصیهشده برای شما
- توجه: نوشتار پیوند وقتی جاوا اسکریپت خاموش است نمایش داده میشود
- اصلاحکنندههای گرافیک
- گرافیک در Compose
- خطوط تراز در Jetpack Compose