אחד הכללים של Compose הוא שצריך למדוד את הילדים רק פעם אחת. מדידת ילדים פעמיים גורמת לחריגה בזמן הריצה. עם זאת, יש מקרים שבהם צריך לקבל מידע מסוים על הילדים לפני שמודדים אותם.
באמצעות Intrinsics אפשר לשאול שאלות על ילדים לפני שמודדים אותם בפועל.
אפשר לבקש מ-Composable את 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 composable שממלאים את המקום הפנוי, וב-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) מגדיר את הגובה של רכיבי הצאצא שלו כך שיהיה שווה לגובה המינימלי המובנה שלהם. מכיוון שהמשנה הזה הוא רקורסיבי, הוא שולח שאילתה אל minIntrinsicHeight של Row ושל הצאצאים שלו.
הוספת מקש הצירוף הזה לקוד גורמת לו לפעול כצפוי:
@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 נקבע באופן הבא:
- הערך
minIntrinsicHeightשל רכיב ה-Rowcomposable הוא הערך המקסימליminIntrinsicHeightשל רכיבי הצאצא שלו. - הערך של
minIntrinsicHeightבאלמנטDividerהוא 0, כי הוא לא תופס מקום אם לא מציינים אילוצים. - ה
TextminIntrinsicHeightהוא של הטקסט עבור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 פיתוח נייטיב