بسیاری از برنامهها باید بتوانند دقیقاً آنچه را که روی صفحهنمایش کشیده میشود کنترل کنند. این کار ممکن است بهسادگی قرار دادن یک جعبه یا دایره در جای مناسب روی صفحهنمایش باشد، یا ممکن است چیدمان پیچیدهای از عناصر گرافیکی در سبکهای مختلف باشد.
طراحی ساده با اصلاحکنندهها و DrawScope
روش اصلی برای ترسیم چیزی سفارشی در Compose با اصلاحکنندهها است، مانند
Modifier.drawWithContent،
Modifier.drawBehind، و
Modifier.drawWithCache.
برای مثال، برای رسم چیزی در پشت ترکیبپذیرتان، میتوانید از اصلاحکننده drawBehind برای شروع اجرای فرمانهای رسم استفاده کنید:
Spacer( modifier = Modifier .fillMaxSize() .drawBehind { // this = DrawScope } )
اگر تنها چیزی که نیاز دارید یک composable است که ترسیم میکند، میتوانید از
composable Canvas استفاده کنید. Canvas composable is a
convenient wrapper around 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 پیشفرضی ارائه میدهند که کل ناحیه طراحی را پر میکند، مانند مثال بالا - میتوانید ببینید که مستطیل در بالا سمت چپ قرار گرفته است. برای تنظیم اندازه و موقعیت
موردتان، باید سیستم مختصات را در Compose درک کنید.
مبدأ سیستم مختصات ([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 برای اعمال چرخش و انتقال استفاده کنید، مستطیل را بچرخانید و آن را به چپ منتقل کنید.عملیات طراحی رایج
نوشتار ترسیم کنید
برای ترسیم نوشتار در Compose، معمولاً میتوانید از ترکیبپذیر Text استفاده کنید. بااینحال،
اگر در DrawScope هستید یا میخواهید نوشتارتان را بهصورت دستی با
سفارشیسازی بکشید، میتوانید از
روش DrawScope.drawText()
استفاده کنید.
برای ترسیم نوشتار، بااستفاده از rememberTextMeasurer، TextMeasurer ایجاد کنید
و drawText را با اندازهگیر فراخوانی کنید:
val textMeasurer = rememberTextMeasurer() Canvas(modifier = Modifier.fillMaxSize()) { drawText(textMeasurer, "Hello") }
اندازهگیری نوشتار
نوشتن نوشتار کمی با دیگر فرمانهای طراحی متفاوت است. معمولاً، اندازه (عرض و ارتفاع) را برای کشیدن شکل/تصویر به فرمان طراحی میدهید. با نوشتار، چند پارامتر وجود دارد که اندازه نوشتار پردازششده را کنترل میکند، مانند اندازه قلم، قلم، نویسهنگاری، و فاصله بین حروف.
با Compose، میتوانید از 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 در Canvas.رسم شکلهای پایه
توابع زیادی برای رسم شکل در 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 در Compose.درحال دسترسی به شیء 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.بیشتر بدانید
برای اطلاعات بیشتر درباره «ترسیم» در Compose، منابع زیر را ببینید:
- اصلاحکنندههای گرافیکی - با انواع مختلف اصلاحکنندههای طراحی آشنا شوید.
- قلممو - با نحوه سفارشیسازی نقاشی محتوایتان آشنا شوید.
- چیدمانها و گرافیکهای سفارشی در Compose - نشست توسعهدهندگان Android ۲۰۲۲ - با نحوه ساختن واسط کاربر سفارشی در Compose بااستفاده از «چیدمانها» و «گرافیکها» آشنا شوید.
- JetLagged Sample - Compose Sample that shows how to draw a custom graph.
توصیهشده برای شما
- توجه: وقتی جاوا اسکریپت خاموش باشد، نوشتار پیوند نمایش داده میشود
- اصلاحکنندههای گرافیک
- گرافیک در Compose
- خطوط تراز در Jetpack Compose