FlowRow
ו-FlowColumn
הם רכיבים שאפשר לשלב, בדומה ל-Row
ול-Column
, אבל ההבדל הוא שהפריטים עוברים לשורה הבאה כשנגמר המקום בקונטיינר. כך נוצרות כמה שורות או עמודות. אפשר גם לקבוע את מספר הפריטים בשורה באמצעות ההגדרה maxItemsInEachRow
או maxItemsInEachColumn
. בדרך כלל אפשר להשתמש ב-FlowRow
וב-FlowColumn
כדי ליצור פריסות עם תמיכה בהתאמה לעומס (responsive). התוכן לא ייחתך אם הפריטים גדולים מדי למאפיין אחד, ושימוש בשילוב של maxItemsInEach*
עם Modifier.weight(weight)
יכול לעזור ליצור פריסות שממלאות או מרחיבות את רוחב השורה או העמודה לפי הצורך.
דוגמה טיפוסית היא צ'יפ או ממשק משתמש לסינון:
שימוש בסיסי
כדי להשתמש ב-FlowRow
או ב-FlowColumn
, יוצרים את הרכיבים האלה ומציבים בתוכם את הפריטים שצריכים לפעול לפי התהליך הרגיל:
@Composable private fun FlowRowSimpleUsageExample() { FlowRow(modifier = Modifier.padding(8.dp)) { ChipItem("Price: High to Low") ChipItem("Avg rating: 4+") ChipItem("Free breakfast") ChipItem("Free cancellation") ChipItem("£50 pn") } }
קטע הקוד הזה יוצר את ממשק המשתמש שמוצג למעלה, שבו הפריטים עוברים באופן אוטומטי לשורה הבאה כשאין יותר מקום בשורה הראשונה.
תכונות של פריסה רציפה
למבנה זרימה יש את המאפיינים והתכונות הבאים, שאפשר להשתמש בהם כדי ליצור פריסות שונות באפליקציה.
סידור הציר הראשי: סידור אופקי או אנכי
הציר הראשי הוא הציר שבו הפריטים מסודרים (לדוגמה, ב-FlowRow
הפריטים מסודרים אופקית). הפרמטר horizontalArrangement
ב-FlowRow
קובע את האופן שבו שטח פנוי מחולק בין הפריטים.
בטבלה הבאה מוצגות דוגמאות להגדרת horizontalArrangement
בפריטים של FlowRow
:
ההגדרה של הפריסה האופקית היא |
התוצאה |
|
|
ל-FlowColumn
יש אפשרויות דומות ב-verticalArrangement
, עם הערך Arrangement.Top
כברירת מחדל.
פריסת צירים חוצים
הציר העקום הוא הציר בכיוון ההפוך לציר הראשי. לדוגמה, ב-FlowRow
, זהו הציר האנכי. כדי לשנות את אופן הסידור של התוכן הכולל בתוך הקונטיינר בציר החוצה, משתמשים ב-verticalArrangement
במקום ב-FlowRow
וב-horizontalArrangement
במקום ב-FlowColumn
.
בטבלה הבאה מוצגות דוגמאות להגדרת verticalArrangement
שונה בפריטים עבור FlowRow
:
הפריסה האנכית מוגדרת ב- |
תוצאה |
|
|
ל-FlowColumn
יש אפשרויות דומות ב-horizontalArrangement
.
ברירת המחדל של הסדר של ציר הצלב היא Arrangement.Start
.
יישור של פריטים בודדים
יכול להיות שתרצו למקם פריטים בודדים בשורה עם התאמות שונות. ההבדל בין verticalArrangement
ל-horizontalArrangement
הוא שהערך הזה מיישר את הפריטים בתוך השורה הנוכחית. אפשר להחיל את זה באמצעות Modifier.align()
.
לדוגמה, כשהפריטים ב-FlowRow
הם בגבהים שונים, השורה מקבלת את הגובה של הפריט הכי גדול ומחילה את Modifier.align(alignmentOption)
על הפריטים:
היישור האנכי מוגדר כ- |
תוצאה |
|
|
ל-FlowColumn
יש אפשרויות דומות. ערך ברירת המחדל הוא
Alignment.Start
.
מספר הפריטים המקסימלי בשורה או בעמודה
הפרמטרים maxItemsInEachRow
או maxItemsInEachColumn
מגדירים את מספר הפריטים המקסימלי בציר הראשי שאפשר להציג בשורה אחת לפני שמעבירים אותם לשורה הבאה. הערך שמוגדר כברירת מחדל הוא Int.MAX_INT
, שמאפשר להוסיף כמה פריטים שאפשר, כל עוד הם מתאימים לקו.
לדוגמה, הגדרת maxItemsInEachRow
מאלצת את הפריסה הראשונית לכלול רק 3 פריטים:
לא הוגדר ערך מקסימלי |
|
פריטים בתהליך טעינה מדורגת
ContextualFlowRow
ו-ContextualFlowColumn
הם גרסאות מיוחדות של FlowRow
ו-FlowColumn
שמאפשרות לטעון באיטרציות את התוכן של שורת הזרימה או העמודה. הם מספקים גם מידע על המיקום של הפריטים (האינדקס, מספר השורה והגודל הזמין), למשל אם הפריט נמצא בשורה הראשונה. האפשרות הזו שימושית לקבוצות גדולות של נתונים, וגם אם אתם צריכים מידע לפי הקשר לגבי פריט מסוים.
הפרמטר maxLines
מגביל את מספר השורות שמוצגות, והפרמטר overflow
מציין מה יוצג כשמגיעים למספר הפריטים המקסימלי. כך אפשר לציין expandIndicator
או collapseIndicator
מותאמים אישית.
לדוגמה, כדי להציג את הלחצן '+ (מספר הפריטים שנותרו)' או 'הצגת פחות':
val totalCount = 40 var maxLines by remember { mutableStateOf(2) } val moreOrCollapseIndicator = @Composable { scope: ContextualFlowRowOverflowScope -> val remainingItems = totalCount - scope.shownItemCount ChipItem(if (remainingItems == 0) "Less" else "+$remainingItems", onClick = { if (remainingItems == 0) { maxLines = 2 } else { maxLines += 5 } }) } ContextualFlowRow( modifier = Modifier .safeDrawingPadding() .fillMaxWidth(1f) .padding(16.dp) .wrapContentHeight(align = Alignment.Top) .verticalScroll(rememberScrollState()), verticalArrangement = Arrangement.spacedBy(4.dp), horizontalArrangement = Arrangement.spacedBy(8.dp), maxLines = maxLines, overflow = ContextualFlowRowOverflow.expandOrCollapseIndicator( minRowsToShowCollapse = 4, expandIndicator = moreOrCollapseIndicator, collapseIndicator = moreOrCollapseIndicator ), itemCount = totalCount ) { index -> ChipItem("Item $index") }
משקלים של פריטים
המשקל מגדיל את הפריט על סמך הגורם שלו והמקום הזמין בשורה שבה הוא ממוקם. חשוב לדעת שיש הבדל בין FlowRow
לבין Row
בנוגע לאופן שבו משתמשים במשקלים כדי לחשב את הרוחב של פריט. עבור Rows
, המשקל מבוסס על כל הפריטים ב-Row
. כשמשתמשים ב-FlowRow
, המשקל מבוסס על הפריטים בשורה שבה הפריט ממוקם, ולא על כל הפריטים במיכל FlowRow
.
לדוגמה, אם יש לכם 4 פריטים שנמצאים באותה שורה, ולכל אחד מהם משקל שונה של 1f, 2f, 1f
ו-3f
, המשקל הכולל הוא 7f
. המרחב שנותר בשורה או בעמודה יחולק ב-7f
. לאחר מכן, רוחב כל פריט יחושב באמצעות: weight * (remainingSpace / totalWeight)
.
אפשר להשתמש בשילוב של Modifier.weight
ופריטים מקסימליים עם FlowRow
או
FlowColumn
כדי ליצור פריסה שדומה לרשת. הגישה הזו שימושית ליצירת פריסות רספונסיביות שמתאימות לגודל המסך של המכשיר.
יש כמה דוגמאות שונות למה שאפשר להשיג באמצעות משקלים. דוגמה לכך היא רשת שבה הפריטים באותו גודל, כפי שמוצג בהמשך:
כדי ליצור רשת של פריטים בגדלים זהים, אפשר לבצע את הפעולות הבאות:
val rows = 3 val columns = 3 FlowRow( modifier = Modifier.padding(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), maxItemsInEachRow = rows ) { val itemModifier = Modifier .padding(4.dp) .height(80.dp) .weight(1f) .clip(RoundedCornerShape(8.dp)) .background(MaterialColors.Blue200) repeat(rows * columns) { Spacer(modifier = itemModifier) } }
חשוב לדעת: אם מוסיפים פריט נוסף ומחזורים אותו 10 פעמים במקום 9, הפריט האחרון תופס את כל העמודה האחרונה, כי המשקל הכולל של השורה כולה הוא 1f
:
אפשר לשלב משקלים עם Modifiers
אחרים, כמו Modifier.width(exactDpAmount), Modifier.aspectRatio(aspectRatio)
או Modifier.fillMaxWidth(fraction)
. כל המשתנים האלה פועלים יחד כדי לאפשר שינוי גודל רספונסיבי של פריטים בתוך FlowRow
(או FlowColumn
).
אפשר גם ליצור רשת לסירוגין של פריטים בגדלים שונים, שבה שני פריטים תופסים כל אחד חצי מהרוחב, ופריט אחד תופס את כל רוחב העמודה הבאה:
אפשר לעשות זאת באמצעות הקוד הבא:
FlowRow( modifier = Modifier.padding(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), maxItemsInEachRow = 2 ) { val itemModifier = Modifier .padding(4.dp) .height(80.dp) .clip(RoundedCornerShape(8.dp)) .background(Color.Blue) repeat(6) { item -> // if the item is the third item, don't use weight modifier, but rather fillMaxWidth if ((item + 1) % 3 == 0) { Spacer(modifier = itemModifier.fillMaxWidth()) } else { Spacer(modifier = itemModifier.weight(0.5f)) } } }
שינוי גודל חלקי
בעזרת Modifier.fillMaxWidth(fraction)
אפשר לציין את הגודל של המאגר שבו הפריט אמור להימצא. ההבדל הוא ש-Row/Column
תופס אחוז מהרוחב שנותר, במקום את רוחב המאגר כולו, בניגוד לאופן שבו Modifier.fillMaxWidth(fraction)
פועל כשמחילים אותו על Row
או על Column
.
לדוגמה, הקוד הבא מניב תוצאות שונות כשמשתמשים ב-FlowRow
לעומת Row
:
FlowRow( modifier = Modifier.padding(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), maxItemsInEachRow = 3 ) { val itemModifier = Modifier .clip(RoundedCornerShape(8.dp)) Box( modifier = itemModifier .height(200.dp) .width(60.dp) .background(Color.Red) ) Box( modifier = itemModifier .height(200.dp) .fillMaxWidth(0.7f) .background(Color.Blue) ) Box( modifier = itemModifier .height(200.dp) .weight(1f) .background(Color.Magenta) ) }
|
|
|
fillMaxColumnWidth()
וגם fillMaxRowHeight()
החלת Modifier.fillMaxColumnWidth()
או Modifier.fillMaxRowHeight()
על פריט בתוך FlowColumn
או FlowRow
מבטיחה שהפריטים באותה עמודה או שורה יתפסו את אותו רוחב או גובה כמו הפריט הגדול ביותר בעמודה או בשורה.
לדוגמה, בדוגמה הזו נעשה שימוש ב-FlowColumn
כדי להציג את רשימת הגרסאות של Android. אפשר לראות את ההבדל בין רוחב כל פריט כשהתכונה Modifier.fillMaxColumnWidth()
חלה על הפריטים לבין רוחב הפריט כשהתכונה לא חלה עליו והפריטים מנותבים.
FlowColumn( Modifier .padding(20.dp) .fillMaxHeight() .fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp), maxItemsInEachColumn = 5, ) { repeat(listDesserts.size) { Box( Modifier .fillMaxColumnWidth() .border(1.dp, Color.DarkGray, RoundedCornerShape(8.dp)) .padding(8.dp) ) { Text( text = listDesserts[it], fontSize = 18.sp, modifier = Modifier.padding(3.dp) ) } } }
|
|
לא הוגדרו שינויים ברוחב (פריטים שמקפלים) |
מומלץ עבורך
- הערה: טקסט הקישור מוצג כש-JavaScript מושבת
- יסודות של יצירת פריסה
- ConstraintLayout ב-Compose
- פעולות של עורך {:#editor-actions}