מגבילי התאמה מאפשרים לכם לקשט או לשפר תוכן קומפוזבילי. בעזרת המשתנים המשתנים תוכלו לבצע את הפעולות הבאות:
- שינוי הגודל, הפריסה, ההתנהגות והמראה של התוכן הקומפוזבילי
- הוספת מידע, כמו תוויות נגישות
- עיבוד קלט של משתמשים
- הוספת אינטראקציות ברמה גבוהה, כמו הפיכת אלמנט לקליקבילי, לגלילה, לגרירה או להגדלת התצוגה שלו
משתני פונקציה הם אובייקטים רגילים של 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
כברירת מחדל, פריסות שסופקו ב-Compose עוטפות את הצאצאים שלהן. עם זאת, אפשר להגדיר גודל באמצעות המשתנה 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 לא משנה את המדידות שלו:
@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.
כדי לקבל מידע מעמיק יותר על המקרים שבהם כדאי להשתמש בכל אחת מהאפשרויות האלה ואיך לבצע אופטימיזציה
לביצועים, לקרוא
ביצועי כתיבה – דחיית הקריאה כמה שיותר זמן.
אבטחת היקף ב-Compose
ב-Compose יש משתני אופן (modifiers) שאפשר להשתמש בהם רק כשהם חלים על צאצאים של רכיבים מסוימים ליצירה. Compose אוכף את הכלל הזה באמצעות היקפים מותאמים אישית.
לדוגמה, אם רוצים להגדיר ילד או ילדה בגודל של הורה 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
כפי שראיתם בקטע הקודם בנושא הגדרת שוליים וגודלים, כברירת מחדל, הגודל של רכיב שאפשר ליצור ממנו קומפוזיציות מוגדר לפי התוכן שהוא עוטף. אפשר להגדיר את הגודל של תוכן קומפוזבילי כך שיהיה גמיש בתוך האב שלו באמצעות המשתנה 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 ) }
חילוץ של מגבילי התאמה ללא היקף ושימוש חוזר בהם
אפשר לבטל את ההיקף של המשתנים המשתנים או להגדיר את ההיקף שלהם ל-composable ספציפי. במקרה של משתני מודיפיקטור ללא היקף, אפשר לחלץ אותם בקלות מחוץ לרכיבים הניתנים לשילוב כמשתנים פשוטים:
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 }