اگر میخواهید نمای سفارشی خود را در اندروید از صفر ایجاد کنید، دانستن اینکه چه توابعی برای رسم در Convas موجود است بسیار مفید است.
در این مقاله 23 تابع رسم موجود در Convas را برای شما لیست کردهام. ممکن است که مواردی را ببینید که هرگز فکر نمیکردید وجود دارند(من خودم در مورد بعضی از توابع متعجب شدم).
در زیر میتوانید طبقهبندی آنها را ببینید:
- طراحی هندسی
- ترسیم متن
- طراحی رنگ
- طراحی تصویر
در صورتی که تجربه درست کردن نماهای سفارشی را ندارید میتوانید به آموزشهای زیر مراجعه کنید:
https://medium.com/@elye.project/building-custom-component-with-kotlin-fc082678b080
https://medium.com/@elye.project/custom-touchable-animated-view-in-kotlin-3ad599f85dbc
https://proandroiddev.com/android-draw-a-custom-view-ef79fe2ff54b
طراحی هندسی
بیشتر افراد از Convas برای ترسیم موارد هندسی استفاده میکنند
Drawline
با استفاده از این تابع به سادگی میتوانید یک خط رسم کنید
canvas.drawLine(startX, startY, endX, endY, paint)
DrawLines
اگر میخواهید بیش از یک خط بکشید به جای اجرای چند بار تابع drawline میتوانیم از drawLines استفاده کنیم. فقط باید یک لیست از مختصات همانند زیر ارائه دهیم:
canvas.drawLines(
floatArrayOf(
startFirstX, startFirstY, endFirstX, endFirstY,
startSecondX, startSecondY, endSecondX, endSecondY),
paint)
drawPoint
در حالی که شما میتوانید با ترسیم خط با همان مختصات شروع وپایان، نقطه را رسم کنید، این روش یک هک محسوب میشود. بنابراین تابع drawpoint ارائه شد.
canvas.drawPoint(coordinateX, coordinateY, paint)
drawPoints
مانند خطوط، میتوانید چندین نقطه با آرایهای از مختصات بکشید.
canvas.drawPoints(
floatArrayOf(
startX, startY,
startSecondX, startSecondY),
paint)
drawRect
با استفاده از مختصات یا کلاس Rect یک مستطیل بکشید.
canvas.drawRect(
Rect(startX, topY, endX, bottomY),
paint)
drawRoundRect
اگر میخواهید یک مستطیل با گوشههای گرد داشته باشید، از drawRoundRect استفاده کنید. شبیه به drawRect است اما با افزودن radius و radiusY میتوان انحنای گوشهها را گرد کرد.
canvas.drawRoundRect(rect, radiusX, radiusY, projectResources.paint)
اگر radiusX برابر با radiusY باشد گوشهای به طور مساوی گرد ایجاد میکند.
هنگامی که radiusX = radiusY باشد، گوشههایی گرد معمول همانند شکل زیر خواهید داشت:
اگر radiusX بزرگتر از radius باشد، شکل همانند زیر خواد شد:
اگر radius کوچکتر از radius باشد، شکلی همانند زیر ایجاد خواد شد:
drawCircle
تابع drawCircle بسیار ساده است. فقط به مختصات مرکز و شعاع نیاز دارد.
canvas.drawCircle(
centerCoordinateX, centerCoordinateY,
radius,
paint)
drawOval
برخلاف رسم دایره به شعاع نیاز نداریم. در عوض یک مستطیل ارائه میدهیم که بیضی براساس آن رسم خواهد شد.
canvas.drawOval(rect, paint)
drawArc
رسم قوس از همان مکانیزم استفاده میکند که یک بیضی را رسم میکند: با استفاده از مستطیل. همچنین پارامترهای دیگری مانند startAngle, sweepAngle و useCenter نیز دارد.
canvas.drawArc(rect, startAngle, sweepAngle, useCenter, paint)
برای startAngle انتهای وسط را به عنوان شروع، یعنی 90 درجه در جهت عقربه ساعت حساب کنید. از آنجا startAngle صفر در نظر گرفته میشود. سپس sweepAngle از startAngle محاسبه میشود. هردو از درجه زاویه استفاده میکنند.
useCenter یک متغیر boolean برای تعیین اینکه آیا قوس به مرکز وصل شده است یا خیر. تصاویر زیر تفاوت بین استفاده از useCenter با مقدار false و true را نشان میدهد.
useCenter = false
useCenter = true
drawPath
گاهی اوقات میخواهیم چیزی را رسم کنیم که محدود به خطوط هندسی عادی نباشد. ما در اینجا از drawPath استفاده میکنیم، که path شئی است که شامل مسیری است که میخواهیم بکشیم. که همچنین شامل توابعی مانند moveTo و lineTo است، مانند استفاده از یک مداد برای حرکت و ترسیم.
مثالی که در زیر مشاهده میکنید با اسفاده از drawPath یک علامت متاقطع را رسم کردهایم:
val path = Path()
path.moveTo(startX, topY)
path.lineTo(endX, bottomY)
path.moveTo(startX, bottomY)
path.lineTo(endX, topY)
canvas.drawPath(path, paint)
drawPath یک تابع بسیار مفید است. بسیاری از آن برای تهیه برنامههای طراحی در اندروید استفاده میکنند. نمونههایی را میتوانید در لینکهای زیر ببینید:
https://android.jlelse.eu/a-guide-to-drawing-in-android-631237ab6e28
https://medium.com/@ssaurel/learn-to-create-a-paint-application-for-android-5b16968063f8
drawVerticales
این یک تابع نسبتاً پیچیده است، که مثلثها یا رئوس را با حداقل نقاط رسم میکند. به عنوان مثال با شش مختصات میتوانید چهار مثلث را رسم کنید:
هنگام تکرار میتوان از آن برای مدل سازی 3D استفاده کرد. طراحی زیر (یک گل رز 3D) با drawVerticales ترسیم شده است.
ترسیم متن
اگر مجبور شدیم خودمان متن را ترسیم کنیم، که این روش یک حقه است :). خوشبختانه ما چندین گزینه خوب داریم:
drawText
در اندروید ما بطور معمول از TextView برای تمام متنها استفاده میکنیم. با این حال اگر میخواهید کنترل بهتری روی متنهایتان داشته باشید مانند تغییرات پویا، موقعیتیابی دقیق و غیره، بهتر است از تابع drawText در Convas استفاده کنید.
در زیر میتوانید نحوه استفاده از تابع drawText را ببینید:
canvas.drawText(text, coordinateX, coordinateY, paintText)
در صورت تنظیمات صحیح میتوانید همانند زیر با آن بازی کنید:
ترسیم Staticlayout
تابع drawText محدودیتهایی دارد. متنهای طولانی را به خط بعدی نمیبرد و همچنین /n را پشتیبانی نمیکند.
برای انجام چنین کاری ما نیاز به StaticLayout داریم تا تا هنگام ترسیم متن بتواند کلمات طولانی را به خط بعدی ببرد.
StaticLayout در واقع یک تابع ترسیم در Canvas نیست، بلکه در عوض خود را بر روی Canvas میکشد:
val staticLayout =
StaticLayout.Builder.obtain(
TEXT, 0, TEXT.length, textPaint, width
).build()
canvas.save()
canvas.translate(coordinateX, coordinateY)
staticLayout.draw(canvas)
canvas.restore()
نتیجه:
drawPosText
drawPosText هر کاراکتر را در یک موقعیت مشخص قرار میدهد. در زیر کلمه fly در موقعیتهای مختلف نوشته شده است.
Api آن همانند زیر است:
val posArray = listOf(x1, y1, x2, y2, x3, y3 ...).toFloatArray()
canvas.drawPosText(TEXT, startIndex, endIndex, posArray, paint)
مختصات نقاط ارائه شده باید حداقل با حروفی که قرار است رسم شوند یکی باشد، در غیر این صورت crash میکند.
نکته: این Api منسوخ شده است، زیرا این روش از ترکیب و تجزیه glyph پشتیبانی نمیکند و بنابراین نباید برای ارائه اسکریپتهای پیچیده استفاده شود. همچنین از کاراکترهای تکمیلی مانند ایموجیها پشتیبانی نمیکند.
drawTextOnPath
با استفاده از یک مسیر، میتوانیم متن خود را در مسیر ارائه شده قرار دهیم.
موقعیتهای x و y به موقعیت مسیر داده شده نسبت داده میشوند.
canvas.drawTextOnPath(TEXT, path, x, y, paint)
در زیر نمونهای از یک مسیر به شکل V قرار دارد که متن خود را بر روی آن ترسیم کردهایم:
drawTextRun
این تابع کمی پیچیدهتر است، زیرا معمولا با کلمات انگلیسی استفاده نمیشود. این فقط مربوط به زبانهایی است که بسته به دید حروف اطراف به شکل متفاوتی ترسیم میشوند.
به عنوان مثال تصویر زیر دارای دو خط از دو حروف است. دو حروف در هر دو خط یکسان هستند. با این حال آنها متفاوت نوشته شده اند. در خط اول آنها بخشی از یک کلمه بزرگتر هستند، در حالی که در خط دوم دو حروف به صورت جداگانه بیان میشود.
طراحی رنگ
رنگ آمیزی برای پیشزمینه و پسزمینه Canvas بکار میرود و بسیار پر کاربرد است.
drawRGB
این تابع فقط رنگ را بر روی Canvas نقاشی میکند، و برای تنظیم رنگ پسزمینه مفید است.
canvas.drawRGB(red, green, blue)
// Each is between 0 and 255, where 0 is not there, and 255 is full.
// When alpha is 255, it is opaque, and 0 is transparent.
drawARGB
این تابع شبیه به drawRGB است، با این تفاوت که قابلیت رنگ نیمه شفاف را هم دارد.
canvas.drawARGB(alpha, red, green, blue)
// When alpha is 255, it is opaque, and 0 is transparent.
این برای زمانی مفید است که میخواهیم یک لایه رنگ تار و یا نیمه شفاف بر روی آیتم زیرین قرار دهیم.
تصویر اصلی
تصویر نیمه شفاف قرمز
drawColor
در صورتی که مایل به استفاده از رنگهای موجود در منابع خود به جای ARGB هستید، میتوانید از این API استفاده کنید.
canvas.drawColor(context.getColor(R.color.colorPrimary))
drawPaint
بعضی اوقات میخواهیم رنگهای خیالیتر ایجاد کنیم. به جای استفاده از ARGB و یا منابع رنگ، میتوانیم از شیء Paint استفاده کنیم. در زیر مثالی از آن میبینید:
val gradientPaint by lazy {
Paint().apply {
shader = RadialGradient(
width/2f,
height/2f,
height/2f,
Color.GREEN,
Color.RED,
Shader.TileMode.MIRROR
)
}
canvas.drawPaint(gradientPaint)
طراحی تصویر
بدون امکان بارگیری تصاویر برای ترسیم و دستکاری آنها، ترسیم Canvas ناقص خواهد بود. پس بیایید آن را بررسی کنیم...
drawBitmap
با دادن یک Bitmap، میتوانیم آن را بر روی Canvas بکشیم.
private val bitmap by lazy {
BitmapFactory.decodeResource(resources, R.drawable.image)
}
canvas.drawBitmap(bitmap, sourceRect, destRect, paint)
پارامترهای مورد نیاز Bitmap و destRect هستند.
- Bitmap میتواند از منابع استخراج شود
- destRect ناحیه مستطیل Canvas است که باید روی آن کشیده شود
گزینههای اختیاری (میتواند null باشد) sourceRect و paint هستند.
- sourceRect مستطیلی است که زیر مجموعه تصویر را ترسیم میکند. وقتی که تهی است، کل تصویر گرفته میشود. (نکته: این برای بعضی از انیمیشنها بسیار مفید است، وقتی تصویری از کل نقاشی متحرک اضافه میشود، فقط زیر مجموعه آن نمایش داده میشود، همانطور که در این لینک میبینید.)
- paint میتواند تهی باشد، و همچنان طبق معمول Bitmap ترسیم میشود. Paint زمانی مفید است که میخواهیم آن را با تصویر دیگری mask کنیم.
drawPicture
اگر ترکیبی از چند چیز برای ترسیم دارید، و ممکن است که چندین بار اتفاق بیافتد و همچنین نمیخواهید پردازش کند شود، میتوانید کل طرح ترسیم شده خود را در تصویر قرار دهید.
در زیر یک مثال ساده وجود دارد که در آن طرح رسم شده خود را در یک تصویر ذخیره میکنیم:
private val picture by lazy {
val picture = Picture()
val pCanvas = picture.beginRecording(width, height)
pCanvas.drawBitmap(bitmap, null, rect, null)
picture.endRecording()
picture
}
و در صورت نیاز به آن، فقط نیاز است این کار را انجام دهیم:
canvas.drawPicture(picture)
این باعث میشود تمام مراحل ترسیم شما برای مواردی که بارها و بارها تکرار میشوند تسریع شود.
drawBitmapMesh
این تابع برای دستکاری در تصویر Bitmap ترسیم شده است. باتوجه به یک تصویر، میتوانیم مختصات را درون تصویر تنظیم کنیم و یک نقطه را به موقعیت دیگری تغییر دهیم.
به عنوان مثال تصویر زیر با مرکز x و y در مقطع خط سفید نشان داده شده است.
با این وجود با استفاده از drawBitmapMesh میتوانیم مختصات را تغییر دهیم و به ترتیب تصویر نیز تغییر داده میشود.
شما میتوانید همهی این نمونه کدهای Canvas را در این لینک پیدا کنید.
دیدگاه و پرسش
در حال دریافت نظرات از سرور، لطفا منتظر بمانید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید