ב-Compose, רכיבי ממשק המשתמש מיוצגים על ידי הפונקציות הניתנות ליצירה שמפיקות קטע של ממשק משתמש כשהן מופעלות, ולאחר מכן מתווספות לעץ של ממשק המשתמש שעבר עיבוד (render) במסך. לכל רכיב בממשק המשתמש יש הורה אחד ויכולים להיות לו הרבה צאצאים. כל רכיב נמצא גם בתוך האב שלו, ומוגדר במיקום (x, y) ובגודל, שמוגדר כ-width
ו-height
.
רכיבי ההורה מגדירים את האילוצים של רכיבי הצאצא שלהם. האלמנט מתבקש להגדיר את הגודל שלו במסגרת האילוצים האלה. המגבלות מגבילות את
לכל היותר width
ו-height
של רכיב. אם לרכיב יש רכיבי צאצא,
כדי לעזור בקביעת הגודל של כל ילד או ילדה. ברגע שרכיב קובע
ומדווחת על גודלו, יש לו הזדמנות להגדיר כיצד למקם את
ביחס לעצמו, כפי שמתואר בפירוט במאמר יצירת
.
תכנון המיקום של כל צומת בעץ ממשק המשתמש הוא תהליך בן שלושה שלבים. כל צומת צריך:
- מודדים ילדים
- בחירת גודל משלהם
- ממקמים את הצאצאים שלו
השימוש בהיקפים מגדיר מתי אפשר למדוד ולמקם את הילדים.
אפשר למדוד פריסה רק במהלך מעברי המדידה והפריסה, ואפשר להציב רכיב צאצא רק במהלך מעברי הפריסה (ורק אחרי שהוא נמדד). בגלל היקפי Compose כמו MeasureScope
ו-PlacementScope
, האכיפה מתבצעת בזמן הידור.
שימוש במשתנה הפריסה
אפשר להשתמש בתכונת הצירוף layout
כדי לשנות את אופן המדידה והפריסה של רכיב
החוצה. Layout
הוא lambda. הפרמטרים שלו כוללים את הרכיב שניתן למדוד,
מועבר בתור measurable
, והמגבלות הנכנסות של התוכן הקומפוזבילי הזה מועברות
constraints
. כך יכול להיראות שינוי מותאם אישית של הפריסה:
fun Modifier.customLayoutModifier() = layout { measurable, constraints -> // ... }
נציג Text
במסך ונקבע את המרחק מהחלק העליון אל
את הבסיס של השורה הראשונה בטקסט. זה בדיוק מה שמשנה paddingFromBaseline
עושה, אנחנו מטמיעים אותו כאן כדוגמה.
כדי לעשות זאת, משתמשים במקש המשנה layout
כדי למקם את ה-Composable במסך באופן ידני. זוהי ההתנהגות הרצויה שבה Text
top padding מוגדר 24.dp
:
הנה הקוד שיוצר את הריווח:
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) } }
זה מה שקורה בקוד הזה:
- כדי למדוד את הערך של
Text
שמיוצג על ידי הפרמטר המדד, קוראים לפונקציהmeasurable.measure(constraints)
בפרמטר lambdameasurable
. - כדי לציין את הגודל של התוכן הקומפוזבילי, שולחים קריאה ל-
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)) } }
יצירת פריסות בהתאמה אישית
המשתנה 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 // ... } }
בדומה למגביל 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 המותאם אישית:
@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!") } }
כיוון הפריסה
כדי לשנות את כיוון הפריסה של תוכן קומפוזבילי, משנים את
LocalLayoutDirection
יצירה מקומית.
אם מוסיפים תכנים קומפוזביליים באופן ידני במסך, הערך של LayoutDirection
הוא
חלק מה-LayoutScope
של המגביל layout
או של התוכן הקומפוזבילי Layout
.
כשמשתמשים ב-layoutDirection
, מציבים את הרכיבים באמצעות place
. בניגוד לשיטה placeRelative
, הערך של place
לא משתנה בהתאם לכיוון של הפריסה (שמאלה לימין לעומת ימינה לשמאל).
פריסות בהתאמה אישית בפעולה
מידע נוסף על פריסות ועל מגבילי התאמה זמין פריסות בסיסיות ב'כתיבה', ולראות פריסות מותאמות אישית בפעולה כתיבת דוגמאות ליצירת פריסות מותאמות אישית.
מידע נוסף
למידע נוסף על פריסות מותאמות אישית ב'כתיבה', אפשר להיעזר במקורות הבאים במשאבי אנוש.
סרטונים
מומלץ עבורך
- הערה: טקסט הקישור מוצג כאשר JavaScript מושבת
- מדידות פנימיות בפריסות של פיתוח חדש
- גרפיקה ב-Compose
- הרכבת משתנים