אחד הכללים של Compose הוא שצריך למדוד את הרכיבים רק פעם אחת. אם מודדים את הרכיבים פעמיים, מתקבל חריג בזמן הריצה. עם זאת, יש מקרים שבהם צריך לקבל מידע מסוים על הילדים לפני שמודדים אותם.
התכונה Intrinsics מאפשרת לשאול שאלות על ילדים לפני שמודדים אותם בפועל.
אפשר לבקש מ-Gemini את IntrinsicSize.Min
או את IntrinsicSize.Max
של קומפוזיציה:
-
Modifier.width(IntrinsicSize.Min)
– מה הרוחב המינימלי שנדרש כדי להציג את התוכן בצורה תקינה? Modifier.width(IntrinsicSize.Max)
– מה הרוחב המקסימלי שנדרש כדי להציג את התוכן בצורה תקינה?-
Modifier.height(IntrinsicSize.Min)
– מה הגובה המינימלי שנדרש כדי להציג את התוכן בצורה תקינה? -
Modifier.height(IntrinsicSize.Max)
– מה הגובה המקסימלי שנדרש כדי להציג את התוכן בצורה תקינה?
לדוגמה, אם מבקשים את minIntrinsicHeight
של Text
עם אילוצי width
אינסופיים בפריסה בהתאמה אישית, הפונקציה תחזיר את height
של Text
עם הטקסט שמוצג בשורה אחת.
פונקציות פנימיות (intrinsics) בפעולה
נניח שאנחנו רוצים ליצור קומפוזבל שמציג שני טקסטים על המסך, מופרדים על ידי קו מפריד, כמו בדוגמה הבאה:
איך עושים את זה? אפשר ליצור Row
עם שני Text
s בתוכו שמתרחב ככל האפשר, ו-Divider
באמצע. אנחנו רוצים שהDivider
יהיה גבוה כמו הText
הכי גבוה ודק (width = 1.dp
).
@Composable fun TwoTexts(modifier: Modifier = Modifier, text1: String, text2: String) { Row(modifier = modifier) { Text( modifier = Modifier .weight(1f) .padding(start = 4.dp) .wrapContentWidth(Alignment.Start), text = text1 ) VerticalDivider( color = Color.Black, modifier = Modifier.fillMaxHeight().width(1.dp) ) Text( modifier = Modifier .weight(1f) .padding(end = 4.dp) .wrapContentWidth(Alignment.End), text = text2 ) } }
אם נציג את זה בתצוגה מקדימה, נראה שהרכיב Divider
מתרחב למסך מלא וזה לא מה שאנחנו רוצים:
הסיבה לכך היא ש-Row
מודד כל ילד בנפרד, ואי אפשר להשתמש בגובה של Text
כדי להגביל את Divider
. אנחנו רוצים שהרכיב Divider
ימלא את השטח הפנוי בגובה נתון. כדי לעשות את זה, אפשר להשתמש במילת המפתח height(IntrinsicSize.Min)
.
הגודל של height(IntrinsicSize.Min)
נקבע לפי הגובה המינימלי הפנימי של רכיבי הצאצא שלו. השאילתה היא רקורסיבית, ולכן היא תפנה אל Row
ואל צאצאיו minIntrinsicHeight
.
אם נחיל את זה על הקוד שלנו, הוא יפעל כמצופה:
@Composable fun TwoTexts(modifier: Modifier = Modifier, text1: String, text2: String) { Row(modifier = modifier.height(IntrinsicSize.Min)) { Text( modifier = Modifier .weight(1f) .padding(start = 4.dp) .wrapContentWidth(Alignment.Start), text = text1 ) VerticalDivider( color = Color.Black, modifier = Modifier.fillMaxHeight().width(1.dp) ) Text( modifier = Modifier .weight(1f) .padding(end = 4.dp) .wrapContentWidth(Alignment.End), text = text2 ) } } // @Preview @Composable fun TwoTextsPreview() { MaterialTheme { Surface { TwoTexts(text1 = "Hi", text2 = "there") } } }
עם תצוגה מקדימה:
הערך של Row
composable's minIntrinsicHeight
יהיה המקסימום
minIntrinsicHeight
של רכיבי הצאצא שלו. הערך של Divider
element's
minIntrinsicHeight
הוא 0 כי הוא לא תופס מקום אם לא מציינים מגבלות. הערך של Text
minIntrinsicHeight
יהיה הערך של הטקסט בהינתן width
ספציפי. לכן, המגבלה height
של הרכיב Row
תהיה הערך המקסימלי minIntrinsicHeight
של הרכיבים Text
. Divider
ירחיב את height
בהתאם לאילוץ height
שצוין על ידי Row
.
מאפיינים מובנים בפריסות בהתאמה אישית
כשיוצרים משנה Layout
או layout
בהתאמה אישית, המערכת מחשבת באופן אוטומטי את המידות הפנימיות על סמך קירובים. לכן, יכול להיות שהחישובים לא יהיו נכונים לכל הפריסות. ממשקי ה-API האלה מציעים אפשרויות לשינוי ברירות המחדל.
כדי לציין את המדידות הפנימיות של Layout
בהתאמה אישית,
צריך לבטל את ההגדרה של minIntrinsicWidth
, minIntrinsicHeight
, maxIntrinsicWidth
ו-maxIntrinsicHeight
בממשק MeasurePolicy
כשיוצרים אותו.
@Composable fun MyCustomComposable( modifier: Modifier = Modifier, content: @Composable () -> Unit ) { Layout( content = content, modifier = modifier, measurePolicy = object : MeasurePolicy { override fun MeasureScope.measure( measurables: List<Measurable>, constraints: Constraints ): MeasureResult { // Measure and layout here // ... } override fun IntrinsicMeasureScope.minIntrinsicWidth( measurables: List<IntrinsicMeasurable>, height: Int ): Int { // Logic here // ... } // Other intrinsics related methods have a default value, // you can override only the methods that you need. } ) }
כשיוצרים משנה מותאם אישית של layout
, מחליפים את השיטות שקשורות לממשק LayoutModifier
.
fun Modifier.myCustomModifier(/* ... */) = this then object : LayoutModifier { override fun MeasureScope.measure( measurable: Measurable, constraints: Constraints ): MeasureResult { // Measure and layout here // ... } override fun IntrinsicMeasureScope.minIntrinsicWidth( measurable: IntrinsicMeasurable, height: Int ): Int { // Logic here // ... } // Other intrinsics related methods have a default value, // you can override only the methods that you need. }
מומלץ עבורך
- הערה: טקסט הקישור מוצג כש-JavaScript מושבת
- פריסות בהתאמה אישית {:#custom-layouts }
- קווי יישור ב-Jetpack פיתוח נייטיב
- שלבים ב-Jetpack פיתוח נייטיב