מגבילי התאמה מאפשרים לכם לקשט או לשפר תוכן קומפוזבילי. מגבילי התאמה מאפשרים לך דברים כאלה:
- שינוי הגודל, הפריסה, ההתנהגות והמראה של התוכן הקומפוזבילי
- הוספת מידע, כמו תוויות נגישות
- עיבוד קלט של משתמשים
- להוסיף אינטראקציות ברמה גבוהה, כמו יצירה של אלמנט שניתן ללחוץ עליו, מאפשר גלילה ניתן לגרירה או לשינוי מרחק התצוגה
מגבילי התאמה הם אובייקטים רגילים של Kotlin. כדי ליצור מגביל, מפעילים את אחת מהאפשרויות
Modifier
פונקציות מחלקה:
@Composable private fun Greeting(name: String) { Column(modifier = Modifier.padding(24.dp)) { Text(text = "Hello,") Text(text = name) } }
אפשר לשרשר את הפונקציות האלה יחד כדי להרכיב אותן:
@Composable private fun Greeting(name: String) { Column( modifier = Modifier .padding(24.dp) .fillMaxWidth() ) { Text(text = "Hello,") Text(text = name) } }
בקוד שלמעלה, שימו לב לפונקציות התאמה שונות שנעשה בהן שימוש יחד.
padding
תופסת רווח מסביב לרכיב.fillMaxWidth
הופך את המילוי הקומפוזבילי לרוחב המקסימלי שניתן לו ההורה שלו.
מומלץ שכל התכנים הקומפוזביליים יקבלו את הערך modifier
ומעבירים את הערך הזה לצאצא הראשון שפולט ממשק משתמש.
הפעולה הזו הופכת את
קוד לשימוש חוזר, והופך את ההתנהגות שלו לצפויה ואינטואיטיבית יותר. עבור
למידע נוסף, ראו את ההנחיות ל-Compose API, הרכיבים מקבלים ומכבדים
פרמטר הצירוף.
סדר ההתאמות חשוב
הסדר של פונקציות הצירוף הוא משמעותי. מכיוון שכל פונקציה היא
בפונקציה Modifier
שמוחזרת על ידי הפונקציה הקודמת, הרצף
משפיעה על התוצאה הסופית. נראה דוגמה לכך:
@Composable fun ArtistCard(/*...*/) { val padding = 16.dp Column( Modifier .clickable(onClick = onClick) .padding(padding) .fillMaxWidth() ) { // rest of the implementation } }
בקוד שמעל כל האזור ניתן ללחוץ, כולל כל האזור שמסביב
המרווח הפנימי, כי הצירוף padding
הוחל אחרי clickable
לעיבוד טקסט. אם סדר המשנים הפוך, המרחב המשותף שנוסף על ידי padding
לא להגיב לקלט של משתמשים:
@Composable fun ArtistCard(/*...*/) { val padding = 16.dp Column( Modifier .padding(padding) .clickable(onClick = onClick) .fillMaxWidth() ) { // rest of the implementation } }
מקשי צירוף מובנים
'Jetpack פיתוח נייטיב' מספק רשימה של מגבילי התאמה מובנים שיעזרו לכם לקשט או להרחיב תוכן קומפוזבילי. הנה כמה התאמות נפוצות שבהן תשתמשו כדי לשנות שונות.
padding
וגם size
כברירת מחדל, פריסות שמופיעות ב'כתיבה' כוללות את הצאצאים שלהן. אבל, לפעמים
אפשר להגדיר גודל באמצעות מקש הצירוף size
:
@Composable fun ArtistCard(/*...*/) { Row( modifier = Modifier.size(width = 400.dp, height = 100.dp) ) { Image(/*...*/) Column { /*...*/ } } }
לתשומת ליבכם: יכול להיות שהגודל שציינתם לא יכובד אם הוא לא מתאים
המגבלות שנובעות מההורה של הפריסה. אם אתם צריכים את התוכן הקומפוזבילי
גודל שצריך לתקן ללא קשר למגבלות הנכנסות, צריך להשתמש בפונקציה requiredSize
מגביל:
@Composable fun ArtistCard(/*...*/) { Row( modifier = Modifier.size(width = 400.dp, height = 100.dp) ) { Image( /*...*/ modifier = Modifier.requiredSize(150.dp) ) Column { /*...*/ } } }
בדוגמה הזו, גם כשההורה height
מוגדר כ-100.dp
, הגובה של
הערך Image
יהיה 150.dp
, כי הצירוף requiredSize
לוקח
בעדיפות גבוהה.
אם רוצים שפריסת צאצא תמלא את כל הגובה הזמין שמותר לפי
הורה, צריך להוסיף את הצירוף fillMaxHeight
(התכונה 'כתיבה' מספקת גם
fillMaxSize
ו-fillMaxWidth
):
@Composable fun ArtistCard(/*...*/) { Row( modifier = Modifier.size(width = 400.dp, height = 100.dp) ) { Image( /*...*/ modifier = Modifier.fillMaxHeight() ) Column { /*...*/ } } }
כדי להוסיף מרווח פנימי מסביב לרכיב, מגדירים מגביל padding
.
אם רוצים להוסיף מרווח פנימי מעל ערך הבסיס של טקסט,
מרחק ספציפי מהחלק העליון של הפריסה אל הבסיס, משתמשים באופרטור
מגביל paddingFromBaseline
:
@Composable fun ArtistCard(artist: Artist) { Row(/*...*/) { Column { Text( text = artist.name, modifier = Modifier.paddingFromBaseline(top = 50.dp) ) Text(artist.lastSeenOnline) } } }
היסט
כדי למקם פריסה ביחס למיקום המקורי שלה, מוסיפים את
מקש הצירוף offset
ומגדירים את ההיסט בצירים x ו-y.
קיזוזים יכולים להיות חיוביים ולא חיוביים. ההבדל בין
padding
ו-offset
זה אומר שהוספת offset
לתוכן קומפוזבילי לא
לשנות את המדידות שלו:
@Composable fun ArtistCard(artist: Artist) { Row(/*...*/) { Column { Text(artist.name) Text( text = artist.lastSeenOnline, modifier = Modifier.offset(x = 4.dp) ) } } }
הצירוף offset
מיושם לרוחב בהתאם לכיוון הפריסה.
בהקשר משמאל לימין, ערך offset
חיובי מזיז את הרכיב
מימין, ובהקשר של ימין לשמאל, היא מסיטה את הרכיב שמאלה.
אם עליך להגדיר היסט בלי להתחשב בכיוון הפריסה,
absoluteOffset
שבו ערך היסט חיובי תמיד מעביר את הרכיב
נכון.
מקש הצירוף offset
מספק שני עומסי יתר – offset
שלוקח את
מחלצת כפרמטרים ו-offset
מקבלת lambda.
כדי לקבל מידע מעמיק יותר על המקרים שבהם כדאי להשתמש בכל אחת מהאפשרויות האלה ואיך לבצע אופטימיזציה
לביצועים, לקרוא
ביצועי כתיבה – דחיית הקריאה כמה שיותר זמן.
היקף הבטיחות של הכתיבה
בקטע 'כתיבה' יש מגבילי התאמה שאפשר להשתמש בהם רק כשמחילים אותם על ילדים של תכנים קומפוזביליים מסוימים. אוכפים את זה באמצעות היקפים מותאמים אישית.
לדוגמה, אם רוצים להגדיר ילד או ילדה בגודל של הורה Box
בלי
שמשפיע על הגודל של Box
, יש להשתמש
matchParentSize
לעיבוד טקסט. matchParentSize
זמין רק ב:
BoxScope
.
לכן, אפשר להשתמש בה רק בחשבון של ילד או ילדה ב-Box
.
בטיחות ההיקף מונעת ממך להוסיף מגבילי התאמה שלא פועלים בקמפיינים אחרים תכנים קומפוזביליים והיקפים, וחוסכים זמן מניסוי ומשגיאות.
מגבילי התאמה עם היקף ספציפי יודיעו להורה על מידע מסוים שההורה לדעת על הילד או הילדה. תכנים כאלה מכונים בדרך כלל פרמטרים להתאמה אישית של נתוני הורה. הדברים הפנימיים שלהם שונים מהמטרה הכללית אבל מבחינת השימוש, ההבדלים האלה לא חשובים.
matchParentSize
בעוד Box
כפי שצוין למעלה, אם רוצים שפריסת צאצא תהיה באותו גודל כמו תבנית הורה.
Box
בלי להשפיע על הגודל של Box
, אפשר להשתמש בתכונת הצירוף matchParentSize
.
לתשומת ליבכם, matchParentSize
זמין רק במסגרת היקף של Box
. כלומר,
הוא חל רק על צאצאים ישירים של תכנים קומפוזביליים של Box
.
בדוגמה הבאה, הצאצא Spacer
מקבל את הגודל שלו ממאפיין ההורה Box
,
שבו הגודל שלו נקבע מהילדים הכי גדולים,
ArtistCard
במקרה הזה.
@Composable fun MatchParentSizeComposable() { Box { Spacer( Modifier .matchParentSize() .background(Color.LightGray) ) ArtistCard() } }
אם נעשה שימוש ב-fillMaxSize
במקום ב-matchParentSize
, הפונקציה Spacer
הייתה
את כל השטח הזמין להורה, וכך גורמים להורה
להרחיב ולמלא את כל השטח הזמין.
weight
ב-Row
וב-Column
כמו שראית בסעיף הקודם על ריפוד
size, כברירת מחדל, גודל קומפוזבילי מוגדר על ידי
את התוכן שעוטף. אפשר להגדיר גודל קומפוזבילי שיהיה גמיש במסגרת
משתמש בתכונת הצירוף weight
שזמינה רק ב-RowScope
, וגם
ColumnScope
.
ניקח למשל Row
שמכיל שתי תכנים קומפוזביליים של Box
.
התיבה הראשונה מקבלת פעמיים את הערך weight
של השנייה, אז היא מקבלת פעמיים את הערך
רוחב. מכיוון שהרוחב של Row
הוא 210.dp
, הBox
הראשון הוא ברוחב של 140.dp
, וגם
השני הוא 70.dp
:
@Composable fun ArtistCard(/*...*/) { Row( modifier = Modifier.fillMaxWidth() ) { Image( /*...*/ modifier = Modifier.weight(2f) ) Column( modifier = Modifier.weight(1f) ) { /*...*/ } } }
חילוץ ושימוש חוזר של רכיבי הצירוף
אפשר לשרשר כמה צירופים כדי לקשט או
להרחיב תוכן קומפוזבילי. הרשת הזו נוצרת דרך הממשק Modifier
שמייצג רשימה ממוינת שלא ניתנת לשינוי של Modifier.Elements
יחיד.
כל Modifier.Element
מייצג התנהגות אישית, כמו פריסה ושרטוט
וההתנהגויות הגרפיות, כל ההתנהגויות שקשורות לתנועה, להתמקדות וסמנטיקה,
וגם אירועי קלט במכשיר. הסדר שלהם חשוב: רכיבי התאמה
שנוספו תחילה יחולו קודם.
לפעמים כדאי להשתמש שוב באותם מופעים של שרשרת הצירוף של כמה תכנים קומפוזביליים, על ידי חילוץ שלהם למשתנים והעלאתם להיקפים גבוהים יותר. הוא יכול לשפר את קריאות הקוד או לעזור בשיפור האפליקציה הביצועים מכמה סיבות:
- ההקצאה מחדש של ערכי הצירוף לא תחזור על עצמה כשתתבצע הרכבה מחדש לתכנים קומפוזביליים שמשתמשים בהם
- שרשראות הצירוף עשויות להיות ארוכות ומורכבות מאוד, לכן שימוש חוזר אותו מופע של שרשרת יכול להקל את עומס העבודה שזמן הריצה של פיתוח נייטיב צריך כשמשווים ביניהם
- החילוץ הזה עוזר לשפר את הניקיון, העקביות והתחזוקה של הקוד ב-codebase
שיטות מומלצות לשימוש חוזר בהתאמות
אפשר ליצור רשתות Modifier
משלך ולחלץ אותן כדי להשתמש בהן שוב בכמה רשתות
ורכיבים קומפוזביליים. זה בסדר גמור לשמור צירוף, כי
הם אובייקטים דמויי נתונים:
val reusableModifier = Modifier .fillMaxWidth() .background(Color.Red) .padding(12.dp)
חילוץ ושימוש חוזר של מגבילים במהלך צפייה במצב שמשתנה לעיתים קרובות
כשצופים במצבים של תכנים קומפוזביליים שמשתנים בתדירות גבוהה, כמו אנימציה
או scrollState
, יכולות להיות כמות משמעותית של הרכבים מחדש
בוצע. במקרה הזה, המשנים יוקצו לכל יצירה מחדש
ואולי גם לכל פריים:
@Composable fun LoadingWheelAnimation() { val animatedState = animateFloatAsState(/*...*/) LoadingWheel( // Creation and allocation of this modifier will happen on every frame of the animation! modifier = Modifier .padding(12.dp) .background(Color.Gray), animatedState = animatedState ) }
במקום זאת, אפשר ליצור את אותו מופע של הצירוף, לחלץ אותו ולהשתמש בו שוב ומעבירים אותו לתוכן הקומפוזבילי כך:
// Now, the allocation of the modifier happens here: val reusableModifier = Modifier .padding(12.dp) .background(Color.Gray) @Composable fun LoadingWheelAnimation() { val animatedState = animateFloatAsState(/*...*/) LoadingWheel( // No allocation, as we're just reusing the same instance modifier = reusableModifier, animatedState = animatedState ) }
חילוץ של מגבילי התאמה ללא היקף ושימוש חוזר בהם
אפשר לבטל את ההיקף של המגבילים או להגביל את ההיקף שלהם קומפוזבילי. במקרה של מקשי צירוף ללא היקף, אפשר לחלץ אותם בקלות מחוץ לחומרים קומפוזביליים כמשתנים פשוטים:
val reusableModifier = Modifier .fillMaxWidth() .background(Color.Red) .padding(12.dp) @Composable fun AuthorField() { HeaderText( // ... modifier = reusableModifier ) SubtitleText( // ... modifier = reusableModifier ) }
האפשרות הזו יכולה להיות שימושית במיוחד כשמשלבים אותה עם פריסות עצלניות. במרבית שתרצו שכל כמות הפריטים שלכם שעשויה להיות משמעותית בדיוק אותם מגבילי התאמה:
val reusableItemModifier = Modifier .padding(bottom = 12.dp) .size(216.dp) .clip(CircleShape) @Composable private fun AuthorList(authors: List<Author>) { LazyColumn { items(authors) { AsyncImage( // ... modifier = reusableItemModifier, ) } } }
חילוץ של ערכי שינוי היקף ושימוש בהם שוב
כשאתם מתמודדים עם מגבילי התאמה בהיקף של תכנים קומפוזביליים מסוימים, אתם יכולים לחלץ אותן לרמה גבוהה ככל האפשר ולהשתמש שוב במקרים הרלוונטיים:
Column(/*...*/) { val reusableItemModifier = Modifier .padding(bottom = 12.dp) // Align Modifier.Element requires a ColumnScope .align(Alignment.CenterHorizontally) .weight(1f) Text1( modifier = reusableItemModifier, // ... ) Text2( modifier = reusableItemModifier // ... ) // ... }
עליכם להעביר רק את רכיבי הצירוף שחולצו, עם היקף ההרשאות ילדים ישירים באותו היקף. ראו את הקטע בטיחות היקף ב- אפשר לקרוא פרטים נוספים על החשיבות של.
Column(modifier = Modifier.fillMaxWidth()) { // Weight modifier is scoped to the Column composable val reusableItemModifier = Modifier.weight(1f) // Weight will be properly assigned here since this Text is a direct child of Column Text1( modifier = reusableItemModifier // ... ) Box { Text2( // Weight won't do anything here since the Text composable is not a direct child of Column modifier = reusableItemModifier // ... ) } }
שרשור נוסף של מגבילי התאמה שחולצו
אפשר להמשיך לשרשר או להוסיף את שרשראות הצירוף שחולצו באמצעות שליחת קריאה ל
הפונקציה .then()
:
val reusableModifier = Modifier .fillMaxWidth() .background(Color.Red) .padding(12.dp) // Append to your reusableModifier reusableModifier.clickable { /*...*/ } // Append your reusableModifier otherModifier.then(reusableModifier)
רק חשוב לזכור שסדר המשנים חשוב!
מידע נוסף
אנחנו מספקים רשימה מלאה של מגבילי התאמה, עם את הפרמטרים וההיקפים שלהם.
לתרגול נוסף על אופן השימוש במקשי הצירוף, אפשר גם לעבור על פריסות בסיסיות ב-Compose codelab או עכשיו במאגר של Android.
כדי לקבל מידע נוסף על מגבילי התאמה מותאמים אישית וללמוד איך יוצרים אותם, אפשר לעיין את מסמכי העזרה בקטע פריסות מותאמות אישית - שימוש בתכונת השינוי של הפריסה.
מומלץ עבורך
- הערה: טקסט הקישור מוצג כאשר JavaScript מושבת
- העקרונות הבסיסיים של הפריסה
- פעולות עריכה {:#editor-actions}
- פריסות בהתאמה אישית {:#custom-layouts }