Android میں Canvas — android.graphics پیکیج کا ایک کلاس ہے جو View پر 2D رینڈرنگ کے لیے API فراہم کرتا ہے۔ Canvas ایک کینوس کی طرح کام کرتا ہے جس پر ڈیولپر مختلف draw* طریقوں کا استعمال کرتے ہوئے ہندسی اشکال، متن، تصاویر اور راستے کھینچتا ہے۔ Android ڈیولپرز دستاویزات (2025) کے مطابق، Canvas Android میں کسٹم رینڈرنگ کے لیے بنیادی ٹول ہے اور اسٹائل اور رنگوں کی وضاحت کے لیے Paint کلاس کے ساتھ استعمال ہوتا ہے۔ ہر onDraw() کال کو View کے bitmap بفر سے منسلک ایک تیار Canvas مثال ملتی ہے۔
اہم نکات
Canvas — Android میں مرکزی 2D گرافکس کلاس ہے جو ایک سطح پر ڈرائنگ کے لیے طریقے فراہم کرتا ہے۔ ہر Canvas ایک Bitmap سے منسلک ہوتا ہے — میموری کا ایک علاقہ جہاں ڈرائنگ آپریشنز کے نتائج ریکارڈ کیے جاتے ہیں۔ جب ایک View دوبارہ کھینچی جاتی ہے، سسٹم onDraw() میں ایک Canvas منتقل کرتا ہے جو پہلے سے اس View کے بفر سے منسلک ہوتا ہے۔
Canvas ایک کوآرڈینیٹ سسٹم میں کام کرتا ہے جہاں (0,0) اوپر بائیں کونا ہے، X محور دائیں جاتا ہے، Y محور نیچے جاتا ہے۔ تمام ڈرائنگ آپریشنز Canvas کی موجودہ حالت استعمال کرتے ہیں، جس میں تبدیلی میٹرکس، کلپنگ ایریا اور Paint اسٹائل شامل ہے۔ Android دستاویزات (2025) کے مطابق، Canvas API میں مختلف اقسام کے گرافک اولیاء کے لیے 30 سے زیادہ draw* طریقے شامل ہیں۔
Android 3.0 (API 11) سے Canvas DisplayList کے ذریعے ہارڈویئر ایکسلریشن کو سپورٹ کرتا ہے۔ ایکسلریٹڈ موڈ میں، Canvas آپریشنز DisplayList میں ریکارڈ کیے جاتے ہیں اور پھر GPU پر عمل کیے جاتے ہیں۔ یہ نمایاں کارکردگی کا فائدہ دیتا ہے لیکن حدود عائد کرتا ہے: کچھ Canvas آپریشنز (غیر Path کلپ کے ساتھ clipPath) ایکسلریٹڈ موڈ میں سپورٹ نہیں ہوتے۔
Canvas بنیادی اولیاء ڈرائنگ کے لیے طریقوں کا ایک سیٹ فراہم کرتا ہے۔ ہر طریقہ ہندسی پیرامیٹرز اور ایک Paint آبجیکٹ قبول کرتا ہے جو بصری اسٹائل کی وضاحت کرتا ہے۔
| طریقہ | مقصد | مثال |
|---|---|---|
| drawRect() | مستطیل کھینچتا ہے | canvas.drawRect(10f, 10f, 100f, 100f, paint) |
| drawCircle() | دائرہ کھینچتا ہے | canvas.drawCircle(50f, 50f, 30f, paint) |
| drawLine() | لکیر کھینچتا ہے | canvas.drawLine(0f, 0f, 100f, 100f, paint) |
| drawText() | متن کھینچتا ہے | canvas.drawText(“Hello”, 10f, 20f, paint) |
| drawBitmap() | تصویر کھینچتا ہے | canvas.drawBitmap(bitmap, 0f, 0f, paint) |
| drawPath() | صوابدیدی راستہ کھینچتا ہے | canvas.drawPath(path, paint) |
| drawOval() | بیضوی کھینچتا ہے | canvas.drawOval(rectF, paint) |
| drawArc() | قوس یا سیکٹر کھینچتا ہے | canvas.drawArc(rectF, 0f, 90f, true, paint) |
ہر طریقہ کسی بھی ترتیب میں بلایا جا سکتا ہے — Canvas کالز کی ترتیب میں کھینچتا ہے، نئے عناصر کو پچھلے عناصر کے اوپر تہہ کرتا ہے۔ پیچیدہ کمپوزیشنز کے لیے، Canvas حالت کو محفوظ اور بحال کرنے کے ساتھ ملٹی لیئر رینڈرنگ تکنیک استعمال کی جاتی ہے۔
Paint — وہ کلاس ہے جو یہ بتاتا ہے کہ Canvas کیسے کھینچے گا۔ Paint کے بغیر، Canvas طریقے بیکار ہیں — یہ رنگ، لکیر کی موٹائی، بھرائی کا اسٹائل، متن کا سائز، اثرات (سایہ، گریڈینٹ، دھندلاپن) اور ملاوٹ کا موڈ سیٹ کرتا ہے۔
Paint کی اہم خصوصیات: color (رنگ)، style (FILL، STROKE یا FILL_AND_STROKE)، strokeWidth (لکیر کی موٹائی)، textSize (متن کا سائز)، isAntiAlias (کناروں کو ہموار کرنا)، shader (گریڈینٹ یا تصویر)۔ Paint آبجیکٹ بنانا ایک مہنگا آپریشن ہے، اس لیے اسے ایک بار بنا کر دوبارہ استعمال کرنا چاہیے۔
private val fillPaint = Paint().apply {
color = Color.parseColor("#FF6200EE")
style = Paint.Style.FILL
isAntiAlias = true
}
private val strokePaint = Paint().apply {
color = Color.WHITE
style = Paint.Style.STROKE
strokeWidth = 4f
isAntiAlias = true
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.drawCircle(100f, 100f, 80f, fillPaint)
canvas.drawCircle(100f, 100f, 80f, strokePaint)
}
اس مثال میں، دو Paint آبجیکٹ استعمال کیے گئے ہیں: ایک دائرے کو جامنی رنگ سے بھرنے کے لیے، دوسرا سفید خاکہ کے لیے۔ بھرائی اور خاکہ کو الگ کرنا ایک معیاری عمل ہے جو آبجیکٹ کو دوبارہ بنائے بغیر ظاہری شکل پر لچکدار کنٹرول دیتا ہے۔
گریڈینٹ بھرائی کے لیے، Paint ایک Shader قبول کرتا ہے — ذیلی کلاسز LinearGradient، RadialGradient، SweepGradient۔ Shader setShader() طریقہ کے ذریعے Paint سے منسلک ہوتا ہے اور یہ بتاتا ہے کہ رنگ ڈرائنگ ایریا میں کیسے بدلتا ہے۔
Canvas کوآرڈینیٹ سسٹم کی میٹرکس تبدیلیوں کو سپورٹ کرتا ہے: translate() (منتقلی)، rotate() (گھماؤ)، scale() (پیمائش) اور skew() (ترچھا پن)۔ تبدیلیاں جمع ہوتی ہیں: ہر بعد کی کال پچھلی کالوں کے اوپر لاگو ہوتی ہے۔
تبدیلی اسٹیک کا انتظام save() اور restore() کے ذریعے کیا جاتا ہے۔ save() موجودہ Canvas حالت (میٹرکس، کلپ) کو اسٹیک میں محفوظ کرتا ہے، restore() آخری محفوظ شدہ حالت کو بحال کرتا ہے۔ save() اور restore() کے درمیان نیسٹڈ تبدیلیاں لاگو کی جا سکتی ہیں۔
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.save() // Save initial state
canvas.translate(100f, 100f) // Translate origin
// First square
canvas.drawRect(0f, 0f, 50f, 50f, fillPaint)
canvas.save() // Save after translate
canvas.rotate(45f, 25f, 25f) // Rotate around square center
// Rotated square
canvas.drawRect(0f, 0f, 50f, 50f, strokePaint)
canvas.restore() // Restore after rotate
canvas.restore() // Restore initial state
}
تبدیلیاں شروع کرنے سے پہلے ہمیشہ save() اور انہیں مکمل کرنے کے بعد restore() استعمال کریں۔ غیر متوازن save/restore جوڑے میٹرکس کے جمع ہونے اور بعد کے عناصر کی غلط رینڈرنگ کا سبب بنتے ہیں۔
پیچیدہ گرافکس کے لیے، Canvas کو Bitmap اور Path کے ساتھ ملایا جاتا ہے۔ Bitmap تصاویر لوڈ کرنے اور رینڈر شدہ فریموں کو کیش کرنے کے لیے استعمال ہوتا ہے۔ Path صوابدیدی بیزیئر منحنی خطوط، کثیرالاضلاع اور پیچیدہ شکلیں بنانے کے لیے استعمال ہوتا ہے۔
آف اسکرین رینڈرنگ تکنیک: ایک Bitmap بنایا جاتا ہے، اس پر ایک علیحدہ Canvas کے ذریعے پیچیدہ منظر کھینچا جاتا ہے، اور پھر تیار Bitmap کو drawBitmap() کے ذریعے onDraw() میں آؤٹ پٹ کیا جاتا ہے۔ یہ ہر فریم پر مکمل دوبارہ ڈرائنگ کے بغیر پیچیدہ گرافکس کو اپ ڈیٹ کرنے کی اجازت دیتا ہے۔
private var offscreenBitmap: Bitmap? = null
private var offscreenCanvas: Canvas? = null
fun buildOffscreenScene(width: Int, height: Int) {
offscreenBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
offscreenCanvas = Canvas(offscreenBitmap)
// Render scene once
offscreenCanvas!!.drawColor(Color.WHITE)
drawGrid(offscreenCanvas!!)
drawComplexShape(offscreenCanvas!!)
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
offscreenBitmap?.let { canvas.drawBitmap(it, 0f, 0f, null) }
}
Path پیچیدہ شکلیں بنانے کے لیے استعمال ہوتا ہے: بیزیئر منحنی خطوط (quadTo، cubicTo)، قوس (arcTo)، لکیریں (lineTo)۔ Path بھرے ہوئے شکل کے لیے بند (close()) یا لکیروں کے لیے کھلا ہو سکتا ہے۔ بنیادی drawPath() طریقہ حتمی رینڈرنگ کے لیے Path اور Paint کو یکجا کرتا ہے۔
Canvas رینڈرنگ کارکردگی براہ راست ایپلیکیشن FPS کو متاثر کرتی ہے۔ اہم مسائل: onDraw() میں ضرورت سے زیادہ مختص، بار بار invalidate() کالز اور ہارڈویئر ایکسلریشن کا غیر بہترین استعمال۔
Paint، Path، Rect، RectF اور دیگر آبجیکٹ ایک بار انیشیالائزر یا setup() طریقہ میں بنائے جانے چاہئیں۔ onDraw() میں ہر مختص کچرا جمع کرنے والے پر دباؤ ڈالتا ہے، جس سے مائیکرو وقفے پیدا ہوتے ہیں۔ استثنا ناقابل تغیر آبجیکٹ کے لیے static یا companion object ہے۔
اگر زیادہ تر View نظر آنے والے علاقے کے باہر چھپا ہوا ہے (مثال کے طور پر، ScrollView میں)، رینڈرنگ کو محدود کرنے کے لیے canvas.clipRect() استعمال کریں۔ اس صورت میں ہارڈویئر ایکسلریشن غیر مرئی پکسلز کی کلپنگ کو مزید بہتر بناتا ہے۔
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
// Clip to visible area
canvas.save()
canvas.clipRect(scrollX, scrollY, scrollX + width, scrollY + height)
// Render large scene
renderScene(canvas)
canvas.restore()
}
پیچیدہ Canvas گرافکس والے Views کے لیے جو شاذ و نادر ہی اپ ڈیٹ ہوتے ہیں، LAYER_TYPE_HARDWARE کے ساتھ View.setLayerType() استعمال کریں۔ بار بار اپ ڈیٹ ہونے والی اینیمیشنز کے لیے، مہنگے ہارڈویئر لیئر اپ ڈیٹس سے بچنے کے لیے LAYER_TYPE_NONE استعمال کریں۔ GPU Profile Rendering اور Android Studio Profiler سے پروفائل کریں۔
اکثر پوچھے گئے سوالات
ہاں، آپ Canvas(Bitmap) بنا سکتے ہیں — ایک کنسٹرکٹر جو Bitmap قبول کرتا ہے۔ یہ آف اسکرین رینڈرنگ کے لیے استعمال ہوتا ہے: آپ Bitmap پر کھینچتے ہیں، پھر اسے drawBitmap() کے ذریعے آؤٹ پٹ کرتے ہیں۔ Canvas Surface (SurfaceView کے لیے) یا Picture کے ذریعے بھی بنایا جا سکتا ہے۔
Canvas — UI تھریڈ میں View پر ڈرائنگ کے لیے API ہے۔ SurfaceView — ایک علیحدہ Surface ہے جو اپنے Canvas (lockCanvas() / unlockCanvasAndPost()) کے ذریعے بیک گراؤنڈ تھریڈ سے اپ ڈیٹ ہو سکتا ہے۔ SurfaceView گیمز اور ویڈیو کے لیے ترجیح دی جاتی ہے۔
سب سے عام وجہ غیر متوازن save() اور restore() جوڑے ہیں۔ اگر تبدیلی (translate، rotate) کے بعد restore() نہ بلایا جائے، Canvas تبدیل شدہ کوآرڈینیٹ سسٹم میں رہتا ہے اور بعد کے عناصر آفسیٹ کے ساتھ کھینچے جاتے ہیں۔ اپنے save()/restore() جوڑے چیک کریں۔
افقی مرکز کے لیے Paint.setTextAlign(Paint.Align.CENTER) اور عمودی کے لیے Paint.getTextBounds() یا Paint.descent() / ascent() استعمال کریں۔ مرکز: canvas.drawText(متن, centerX, centerY - (ascent + descent) / 2, paint)۔
Canvas خود اینیمیشن نہیں بناتا — یہ صرف موجودہ حالت کھینچتا ہے۔ اینیمیشن invalidate() (یا postInvalidateOnAnimation()) کی متواتر کالز کے ذریعے حاصل کی جاتی ہے، ہر بار onDraw() میں ایک نیا فریم کھینچتا ہے۔ ہموار اینیمیشنز کے لیے Vsync کے ساتھ ہم آہنگی کے لیے ValueAnimator یا Choreographer استعمال کریں۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں