LazyRow — هي دالة قابلة للتركيب في Jetpack Compose لإنشاء قوائم أفقية مع تحميل بطيء للعناصر. على عكس Row، يقوم LazyRow بإنشاء العناصر المرئية فقط وإعادة استخدامها أثناء التمرير الأفقي. وفقًا لـ Google Android Documentation, 2025، يعتبر LazyRow النظير الأفقي لـ LazyColumn وهو فعال لعربات العرض والمعارض والقوائم الأفقية في تطبيقات الجوال.
الخلاصة
LazyRow — هي دالة قابلة للتركيب تنفذ قائمة أفقية قابلة للتمرير مع تحميل بطيء للعناصر. على عكس Row الذي يعرض جميع العناصر الفرعية في وقت واحد، يقوم LazyRow بإنشاء العناصر المرئية فقط في منطقة العرض.
يعمل LazyRow بنفس مبدأ LazyColumn، ولكنه يرتب العناصر أفقيًا. عند التمرير لليسار أو لليمين، يتم إعادة استخدام العناصر التي خرجت من منطقة العرض لعرض عناصر جديدة. هذا مهم جدًا للمعارض التي تحتوي على العديد من الصور أو قوائم الفئات الطويلة.
وفقًا لـ Android Developers Blog, 2024، يستخدم LazyRow نفس بنية LazyList التي يستخدمها LazyColumn، بما في ذلك LazyListState وآلية إعادة الاستخدام عبر Pool ودعم أنواع العناصر المختلفة. يتم تحقيق أقصى كفاءة باستخدام ارتفاع ثابت للعناصر.
LazyRow يقبل المعلمات modifier و state و contentPadding و reverseLayout و horizontalArrangement و verticalAlignment. يتم تعريف المحتوى عبر دوال DSL items و item، على غرار LazyColumn.
@Composable
fun SimpleLazyRow() {
val items = (1..50).toList()
LazyRow(
modifier = Modifier.fillMaxWidth().height(100.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
contentPadding = PaddingValues(start = 16.dp, end = 16.dp)
) {
items(items) { item ->
Box(
modifier = Modifier.size(80.dp).background(Color.Gray)
) {
Text(text = "$item", modifier = Modifier.align(Alignment.Center))
}
}
}
}
horizontalArrangement يدير توزيع العناصر على طول المحور الأفقي داخل LazyRow. تتوفر نفس قيم Arrangement الموجودة في Row: Start و Center و End و SpaceBetween و SpaceEvenly و SpaceAround و spacedBy بمسافة مخصصة.
contentPadding يضيف هوامش على حواف حاوية LazyRow. على عكس Modifier.padding، يتم أخذ contentPadding في الاعتبار أثناء التمرير: سيكون للعنصر الأول هامش من الحافة اليسرى، وللعنصر الأخير من الحافة اليمنى. وفقًا لـ Material Design Guidelines, 2025، فإن contentPadding إلزامي لعربات العرض والمعارض بحيث لا يلتصق العنصر الأول والأخير بحافة الشاشة.
verticalAlignment يحاذي العناصر عموديًا داخل LazyRow. افتراضيًا يتم استخدام Alignment.Top. لتوسيط عناصر ذات ارتفاعات مختلفة، استخدم Alignment.CenterVertically، وهو مفيد لعربات العرض التي تحتوي على صور بنسب مختلفة.
| المعلمة | الوصف | القيمة الافتراضية |
|---|---|---|
| horizontalArrangement | توزيع العناصر أفقيًا | Arrangement.Start |
| contentPadding | الهوامش على حواف الحاوية | PaddingValues(0.dp) |
| verticalAlignment | المحاذاة العمودية | Alignment.Top |
| reverseLayout | ترتيب عكسي للعناصر | false |
| userScrollEnabled | تمكين تمرير المستخدم | true |
LazyListState لـ LazyRow يعمل بشكل مماثل لـ LazyColumn: يتتبع العنصر الأول المرئي والإزاحة وموضع التمرير العام. يتم إنشاء الحالة عبر rememberLazyListState() وتمريرها إلى معلمة state.
يتم التحكم البرمجي في تمرير LazyRow بنفس الطرق: animateScrollToItem للتمرير السلس و scrollToItem للتمرير الفوري. يتم استدعاء كلاهما داخل كوروتين. هذا مفيد لعربات العرض التي تحتوي على أزرار للتمرير لليسار/لليمين أو للتمرير التلقائي.
وفقًا لـ Android Developers, 2024، يدعم LazyRow أيضًا SnapFlingBehavior — سلوك التمرير السريع الذي يتوقف عند أقرب عنصر بدلاً من التوقف بين العناصر. هذا يخلق تأثير التقاط مألوف لعربات العرض والمعارض.
@Composable
fun CarouselWithSnap() {
val listState = rememberLazyListState()
val scope = rememberCoroutineScope()
val items = listOf("A", "B", "C", "D", "E")
Column {
LazyRow(
state = listState,
flingBehavior = SnapFlingBehavior(listState),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
items(items) { item ->
Card(modifier = Modifier.width(150.dp)) {
Text(text = item, modifier = Modifier.padding(16.dp))
}
}
}
Row(modifier = Modifier.fillMaxWidth()) {
Button(onClick = {
scope.launch {
listState.animateScrollToItem(0)
}
}) { Text("للبدء") }
}
}
}
المثال الأول — LazyRow لمعرض صور مع معاينات. كل عنصر هو Box يحتوي على صورة وتسمية توضيحية. يتعامل LazyRow بكفاءة مع عشرات ومئات الصور، محملاً فقط المرئية منها.
@Composable
fun ImageGallery(images: List<String>) {
LazyRow(
contentPadding = PaddingValues(start = 16.dp, end = 16.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
items(images, key = { it }) { url ->
AsyncImage(
model = url,
contentDescription = "Image",
modifier = Modifier.size(120.dp)
)
}
}
}
المثال الثاني — LazyRow لقائمة فئات مع أيقونات. يتم عرض الفئات كرقائق ويمكن للمستخدم تمريرها أفقيًا. يقوم LazyRow مع spacedBy و contentPadding بإنشاء مسافات بين الفئات وعلى الحواف.
@Composable
fun CategoryChips(categories: List<String>) {
LazyRow(
contentPadding = PaddingValues(horizontal = 16.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
items(categories, key = { it }) { category ->
AssistChip(
onClick = {},
label = { Text(category) }
)
}
}
}
الاختيار بين LazyRow و Row يعتمد على عدد العناصر. Row مناسب لـ 5–10 عناصر تكون مرئية دائمًا على الشاشة. LazyRow ضروري عندما يكون هناك العديد من العناصر أو عددها ديناميكي.
Row يعرض جميع العناصر مرة واحدة، مما يسبب تأخيرات مع عدد كبير من العناصر. LazyRow يعرض فقط المرئية منها، مما يجعله مفضلاً للقوائم القابلة للتمرير. وفقًا لـ Android Developers Blog, 2024، تبلغ العتبة حوالي 10 عناصر: إذا كان هناك المزيد من العناصر، استخدم LazyRow.
LazyRow يدعم أيضًا الرسوم المتحركة و SnapFlingBehavior والتجميع عبر الفواصل، مما يجعله أكثر مرونة للواجهات المعقدة. Row أبسط ولا يتطلب LazyListState، ولكنه غير محسن للقوائم الطويلة.
الأسئلة الشائعة
LazyRow يتمرر أفقيًا ويرتب العناصر من اليسار إلى اليمين، بينما يتمرر LazyColumn عموديًا من الأعلى إلى الأسفل. كلاهما يستخدم نفس مبادئ التحميل البطيء و LazyListState ودوال DSL items.
مرر SnapFlingBehavior(listState) إلى معلمة flingBehavior في LazyRow. SnapFlingBehavior يجبر LazyRow على التوقف عند أقرب عنصر بدلاً من التوقف بين العناصر، مما يخلق تأثير التقاط لعربات العرض.
تتبع آخر عنصر مرئي عبر LazyListState.layoutInfo وقم بتحميل بيانات جديدة عندما يقترب العنصر الأخير من نهاية القائمة. للتمرير الدائري، استخدم تنفيذًا مخصصًا مع تكرار العناصر.
نعم، يمكن دمج LazyRow داخل LazyColumn. هذا نمط قياسي لإنشاء صفحات معقدة بعربات عرض أفقية داخل قائمة عمودية. يجب أن يكون لكل LazyRow ارتفاع ثابت ليعمل بشكل صحيح.
استخدم LazyListState.layoutInfo.visibleItemsInfo وقارن فهرس آخر عنصر مرئي مع العدد الإجمالي ناقص واحد. عندما تتطابق هذه القيم، يكون LazyRow في نهاية القائمة.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.