Column: الترتيب الرأسي وتكوين الحاوية في Compose

المؤلف: IT Sectr نُشر: 2026-06-28 وقت القراءة: 8 دق

Column هو مكون Composable مدمج في Jetpack Compose من حزمة compose.foundation.layout الذي يرتب العناصر الفرعية عمودياً، واحداً تحت الآخر. Column هو المكافئ لـ LinearLayout مع اتجاه عمودي من نظام View القديم، ولكن على عكسه، يستخدم وصفاً تصريحياً ويتفاعل تلقائياً مع تغييرات الحالة. وفقاً لـ Google Android Developers, 2026، Column هو أحد الحاويات الأساسية الثلاث إلى جانب Row و Box.

النقاط الرئيسية

  • Column يرتب العناصر عمودياً مع إعدادات Arrangement و Alignment
  • Arrangement يحدد توزيع المساحة بين العناصر عمودياً
  • Alignment يحدد المحاذاة الأفقية لكل عنصر داخل Column
  • الوزن (weight) يوزع المساحة الحرة نسبياً بين العناصر
  • IntrinsicSize يسمح لـ Column بضبط حجمه حسب الحد الأدنى/الأقصى لعرض العناصر الفرعية

ما هو Column في Jetpack Compose

Column هي دالة Composable تقبل معلمات اختيارية: modifier و verticalArrangement و horizontalAlignment و content — وهي لامبدا مع ColumnScope. داخل Column، تُرتب دوال Composable الفرعية من الأعلى إلى الأسفل بترتيب الإعلان. ارتفاع Column يساوي مجموع ارتفاعات العناصر الفرعية بالإضافة إلى المساحة المحددة بواسطة Arrangement. العرض يساوي أقصى عرض للعنصر الفرعي مع مراعاة Alignment.

Column هي حاوية غير مرئية: ليس لها خلفية أو حدود افتراضية. إذا كنت بحاجة إلى خلفية، أضف Modifier.background() إلى Column نفسها. على عكس LazyColumn، تعرض Column جميع العناصر الفرعية في وقت واحد ولا تدعم الظاهرية. هذا يعني أن Column مناسبة فقط لمجموعات البيانات الصغيرة — حتى 10-15 عنصراً. للقوائم الطويلة، استخدم LazyColumn.

ColumnScope هو مستقبل لامبدا المحتوى لـ Column. يوفر معدّلات إضافية تعمل فقط داخل Column: weight() و align() و alignByBaseline(). هذه المعدّلات ليس لها معنى خارج Column لأنها تعتمد على خصائص الترتيب الرأسي. على سبيل المثال، Modifier.align(Alignment.CenterHorizontally) يحاذي العنصر الفرعي إلى مركز Column أفقياً.

معلمات Column: Arrangement, Alignment, Modifier

VerticalArrangement يحدد كيفية توزيع المساحة الرأسية بين العناصر. القيم المتاحة: Arrangement.Top (افتراضي)، Bottom، Center، SpaceBetween، SpaceEvenly، SpaceAround. إذا كان ارتفاع Column أكبر من مجموع ارتفاعات العناصر، يوزع Arrangement المساحة الحرة. إذا كانت العناصر تشغل الارتفاع بالكامل، لا يكون لـ Arrangement تأثير.

HorizontalAlignment يحدد المحاذاة الأفقية لكل عنصر فرعي. Alignment.Start (افتراضي لـ LTR)، CenterHorizontally، End. يعمل Alignment على كل عنصر بشكل مستقل: إذا كان أحد العناصر ضيقاً وآخر عريضاً، فسيتم محاذاة الأول، وقد يمتد الثاني خارج حدود Column. يعمل Alignment فقط إذا كان لـ Column عرض ثابت أو fillMaxWidth.

Modifier لـ Column: تقبل Column معدّلاً (Modifier) يتم تطبيقه على الحاوية نفسها. Modifier.fillMaxWidth() و fillMaxHeight() و size() و padding() — جميع المعدّلات القياسية تعمل. ملاحظة خاصة: Modifier.height(IntrinsicSize.Min) يجبر Column على حساب الحد الأدنى للارتفاع بناءً على العناصر الفرعية باستخدام القياس Intrinsic.

kotlin
@Composable
fun ColumnArrangementDemo() {
    Column(
        modifier = Modifier.fillMaxSize().background(Color(0xFFF5F5F5)),
        verticalArrangement = Arrangement.SpaceEvenly,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text("أعلى", modifier = Modifier.background(Color.Cyan))
        Text("وسط", modifier = Modifier.background(Color.Magenta))
        Text("أسفل", modifier = Modifier.background(Color.Yellow))
    }
}

    // IntrinsicSize: Column يضبط الارتفاع حسب المحتوى
@Composable
fun IntrinsicColumn() {
    Column(
        modifier = Modifier
            .height(IntrinsicSize.Min)
            .width(200.dp)
    ) {
        Text("نص قصير")
        Text("نص طويل جداً سيلتف داخل العمود")
    }
}
Arrangementالسلوك
Arrangement.Topالعناصر ملتصقة بالأعلى، المساحة الحرة في الأسفل
Arrangement.Centerالعناصر في المنتصف، المساحة مقسمة بالتساوي أعلى وأسفل
Arrangement.SpaceBetweenالعنصر الأول في الأعلى، الأخير في الأسفل، والباقي بالتساوي
Arrangement.SpaceEvenlyفجوات متساوية بين جميع العناصر والحواف
Arrangement.SpaceAroundفجوات متساوية بين العناصر، نصف فجوة عند الحواف

وزن Column: توزيع المساحة بين العناصر

Modifier.weight() هو معدّل ColumnScope يوزع المساحة الرأسية الحرة بين عناصر Column بشكل نسبي حسب الأوزان المحددة. إذا كان Column يشغل ارتفاع 400dp ومجموع ارتفاعات العناصر الفرعية 100dp، فسيتم تقسيم الـ 300dp المتبقية بين عناصر الوزن. عنصر بوزن (2f) سيحصل على ضعف مساحة عنصر بوزن (1f).

fill — المعامل الثاني للوزن: weight(weight: Float, fill: Boolean = true). إذا كان fill = true (افتراضي)، يتمدد العنصر ليشغل الارتفاع الكامل المتاح. إذا كان fill = false، يشغل العنصر ارتفاعه الجوهري فقط، وتبقى المساحة المتبقية فارغة. هذا مفيد عندما يجب أن يكون العنصر ملتصقاً بجانب واحد لكن الوزن يحدد فقط نسبة توزيع المساحة الفارغة.

قيود الوزن: يعمل الوزن فقط في Column بارتفاع ثابت أو fillMaxHeight(). إذا كان ارتفاع Column محدداً بالعناصر الفرعية (wrap content)، لا معنى للأوزان — فلا توجد مساحة حرة للتوزيع. أيضاً، لا يمكن دمج الوزن مع Modifier.height() على نفس العنصر — يتعارضان ويتم تجاهل الوزن.

kotlin
@Composable
fun WeightedColumn() {
    Column(
        modifier = Modifier.fillMaxHeight().width(300.dp)
    ) {
        // يأخذ 1/6 من الارتفاع (weight 1 من مجموع 1+2+3=6)
        Box(
            modifier = Modifier
                .weight(1f)
                .fillMaxWidth()
                .background(Color.Red)
        )
        // يأخذ 2/6 من الارتفاع
        Box(
            modifier = Modifier
                .weight(2f)
                .fillMaxWidth()
                .background(Color.Green)
        )
        // يأخذ 3/6 من الارتفاع
        Box(
            modifier = Modifier
                .weight(3f)
                .fillMaxWidth()
                .background(Color.Blue)
        )
    }
}

Column مقابل LazyColumn: متى نستخدم أياً منهما

Column يعرض جميع العناصر الفرعية فوراً. إذا كان هناك أكثر من 10-15 عنصراً، يخلق Column حملاً كبيراً على التركيب والقياس. LazyColumn، على النقيض، يعرض فقط العناصر المرئية ويعيد استخدام غير المرئية. للقوائم الطويلة، القوائم بآلاف العناصر، القوائم اللانهائية أو الدردشات — LazyColumn إلزامي.

متى يكون Column أفضل: شاشات النماذج (3-10 حقول)، بطاقات الملف الشخصي، الأعمدة الرأسية مع الأيقونات، القوائم. يدعم Column أيضاً IntrinsicSize، وهو مفيد للارتفاع التكيفي. بالإضافة إلى ذلك، Column أسهل في التصحيح — لا ظاهرية، جميع العناصر مرئية في Layout Inspector. لواجهة مستخدم ثابتة، Column هو الخيار الصحيح.

LazyColumn يوفر: تخزين العناصر مؤقتاً، الهوية المبنية على المفتاح، تحريك الإضافة/الإزالة (animateItemPlacement)، الرؤوس الثابتة (sticky headers). إذا كانت القائمة تحتوي على عناصر من أنواع مختلفة (viewType مختلفة)، استخدم LazyColumn مع sealed class في items. Column لا يدعم sticky headers (يجب محاكاتها عبر Column قابلة للتمرير). كما يدعم LazyColumn LazyVerticalGrid عند استخدام GridCells.

المعيارColumnLazyColumn
عدد العناصرحتى 10-15أي عدد
الأداءيعرض الكل دائماًالمرئية فقط + مخزن مؤقت
التمريرعبر Modifier.verticalScrollمدمج
IntrinsicSizeمدعومغير مدعوم
الرؤوس الثابتةلا (محاكاة)نعم (stickyHeader)
تحريك العناصرغير مدمجanimateItemPlacement

أمثلة عملية لاستخدام Column

دعنا نلقي نظرة على شاشة ملف تعريف المستخدم حيث يُستخدم Column كحاوية رئيسية للصورة الرمزية والاسم والسيرة الذاتية وأزرار الإجراءات. هنا، Column مع IntrinsicSize.Min يتكيف مع المحتوى، ويُستخدم الوزن لتوزيع المساحة بين الأقسام.

kotlin
@Composable
fun UserProfileCard(name: String, bio: String) {
    Card(
        modifier = Modifier.fillMaxWidth().padding(16.dp),
        elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
    ) {
        Column(
            modifier = Modifier.fillMaxWidth().padding(16.dp),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            // الصورة الرمزية
            Icon(
                imageVector = Icons.Default.AccountCircle,
                contentDescription = "Avatar",
                modifier = Modifier.size(64.dp)
            )
            // الاسم
            Text(name, style = MaterialTheme.typography.headlineSmall)
            // السيرة الذاتية
            Text(bio, style = MaterialTheme.typography.bodyMedium,
                modifier = Modifier.padding(top = 4.dp))
            // أزرار الإجراءات
            Row(
                horizontalArrangement = Arrangement.spacedBy(12.dp),
                modifier = Modifier.padding(top = 12.dp)
            ) {
                Button(onClick = { }) { Text("رسالة") }
                OutlinedButton(onClick = { }) { Text("متابعة") }
            }
        }
    }
}

في المثال، يستخدم Column Arrangement.spacedBy(8.dp) لمسافات متساوية بين العناصر. horizontalAlignment = CenterHorizontally يحاذي الصورة الرمزية والاسم والسيرة الذاتية إلى المنتصف. Row داخل Column هي حاوية متداخلة للأزرار في صف واحد. هذا المزيج من Column (ترتيب رأسي) و Row (ترتيب أفقي) هو نمط بناء واجهة مستخدم نموذجي في Compose.

الأسئلة الشائعة

كيف يختلف Column عن LazyColumn من حيث الأداء؟

Column يعرض جميع العناصر الفرعية مرة واحدة، مما يتسبب في انخفاض FPS مع 100+ عنصر. LazyColumn يعرض فقط العناصر المرئية بالإضافة إلى مخزن مؤقت (عادة 3-5 شاشات). للشاشات الثابتة التي تحتوي على 3-10 عناصر، Column أسرع حيث لا يوجد عبء ظاهرية.

كيف أجعل Column قابلة للتمرير؟

أضف Modifier.verticalScroll(rememberScrollState()) إلى Column. هذا يجعل Column قابلة للتمرير لكنه لا يوفر ظاهرية — لا تزال جميع العناصر تُعرض مرة واحدة. للقوائم الطويلة القابلة للتمرير، استخدم LazyColumn.

هل يمكن تداخل Row داخل Column و Column داخل Row؟

نعم، التداخل بين Row/Column ممارسة شائعة. من خلال الجمع بين الحاويتين، يمكن بناء شبكات معقدة. ومع ذلك، تجنب التداخل العميق (4+ مستويات) دون ضرورة — فهو يزيد من عدد قياسات LayoutNode ويبطئ التركيب.

كيف أجعل جميع العناصر في Column بنفس العرض؟

استخدم Modifier.fillMaxWidth() على كل عنصر فرعي. إذا كان Column لديه Modifier.fillMaxWidth()، فجميع العناصر الفرعية التي تستخدم fillMaxWidth() ستمتد للعرض الكامل. بديل: استخدم Modifier.weight(1f) في ColumnScope إذا كان Column داخل حاوية ثابتة.

كيف يعمل spacedBy في Column؟

Arrangement.spacedBy(space) يضيف فجوة ثابتة بين كل عنصرين متجاورين. على عكس SpaceBetween/SpaceAround، لا يمتد spacedBy العناصر — الفجوة ثابتة، والمساحة المتبقية تبقى في نهاية Column. spacedBy لا يضيف فجوة قبل العنصر الأول ولا بعد العنصر الأخير.

الخلاصة

  • Column — حاوية رأسية أساسية في Compose لترتيب العناصر من الأعلى إلى الأسفل
  • Arrangement يتحكم في توزيع المساحة (Top, Center, SpaceBetween, spacedBy)
  • Alignment يحدد المحاذاة الأفقية لكل عنصر فرعي
  • الوزن يوزع المساحة الحرة نسبياً بين العناصر
  • Column مقابل LazyColumn: Column لـ 3-10 عناصر، LazyColumn للقوائم الطويلة
  • IntrinsicSize يسمح لـ Column بضبط الارتفاع حسب الحد الأدنى لقياس العناصر الفرعية
  • توصية: استخدم spacedBy للمسافات بين العناصر بدلاً من padding على كل عنصر

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا