dispatchDraw() ViewGroup کلاس کا ایک طریقہ ہے جو Android درجہ بندی میں تمام چائلڈ Views کی ریکرسیو ڈرائنگ کے لیے ذمہ دار ہے۔ Android Developers Documentation (2026) کے مطابق، dispatchDraw مرکزی View کے draw() طریقہ میں onDraw کے بعد خود بخود کال کیا جاتا ہے اور تمام چائلڈ عناصر کو عبور کرتا ہے، ان کے اپنے draw() کو کال کرتا ہے۔ ڈویلپر کسٹم ViewGroups میں dispatchDraw کو اوور رائڈ کرتے ہیں تاکہ اثرات شامل کریں، چائلڈز کے اوپر گرافکس لگائیں یا ڈرائنگ کی ترتیب تبدیل کریں۔
اہم نکات
dispatchDraw(Canvas canvas) ViewGroup کلاس کا ایک protected طریقہ ہے جسے Android سسٹم موجودہ کنٹینر کے تمام چائلڈ Views کو ڈرائنگ کرنے کے لیے کال کرتا ہے۔ dispatchDraw معیاری ڈرائنگ پائپ لائن کا حصہ ہے: پہلے onDraw عمل میں آتا ہے (View کے اپنے مواد کی ڈرائنگ)، پھر dispatchDraw (چائلڈز کی ریکرسیو ڈرائنگ)، پھر onDrawForeground (پیش منظر اور اسکرول بار کی ڈرائنگ)۔ یہ طریقہ ایپلیکیشن کوڈ سے براہ راست کال کرنے کے لیے نہیں ہے۔
ViewGroup میں dispatchDraw کا معیاری نفاذ تمام چائلڈ Views کو عبور کرتا ہے، ان کی نمائش چیک کرتا ہے اور ہر ایک کے لیے draw(Canvas) کال کرتا ہے۔ عبور کرنے کی ترتیب چائلڈ انڈیکس (0 سے childCount - 1 تک) کے مطابق ہوتی ہے۔ اگر چائلڈ Views اوورلیپ ہوتے ہیں، تو فہرست میں بعد والے پہلے والوں کے اوپر ڈرائنگ ہوتے ہیں۔ dispatchDraw میں ترتیب تبدیل کرنے سے ڈرائنگ کا Z-order تبدیل کیا جا سکتا ہے۔
View (ViewGroup نہیں) کے لیے، dispatchDraw طریقہ خالی ہے — ایک عام View میں کوئی چائلڈ عناصر نہیں ہوتے، اس لیے ڈرائنگ کرنے کے لیے کچھ نہیں ہے۔ یہ طریقہ بیس View کلاس میں موجود ہے لیکن صرف ViewGroup مثالوں پر کال کیا جاتا ہے۔ ایک ڈویلپر dispatchDraw کے ڈیفالٹ رویے کے ذریعے چیک کر سکتا ہے کہ View میں چائلڈ عناصر ہیں یا نہیں، لیکن اکثر instanceof ViewGroup چیک کرنا آسان ہوتا ہے۔
View کلاس کا draw(Canvas) طریقہ تین مراحل پر مشتمل ڈرائنگ پائپ لائن ترتیب دیتا ہے۔ پہلا مرحلہ onDraw(canvas) کال کرنا ہے، جہاں View اپنا مواد ڈرائنگ کرتا ہے۔ دوسرا مرحلہ dispatchDraw(canvas) کال کرنا ہے، جو چائلڈ Views کی ڈرائنگ شروع کرتا ہے۔ تیسرا مرحلہ onDrawForeground(canvas) ہے، جو پیش منظر کی تہہ، اسکرول بار اور ripple اثر کے لیے ذمہ دار ہے۔ یہ ترتیب گرافیکل تہوں کے صحیح اوورلے ترتیب کو یقینی بناتی ہے۔
onDraw ہمیشہ dispatchDraw سے پہلے عمل میں آتا ہے۔ اس کا مطلب ہے کہ پیرنٹ View کا مواد چائلڈ Views کے نیچے ظاہر ہوتا ہے۔ اگر آپ کو چائلڈز کے اوپر کچھ ڈرائنگ کرنے کی ضرورت ہے، تو یہ onDrawForeground میں یا اوور رائڈ شدہ dispatchDraw میں super.dispatchDraw(canvas) کال کرکے اور پھر اوپر ڈرائنگ کرکے کیا جاتا ہے۔ پس منظر onDraw سے پہلے بھی draw() طریقہ کے اندر drawBackground(canvas) میں ڈرائنگ کیا جاتا ہے۔
ہارڈویئر ایکسلریشن کے ساتھ، ڈرائنگ پائپ لائن GPU کے ذریعے کام کرتی ہے۔ View کو DisplayList میں ڈرائنگ کیا جاتا ہے — ڈرائنگ کمانڈز کی ایک فہرست جو کیش کی جاتی ہے اور دوبارہ استعمال ہوتی ہے۔ ہارڈویئر ایکسلریٹڈ موڈ میں dispatchDraw چائلڈ Views کے DisplayLists کو منظر کے مجموعی DisplayList میں شامل کرتا ہے۔ dispatchDraw میں ترمیم کرنے سے DisplayList باطل ہو سکتا ہے اور کیشے کی دوبارہ تعمیر ہو سکتی ہے، جو کارکردگی کو متاثر کرتی ہے۔
| طریقہ | کال کی ترتیب | مقصد |
|---|---|---|
| drawBackground | 1 | پس منظر کی ڈرائنگ (background drawable) |
| onDraw | 2 | View کے اپنے مواد کی ڈرائنگ |
| dispatchDraw | 3 | تمام چائلڈ Views کی ڈرائنگ (صرف ViewGroup) |
| onDrawForeground | 4 | پیش منظر، اسکرول بار اور ripple اثر کی ڈرائنگ |
onDraw View کے اپنے مواد — شکلیں، متن، تصاویر جو اس مخصوص عنصر سے تعلق رکھتی ہیں — کی ڈرائنگ کے لیے ذمہ دار ہے۔ dispatchDraw چائلڈ Views — ViewGroup کے اندر موجود تمام عناصر — کی ڈرائنگ کے لیے ذمہ دار ہے۔ اگر ViewGroup dispatchDraw کو اوور رائڈ نہیں کرتا، تو ViewGroup سے نفاذ استعمال ہوتا ہے، جو صرف childCount کو ریکرسیو طور پر عبور کرتا ہے اور ہر چائلڈ کے لیے draw کال کرتا ہے۔
ان ViewGroups کے لیے جو اپنا مواد ڈرائنگ نہیں کرتے (مثلاً FrameLayout, LinearLayout)، setWillNotDraw(true) سیٹ کرکے onDraw کو بہتر بنایا جا سکتا ہے۔ اس صورت میں، onDraw کبھی کال نہیں ہوتا، جو وسائل بچاتا ہے۔ dispatchDraw کام کرتا رہتا ہے اور چائلڈ عناصر کے لیے draw کال کرتا ہے۔ تمام معیاری ViewGroups (LinearLayout, RelativeLayout, ConstraintLayout) setWillNotDraw(true) استعمال کرتے ہیں۔
اگر آپ super.dispatchDraw(canvas) کال کیے بغیر dispatchDraw کو اوور رائڈ کرتے ہیں، تو چائلڈ Views ڈرائنگ نہیں ہوں گے۔ یہ تمام چائلڈز کو عارضی طور پر چھپانے کے لیے مفید ہو سکتا ہے، لیکن زیادہ تر معاملات میں یہ خرابیاں پیدا کرتا ہے۔ تجویز کردہ عمل: اوور رائڈ کردہ طریقہ کے شروع میں super.dispatchDraw(canvas) کال کریں، پھر چائلڈز کے اوپر اپنی گرافکس (مثلاً الفا چینل کے ساتھ اوورلے) شامل کریں۔
آئیے OverlayViewGroup بناتے ہیں — ایک کسٹم ViewGroup جو تمام چائلڈ Views کے اوپر ٹیکسٹ لیبل کے ساتھ ایک نیم شفاف تہہ شامل کرتا ہے۔ dispatchDraw پہلے super کال کرتا ہے (تمام چائلڈز کی ڈرائنگ)، پھر اوورلے مستطیل اور متن ڈرائنگ کرتا ہے۔ Paint کنسٹرکٹر میں بنایا جاتا ہے تاکہ ڈرائنگ لوپ میں مختص کرنے سے بچا جا سکے۔
class OverlayViewGroup(context: Context)
: ViewGroup(context) {
private val overlayPaint = Paint().apply {
color = Color.parseColor("#66000000")
style = Paint.Style.FILL
}
private val textPaint = Paint().apply {
color = Color.WHITE
textSize = 36f
isAntiAlias = true
textAlign = Paint.Align.CENTER
}
init {
setWillNotDraw(false)
}
override fun dispatchDraw(canvas: Canvas) {
super.dispatchDraw(canvas)
canvas.drawRect(0f, 0f,
width.toFloat(),
height.toFloat(), overlayPaint)
canvas.drawText("پیش منظر موڈ",
width / 2f,
height / 2f, textPaint)
}
override fun onLayout(changed: Boolean,
l: Int, t: Int,
r: Int, b: Int) {
var top = t
for (i in 0 until childCount) {
val child = getChildAt(i)
val cw = child.measuredWidth
val ch = child.measuredHeight
child.layout(l, top, l + cw, top + ch)
top += ch
}
}
override fun onMeasure(widthMeasureSpec: Int,
heightMeasureSpec: Int) {
measureChildren(widthMeasureSpec, heightMeasureSpec)
val maxWidth = resolveSize(
getChildAt(0).measuredWidth,
widthMeasureSpec)
var totalHeight = 0
for (i in 0 until childCount) {
totalHeight += getChildAt(i).measuredHeight
}
setMeasuredDimension(maxWidth,
resolveSize(totalHeight, heightMeasureSpec))
}
}
مندرجہ ذیل مثال چائلڈ عناصر کی ڈرائنگ کی ترتیب تبدیل کرنے کو ظاہر کرتی ہے۔ CircularRevealLayout dispatchDraw کو اوور رائڈ کرتا ہے اور چائلڈز کو الٹی ترتیب میں ڈرائنگ کرتا ہے، ایک الٹا Z-order اثر پیدا کرتا ہے۔ حرکت پذیری کے لیے، متحرک offset قدر کی بنیاد پر ڈرائنگ انڈیکس کا ایک چکری نقل مکانی شامل کیا جاتا ہے۔
class ReverseOrderLayout(context: Context)
: ViewGroup(context) {
private var reverse = false
override fun dispatchDraw(canvas: Canvas) {
if (!reverse) {
super.dispatchDraw(canvas)
return
}
for (i in childCount - 1 downTo 0) {
val child = getChildAt(i)
if (child.visibility == GONE) continue
drawChild(canvas, child, getDrawingTime())
}
}
fun toggleReverse() {
reverse = !reverse
invalidate()
}
override fun onLayout(changed: Boolean,
l: Int, t: Int,
r: Int, b: Int) {
var left = l
for (i in 0 until childCount) {
val child = getChildAt(i)
val cw = child.measuredWidth
child.layout(left, t,
left + cw, t + child.measuredHeight)
left += cw
}
}
override fun onMeasure(widthMeasureSpec: Int,
heightMeasureSpec: Int) {
measureChildren(widthMeasureSpec, heightMeasureSpec)
var totalWidth = 0
for (i in 0 until childCount) {
totalWidth += getChildAt(i).measuredWidth
}
setMeasuredDimension(
resolveSize(totalWidth, widthMeasureSpec),
resolveSize(getChildAt(0).measuredHeight,
heightMeasureSpec))
}
}
dispatchDraw ان منظرناموں میں استعمال ہوتا ہے جہاں آپ کو ViewGroup کے اپنے مواد کو متاثر کیے بغیر چائلڈ Views کی ڈرائنگ کے عمل کو متاثر کرنے کی ضرورت ہوتی ہے۔ اہم منظرنامے: تمام چائلڈز کے اوپر ایک مشترکہ اثر (اوورلے، شیڈو، گریڈینٹ) لگانا؛ گہرائی کے اثرات پیدا کرنے کے لیے Z-order تبدیل کرنا؛ Canvas تبدیلیوں کے ذریعے چائلڈ عناصر کے ظاہر یا غائب ہونے کو متحرک کرنا۔
اگر آپ کو چائلڈ عناصر کے نیچے گرافکس لگانے کی ضرورت ہے (پس منظر کا اثر)، onDraw استعمال کریں — dispatchDraw اس کے بعد کال ہوتا ہے۔ اگر گرافکس چائلڈز کے اوپر ہونی چاہیے — پہلے super کال کرکے، پھر Canvas.draw استعمال کرکے dispatchDraw استعمال کریں۔ اگر آپ کو عالمی رنگ یا شفافیت کی تبدیلی کی ضرورت ہے، تو dispatchDraw میں چائلڈز کی ڈرائنگ کو لپیٹنے کے لیے canvas.saveLayerAlpha() استعمال کرنا آسان ہے۔
سفارش نہیں کی جاتی dispatchDraw استعمال کرنا: 1) ریئل ٹائم میں پیچیدہ حرکت پذیری ڈرائنگ کرنے کے لیے (invalidate اور onDraw استعمال کریں)؛ 2) ViewGroup کے اسکرین شاٹس بنانے کے لیے (buildDrawingCache() یا View.draw(Canvas) استعمال کریں)؛ 3) چائلڈ Views میں ترمیم کرنے کے لیے (متناسقات، سائز — یہ onLayout کے کام ہیں، dispatchDraw کے نہیں)۔ dispatchDraw صرف بصری اثرات لگانے کے لیے ہے۔
اکثر پوچھے گئے سوالات
نہیں، dispatchDraw ایک protected طریقہ ہے جسے Android سسٹم عوامی draw() طریقہ کے اندر کال کرتا ہے۔ dispatchDraw کا براہ راست کال بے معنی ہے کیونکہ یہ تیاری کے اقدامات (Canvas محفوظ کرنا، پس منظر اور پیش منظر ڈرائنگ کرنا) انجام نہیں دیتا۔ اس کے بجائے، پروگراماتی طور پر کسی بھی Canvas پر ڈرائنگ کرنے کے لیے View.draw(Canvas) استعمال کریں۔
اگر آپ اپنی ڈرائنگ کے عمل کے بعد super.dispatchDraw(canvas) کال کرتے ہیں، تو چائلڈ Views کسٹم گرافکس کے اوپر ڈرائنگ ہوں گے۔ یہ تہوں کی ترتیب کو تبدیل کرتا ہے: پہلے کسٹم تہہ ڈرائنگ ہوتی ہے، پھر چائلڈز۔ اگر آپ کو الٹی صورت حال کی ضرورت ہے (چائلڈز کے اوپر گرافکس)، پہلے super.dispatchDraw کال کریں، پھر اپنے عمل۔
dispatchDraw ہر چائلڈ View کے لیے draw() کال کرتا ہے، اور کل وقت چائلڈز کی تعداد کے متناسب ہوتا ہے۔ ہارڈویئر ایکسلریشن کے ساتھ، dispatchDraw میں Canvas آپریشنز شامل کرنے سے DisplayList باطل ہو سکتا ہے اور کیشے کی دوبارہ تعمیر ہو سکتی ہے۔ 5–10 چائلڈز کے لیے اثر کم سے کم ہے، 50+ چائلڈز کے لیے پیچیدہ اوورلیز کو کیش کرنے کی سفارش کی جاتی ہے۔
ایک View (ViewGroup نہیں) میں کوئی چائلڈ عناصر نہیں ہوتے، اس لیے dispatchDraw کوئی مفید کام انجام نہیں دیتا۔ تاہم، یہ طریقہ پولیمورفزم کے لیے بنیادی View کلاس میں موجود ہے: draw() میں کوڈ کسی بھی View کے لیے dispatchDraw کال کرتا ہے، لیکن View کے نفاذ میں چائلڈ ڈرائنگ کی منطق موجود نہیں ہے۔ صرف ViewGroup dispatchDraw کو اوور رائڈ کرتا ہے۔
ہاں، dispatchDraw ایک Canvas قبول کرتا ہے، اور super.dispatchDraw کال کرنے سے پہلے اسے تبدیل کیا جا سکتا ہے (translate, rotate, scale)۔ یہ چائلڈز کے پورے سیٹ کو ایک اکائی کے طور پر متحرک کرنے کے لیے استعمال ہوتا ہے۔ super.dispatchDraw مکمل ہونے کے بعد، Canvas کو اس کی اصل حالت میں بحال کرنے کی سفارش کی جاتی ہے۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں