ב-Compose, רכיבים בממשק המשתמש מיוצגים על ידי הפונקציות הקומפוזביליות שפולטות חלק מממשק המשתמש כשהן מופעלות, ואז מתווספות לעץ של ממשק המשתמש שמוצג במסך. לכל רכיב בממשק המשתמש יש הורה אחד, ויכולים להיות לו הרבה צאצאים. כל רכיב נמצא גם בתוך רכיב ההורה שלו, שמוגדר כמיקום (x, y) וכגודל, שמוגדר כ-width וכ-height.
ההורים מגדירים את האילוצים של רכיבי הצאצאים שלהם. הרכיב מתבקש להגדיר את הגודל שלו בתוך המגבלות האלה. האילוצים מגבילים את הערכים המינימליים והמקסימליים של width ו-height של רכיב. אם לרכיב יש רכיבי צאצא, הוא יכול למדוד כל צאצא כדי לקבוע את הגודל שלו. אחרי שרכיב קובע את הגודל שלו ומדווח עליו, הוא יכול להגדיר איך למקם את רכיבי הצאצא שלו ביחס אליו, כפי שמתואר בפירוט במאמר יצירת פריסות בהתאמה אישית.
הפריסה של כל צומת בעץ ממשק המשתמש היא תהליך בן שלושה שלבים. כל צומת חייב:
- מודדים את כל הילדים
- לקבוע את הגודל שלו בעצמו
- מיקום הצאצאים שלו
השימוש בהיקפים מגדיר מתי אפשר למדוד ולהציב את הצאצאים.
אפשר למדוד פריסה רק במהלך שלבי המדידה והפריסה, ואפשר למקם רכיב צאצא רק במהלך שלבי הפריסה (ורק אחרי שהוא נמדד). בגלל היקפי ההרשאות של Compose, כמו MeasureScope ו-PlacementScope, האכיפה מתבצעת בזמן הקימפול.
שימוש בשינוי הפריסה
אפשר להשתמש במשנה layout כדי לשנות את האופן שבו רכיב נמדד ומוצג. Layout הוא למבדה. הפרמטרים שלו כוללים את הרכיב שאפשר למדוד, שמועבר בתור measurable, ואת האילוצים הנכנסים של הרכיב הניתן לשילוב, שמועברים בתור constraints. כך נראה משתנה של פריסה בהתאמה אישית:
fun Modifier.customLayoutModifier() = layout { measurable, constraints -> // ... }
הצגת Text במסך ושליטה במרחק מהחלק העליון לקו הבסיס של שורת הטקסט הראשונה. זה בדיוק מה שהמשתנה paddingFromBaseline עושה. אתם מטמיעים אותו כאן כדוגמה.
כדי לעשות את זה, משתמשים ב-modifier layout כדי למקם את ה-composable במסך באופן ידני. כך נראית התוצאה כשהריפוד העליון של Text מוגדר לערך 24.dp:
paddingFromBaseline.
זה הקוד שיוצר את הריווח הזה:
fun Modifier.firstBaselineToTop( firstBaselineToTop: Dp ) = layout { measurable, constraints -> // Measure the composable val placeable = measurable.measure(constraints) // Check the composable has a first baseline check(placeable[FirstBaseline] != AlignmentLine.Unspecified) val firstBaseline = placeable[FirstBaseline] // Height of the composable with padding - first baseline val placeableY = firstBaselineToTop.roundToPx() - firstBaseline val height = placeable.height + placeableY layout(placeable.width, height) { // Where the composable gets placed placeable.placeRelative(0, placeableY) } }
הנה הסבר על מה שקורה בקוד הזה:
- בפרמטר הלמבדה
measurable, מודדים אתTextשמיוצג על ידי הפרמטר שניתן למדידה באמצעות קריאה ל-measurable.measure(constraints). - כדי לציין את הגודל של התוכן הקומפוזבילי, מפעילים את השיטה
layout(width, height), שמספקת גם פונקציית lambda שמשמשת להצבת הרכיבים שעטופים. במקרה הזה, זה הגובה בין קו הבסיס האחרון לבין המרווח הפנימי העליון שנוסף. - כדי למקם את הרכיבים העטופים במסך, צריך להפעיל את הפונקציה
placeable.place(x, y). אם לא ממקמים את הרכיבים שעטופים, הם לא יהיו גלויים. המיקוםyתואם למרווח הפנימי העליון: המיקום של קו הבסיס הראשון של הטקסט.
כדי לוודא שהשינוי פועל כמו שצריך, משתמשים בשינוי הזה ב-Text:
@Preview @Composable fun TextWithPaddingToBaselinePreview() { MyApplicationTheme { Text("Hi there!", Modifier.firstBaselineToTop(32.dp)) } } @Preview @Composable fun TextWithNormalPaddingPreview() { MyApplicationTheme { Text("Hi there!", Modifier.padding(top = 32.dp)) } }
Text ומוצג בתצוגה מקדימה.
יצירת פריסות בהתאמה אישית
המשתנה layout משנה רק את ה-composable שקורא לו. כדי למדוד ולסדר כמה רכיבים קומפוזביליים, משתמשים במקום זאת ברכיב הקומפוזבילי Layout. הפונקציה הקומפוזבילית הזו מאפשרת למדוד ולפרוס רכיבי צאצא באופן ידני. כל הפריסות ברמה גבוהה יותר, כמו Column ו-Row, נוצרות באמצעות הרכיב הקומפוזבילי Layout.
בדוגמה הזו אנחנו יוצרים גרסה בסיסית מאוד של Column. רוב הפריסות בהתאמה אישית פועלות לפי התבנית הזו:
@Composable fun MyBasicColumn( modifier: Modifier = Modifier, content: @Composable () -> Unit ) { Layout( modifier = modifier, content = content ) { measurables, constraints -> // measure and position children given constraints logic here // ... } }
בדומה ל-modifier layout, measurables היא רשימת הצאצאים שצריך למדוד ו-constraints הם האילוצים מההורה.
לפי אותו היגיון, אפשר להטמיע את MyBasicColumn כך:
@Composable fun MyBasicColumn( modifier: Modifier = Modifier, content: @Composable () -> Unit ) { Layout( modifier = modifier, content = content ) { measurables, constraints -> // Don't constrain child views further, measure them with given constraints // List of measured children val placeables = measurables.map { measurable -> // Measure each children measurable.measure(constraints) } // Set the size of the layout as big as it can layout(constraints.maxWidth, constraints.maxHeight) { // Track the y co-ord we have placed children up to var yPosition = 0 // Place children in the parent layout placeables.forEach { placeable -> // Position item on the screen placeable.placeRelative(x = 0, y = yPosition) // Record the y co-ord placed up to yPosition += placeable.height } } } }
הרכיבים הניתנים ליצירה שהם צאצאים מוגבלים על ידי האילוצים של Layout (ללא האילוצים של minHeight), והם ממוקמים על סמך ה-yPosition של הרכיב הניתן ליצירה הקודם.
כך משתמשים בפונקציה הניתנת ליצירה בהתאמה אישית:
@Composable fun CallingComposable(modifier: Modifier = Modifier) { MyBasicColumn(modifier.padding(8.dp)) { Text("MyBasicColumn") Text("places items") Text("vertically.") Text("We've done it by hand!") } }
Column.
כיוון הפריסה
כדי לשנות את כיוון הפריסה של רכיב קומפוזבילי, משנים את הערך של LocalLayoutDirection ב-CompositionLocal.
אם אתם ממקמים רכיבים קומפוזביליים באופן ידני במסך, ה-LayoutDirection הוא חלק מה-LayoutScope של ה-modifier layout או של הרכיב הקומפוזבילי Layout.
כשמשתמשים ב-layoutDirection, ממקמים רכיבים קומפוזביליים באמצעות place. בניגוד ל-method placeRelative, הערך של place לא משתנה בהתאם לכיוון הפריסה (משמאל לימין לעומת מימין לשמאל).
פריסות בהתאמה אישית בפעולה
מידע נוסף על פריסות ומשתני שינוי זמין במאמר פריסות בסיסיות ב-Compose, ודוגמאות לפריסות בהתאמה אישית זמינות במאמר דוגמאות ליצירת פריסות בהתאמה אישית ב-Compose.
מידע נוסף
במקורות המידע הבאים אפשר למצוא מידע נוסף על פריסות בהתאמה אישית ב-Compose.
סרטונים
מומלץ בשבילכם
- הערה: טקסט הקישור מוצג כש-JavaScript מושבת
- מדידות פנימיות בפריסות של Compose
- גרפיקה ב-Compose
- שינוי קומפוזיציה