onMeasure() android.view.View کلاس کا ایک protected طریقہ ہے جسے Android سسٹم View کے سائز کا تعین کرنے کے لیے کال کرتا ہے۔ سسٹم اس طریقہ میں دو MeasureSpec آبجیکٹ بھیجتا ہے، جن میں سے ہر ایک میں پیمائش کا موڈ (EXACTLY، AT_MOST یا UNSPECIFIED) اور پیرنٹ کنٹینر کے تجویز کردہ سائز شامل ہوتا ہے۔ Android Developers Documentation (2026) کے مطابق، درست MeasureSpec ہینڈلنگ کے ساتھ onMeasure کو اوور رائڈ کرنا ان تمام کسٹم View اور ViewGroup کے لیے لازمی ہے جنہیں سائز پر عین مطابق کنٹرول کی ضرورت ہوتی ہے۔
اہم نکات
onMeasure(int widthMeasureSpec, int heightMeasureSpec) View کلاس کا ایک طریقہ ہے جسے Android سسٹم کسی ویو کی چوڑائی اور اونچائی کا تعین کرنے کے لیے کال کرتا ہے۔ ڈیولپر اس طریقہ کو اوور رائڈ کرکے یہ بتاتا ہے کہ MeasureSpec میں دی گئی رکاوٹوں کی بنیاد پر View کا سائز کیا ہونا چاہیے۔ درست onMeasure اوور رائڈنگ کے بغیر، کسٹم View غلط طریقے سے ظاہر ہو سکتا ہے یا بالکل نظر نہیں آ سکتا۔
سسٹم View کی زندگی کے چکر کے measure مرحلے کے دوران onMeasure کو کال کرتا ہے، جو layout (onLayout) اور draw (onDraw) مراحل سے پہلے آتا ہے۔ اگر کوئی View onMeasure کو اوور رائڈ نہیں کرتا، تو سپر کلاس کا نفاذ استعمال ہوتا ہے، جو background drawable یا layout_params کی بنیاد پر ڈیفالٹ سائز مقرر کرتا ہے۔ super.onMeasure(widthMeasureSpec, heightMeasureSpec) کو کال کرنا صرف View کے معیاری ذیلی طبقات جیسے TextView یا ImageView کے لیے کام کرتا ہے۔
onMeasure کے لیے ایک اہم ضرورت یہ ہے کہ setMeasuredDimension(int, int) کی کال طریقہ کے آخر میں موجود ہو۔ اگر یہ کال غائب ہے، تو سسٹم IllegalStateException پھینکتا ہے جس میں بتایا جاتا ہے کہ View نے ناپے گئے طول و عرض مقرر نہیں کیے۔ پیمائش کا مرحلہ مکمل ہونے کے بعد حتمی طول و عرض getMeasuredWidth() اور getMeasuredHeight() گیٹرز کے ذریعے دستیاب ہوتے ہیں۔
MeasureSpec ایک 32 بٹ عدد ہے جہاں اوپر کے 2 بٹ پیمائش کے موڈ کو انکوڈ کرتے ہیں اور نیچے کے 30 بٹ سائز کو انکوڈ کرتے ہیں۔ موڈ اس بات کا تعین کرتا ہے کہ View اپنا سائز منتخب کرنے میں کتنا آزاد ہے۔ Android تین موڈ فراہم کرتا ہے: EXACTLY، AT_MOST اور UNSPECIFIED۔ ہر موڈ onMeasure میں مختلف پروسیسنگ منطق کا حکم دیتا ہے۔
| MeasureSpec موڈ | قدر | سلوک |
|---|---|---|
| EXACTLY | پیرنٹ نے عین مطابق سائز بتایا | View کو دیے گئے سائز میں بالکل فٹ ہونا چاہیے اگر وہ حدوں سے باہر نہیں جانا چاہتا |
| AT_MOST | پیرنٹ نے زیادہ سے زیادہ سائز مقرر کیا | View 0 سے دیے گئے زیادہ سے زیادہ تک کوئی بھی سائز منتخب کر سکتا ہے |
| UNSPECIFIED | پیرنٹ کوئی پابندی نہیں لگاتا | View بغیر کسی بالائی حد کے کوئی بھی مطلوبہ سائز منتخب کر سکتا ہے |
MeasureSpec سے موڈ اور سائز نکالنے کے لیے MeasureSpec کلاس کے جامد طریقے استعمال کیے جاتے ہیں: MeasureSpec.getMode(int) تین موڈز میں سے ایک واپس کرتا ہے (EXACTLY, AT_MOST, UNSPECIFIED)، اور MeasureSpec.getSize(int) پکسلز میں عددی سائز واپس کرتا ہے۔ کسٹم MeasureSpec بنانے کے لیے MeasureSpec.makeMeasureSpec(int size, int mode) استعمال کیا جاتا ہے۔ یہ تینوں طریقے onMeasure میں سائز کے ساتھ کام کرنے کے تمام منظرناموں کو کور کرتے ہیں۔
معیاری نمونہ MeasureSpec ہینڈلنگ کے لیے: اگر موڈ EXACTLY ہے — دیے گئے سائز کو حتمی کے طور پر استعمال کریں؛ اگر AT_MOST ہے — مطلوبہ سائز (View کا مواد) اور دیے گئے زیادہ سے زیادہ کے درمیان کم از کم منتخب کریں؛ اگر UNSPECIFIED ہے — بغیر کسی پابندی کے View کا مطلوبہ سائز استعمال کریں۔ یہ نمونہ پیرنٹ کی کسی بھی رکاوٹ کے تحت درست سلوک کو یقینی بناتا ہے۔
override fun onMeasure(widthMeasureSpec: Int,
heightMeasureSpec: Int) {
val desiredWidth = 200
val desiredHeight = 100
val widthMode = MeasureSpec.getMode(widthMeasureSpec)
val widthSize = MeasureSpec.getSize(widthMeasureSpec)
val heightMode = MeasureSpec.getMode(heightMeasureSpec)
val heightSize = MeasureSpec.getSize(heightMeasureSpec)
val width = when (widthMode) {
MeasureSpec.EXACTLY -> widthSize
MeasureSpec.AT_MOST -> minOf(desiredWidth, widthSize)
else -> desiredWidth
}
val height = when (heightMode) {
MeasureSpec.EXACTLY -> heightSize
MeasureSpec.AT_MOST -> minOf(desiredHeight, heightSize)
else -> desiredHeight
}
setMeasuredDimension(width, height)
}
معیاری منطق کو آسان بنانے کے لیے، Android resolveSizeAndState طریقہ فراہم کرتا ہے، جو مطلوبہ سائز اور MeasureSpec لے کر درست موڈ کے ساتھ حتمی سائز واپس کرتا ہے۔ یہ طریقہ اوپر بیان کردہ نمونے کو کوڈ کی ایک لائن میں نافذ کرتا ہے۔ resolveSize(int size, int measureSpec) فنکشن بھی دستیاب ہے، جو سٹیٹ بٹس کے بغیر صاف سائز واپس کرتا ہے۔
Android دو پاس پیمائش الگورتھم استعمال کرتا ہے جو اس بات کو یقینی بناتا ہے کہ درجہ بندی میں ہر View کو پیرنٹ کی رکاوٹوں اور بچوں کی ترجیحات کو مدنظر رکھتے ہوئے درست طول و عرض ملے۔ پہلے پاس میں، پیرنٹ رکاوٹوں کے ساتھ MeasureSpec چائلڈ View کو بھیجتا ہے، اور چائلڈ View اپنے مطلوبہ سائز کا حساب لگاتے ہیں۔ دوسرے پاس میں، پیرنٹ سائز کے بارے میں حتمی فیصلہ کرتا ہے۔
ViewGroup کے لیے، پیمائش کا عمل زیادہ پیچیدہ ہے: پیرنٹ کو پہلے اپنے تمام بچوں کو ناپنا چاہیے، پھر ان کے سائز کی بنیاد پر اپنا سائز متعین کرنا چاہیے۔ measureChildren(int widthMeasureSpec, int heightMeasureSpec) کو کال کرنا تمام چائلڈ View کو iterate کرتا ہے اور ہر ایک کے لیے measure(child, childWidthSpec, childHeightSpec) کو کال کرتا ہے۔ تمام بچوں کو ناپنے کے بعد، ViewGroup اپنے طول و عرض کے ساتھ setMeasuredDimension کو کال کرتا ہے۔
ایک اہم باریکی: measure طریقہ (عوامی، حتمی) کو اوور رائڈ نہیں کیا جا سکتا — اس کے بجائے onMeasure کو اوور رائڈ کیا جاتا ہے۔ یہ اس بات کو یقینی بناتا ہے کہ سسٹم onMeasure سے پہلے اور بعد میں دیکھ بھال کے کام انجام دے سکتا ہے، جیسے سائز میں تبدیلی کی جانچ کرنا اور بعد میں ڈرائنگ کے لیے گندے علاقے کا حساب لگانا۔ اگر View کے مقررہ طول و عرض ہیں، تو onMeasure کو اوور رائڈ کرنا ضروری نہیں ہو سکتا۔
MeasureSpec میں نہ صرف سائز اور موڈ بلکہ سٹیٹ بٹس بھی شامل ہیں، جو MeasureSpec.getMode() کے ذریعے قابل رسائی ہیں۔ setMeasuredDimension کو کال کرنے کے بعد، حالت View کے ناپے گئے طول و عرض کا حصہ بن جاتی ہے اور getMeasuredState() کے ذریعے جانچی جا سکتی ہے۔ یہ ScrollView اور دیگر اسکرول ایبل کنٹینرز میں بچوں تک رکاوٹوں کو صحیح طریقے سے پہنچانے کے لیے استعمال ہوتا ہے۔
آئیے مربع ڈسپلے کے لیے onMeasure کے ساتھ ایک کسٹم View بنانے کی عملی مثال دیکھتے ہیں۔ SquareView کلاس View کو بڑھاتی ہے اور اس بات کو یقینی بناتی ہے کہ چوڑائی اور اونچائی ہمیشہ برابر ہوں، بھیجے گئے MeasureSpec سے قطع نظر۔ onMeasure میں، کم از کم پہلو کا تعین کیا جاتا ہے اور مربع سائز مقرر کیا جاتا ہے۔
class SquareView(context: Context)
: View(context) {
override fun onMeasure(widthMeasureSpec: Int,
heightMeasureSpec: Int) {
val widthSize =
MeasureSpec.getSize(widthMeasureSpec)
val heightSize =
MeasureSpec.getSize(heightMeasureSpec)
val size = minOf(widthSize, heightSize)
setMeasuredDimension(size, size)
}
}
ViewGroup کو زیادہ پیچیدہ onMeasure منطق کی ضرورت ہوتی ہے کیونکہ پہلے بچوں کو ناپنا ضروری ہے، پھر ViewGroup کا اپنا سائز متعین کیا جاتا ہے۔ CascadeLayout مثال بچوں کو ایک آفسیٹ کے ساتھ جھرن میں تقسیم کرتی ہے۔ measureChildWithMargins کے ذریعے تمام بچوں کو ناپنے کے بعد، کل چوڑائی اور اونچائی کا حساب لگایا جاتا ہے۔
class CascadeLayout(context: Context)
: ViewGroup(context) {
private val cascadeOffset = 40
override fun onMeasure(widthMeasureSpec: Int,
heightMeasureSpec: Int) {
var maxWidth = 0
var totalHeight = 0
for (i in 0 until childCount) {
val child = getChildAt(i)
measureChildWithMargins(child,
widthMeasureSpec,
cascadeOffset * i,
heightMeasureSpec, 0)
maxWidth = maxOf(maxWidth,
child.measuredWidth +
cascadeOffset * i)
totalHeight += child.measuredHeight
}
setMeasuredDimension(
resolveSize(maxWidth, widthMeasureSpec),
resolveSize(totalHeight, heightMeasureSpec))
}
override fun generateLayoutParams(attrs: AttributeSet?)
: LayoutParams = MarginLayoutParams(context, attrs)
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 left = l + cascadeOffset * i
child.layout(left, top,
left + child.measuredWidth,
top + child.measuredHeight)
top += child.measuredHeight
}
}
}
setMeasuredDimension کال چھوڑنا سب سے عام غلطی ہے۔ اگر ڈیولپر onMeasure کو اوور رائڈ کرتا ہے لیکن setMeasuredDimension کو کال نہیں کرتا، تو ایپلیکیشن IllegalStateException کے ساتھ کریش ہو جاتی ہے۔ یہ خاص طور پر اس وقت ہوتا ہے جب طریقہ میں مشروط شاخیں ہوں اور ایک شاخ میں کال غائب ہو۔ onMeasure میں کوڈ کی ہر شاخ setMeasuredDimension کال کے ساتھ ختم ہونی چاہیے۔
AT_MOST موڈ کو نظر انداز کرنا دوسری سب سے عام غلطی ہے۔ اگر AT_MOST موڈ میں کوئی View مواد کی بنیاد پر حساب کرنے کے بجائے ہمیشہ بھیجا گیا سائز استعمال کرتا ہے، تو پیرنٹ کنٹینر جگہ کو صحیح طریقے سے تقسیم نہیں کر سکتا۔ مثال کے طور پر، AT_MOST میں TextView کو متن کی چوڑائی کا حساب لگانا چاہیے اور مطلوبہ اور بھیجی گئی چوڑائی میں سے کم از کم استعمال کرنی چاہیے۔ AT_MOST کو نظر انداز کرنے سے View چھوٹے مواد کے باوجود تمام دستیاب جگہ گھیر لیتا ہے۔
onMeasure کے اندر آبجیکٹ بنانا ایک کلاسک کارکردگی کی غلطی ہے۔ چونکہ onMeasure متعدد بار کال کیا جا سکتا ہے (ہر layout درخواست پر)، اس طریقہ کے اندر آبجیکٹ (Paint, Rect, String) بنانا میموری کو خراب کرتا ہے اور کوڑا اکٹھا کرنے کو متحرک کرتا ہے۔ تمام آبجیکٹ View کنسٹرکٹر میں ایک بار بنائے جائیں، اور onMeasure میں صرف سائز کے حساب کی منطق چلنی چاہیے۔ یہی اصول onDraw اور onLayout پر بھی لاگو ہوتا ہے۔
measureChildWithMargins ViewGroup کا ایک محفوظ طریقہ ہے جو ایک واحد چائلڈ View کو اس کے MarginLayoutParams کو مدنظر رکھتے ہوئے ناپتا ہے۔ طریقہ پیرنٹ کا MeasureSpec اور جمع شدہ چوڑائی اور اونچائی کے آفسیٹ قبول کرتا ہے۔ یہ پیرنٹ کے padding اور چائلڈ کے margin کو گھٹا کر چائلڈ View کے لیے MeasureSpec کو خود بخود ایڈجسٹ کرتا ہے، پھر ایڈجسٹ شدہ MeasureSpec کو child.measure() میں بھیجتا ہے۔
اعلی درجے کی پیمائش منطق کے لیے، ViewGroup measureChild(View child, int parentWidthSpec, int parentHeightSpec) کو اوور رائڈ کر سکتا ہے یا ہر بچے کے لیے براہ راست MeasureSpec کے ساتھ کام کر سکتا ہے۔ مثال کے طور پر، LinearLayout onMeasure میں تمام چائلڈ View کو iterate کرتا ہے، ہر ایک کو اس کے layout_weight کو مدنظر رکھتے ہوئے ناپتا ہے اور باقی جگہ کو متناسب طور پر تقسیم کرتا ہے۔ یہ طریقہ صوابدیدی layout الگورتھم کو نافذ کرنے کی اجازت دیتا ہے۔
پیمائش کے نتائج کو پیمائش کیش میکانزم کے ذریعے کیش کرنا مخصوص ViewGroup میں setMeasureWithLargestChildEnabled پرچم کے ذریعے دستیاب ہے۔ تاہم، زیادہ تر معاملات میں onMeasure کسی بھی layout تبدیلی پر دوبارہ کال کیا جاتا ہے اور کیشنگ لاگو نہیں ہوتی۔ کسٹم ViewGroup میں، کیشنگ پر انحصار کرنے کے بجائے onMeasure میں حسابات کو کم سے کم کرنے کی سفارش کی جاتی ہے۔
اکثر پوچھے گئے سوالات
ہاں، اگر کسٹم View براہ راست View کلاس سے وراثت پاتا ہے۔ اگر یہ TextView، ImageView یا Button سے ان کے معیاری سائز کے ساتھ وراثت پاتا ہے، تو onMeasure کو تبدیل کیے بغیر چھوڑا جا سکتا ہے۔ ViewGroup کے لیے، onMeasure کو اوور رائڈ کرنا ہمیشہ ضروری ہے — ورنہ بچے صحیح طریقے سے نہیں ناپے جائیں گے۔
Android سسٹم IllegalStateException پھینکتا ہے جس میں پیغام “The View did not call setMeasuredDimension” ہوتا ہے۔ یہ استثنا measure() طریقہ میں onMeasure مکمل ہونے کے بعد ہوتا ہے، اگر حتمی طول و عرض صفر رہ گئے ہوں۔ try-catch کے ذریعے نہ سنبھالے جانے پر استثنا ایپلیکیشن کو کریش کر دیتا ہے۔
getMeasuredWidth() onMeasure (پیمائش کے مرحلے) میں مقرر کردہ سائز واپس کرتا ہے۔ getWidth() اصل سائز واپس کرتا ہے جو View کو onLayout میں تمام مقام کی ایڈجسٹمنٹ کے بعد ملا۔ زیادہ تر View کے لیے یہ قدریں ملتی ہیں، لیکن کسٹم ViewGroup میں یہ مختلف ہو سکتی ہیں۔
نہیں، onMeasure صرف سائز کے حساب کے لیے ہے۔ اس طریقہ میں حالت تبدیل کرنا، اینیمیشن شروع کرنا، نیٹ ورکنگ کرنا یا ڈیٹا اپ ڈیٹ کرنا Android فن تعمیر کی خلاف ورزی کرتا ہے اور بار بار measure کالز کا سبب بن سکتا ہے، کیونکہ حالت میں تبدیلیاں requestLayout کو متحرک کر سکتی ہیں۔
ConstraintLayout متعین رکاوٹوں کی بنیاد پر بچوں کی پیمائش کو آزادانہ طور پر منظم کرتا ہے۔ اگر ConstraintLayout کے اندر کوئی کسٹم View onMeasure کو اوور رائڈ کرتا ہے، تو اسے ConstraintLayout سے بھیجے گئے MeasureSpec کو صحیح طریقے سے سنبھالنا چاہیے، ورنہ رکاوٹیں کام نہیں کر سکتیں۔ ConstraintLayout حساب کے لیے اپنے WidgetContainer کے ساتھ دو پاس الگورتھم استعمال کرتا ہے۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں