ב-Compose, אפשר לשרשר יחד כמה משתני אופן פעולה כדי לשנות את המראה והתחושה של רכיב ה-Composable. שרשרות המשתנים האלה יכולות להשפיע על המגבלות שמועברות לרכיבים הניתנים לשילוב, שמגדירות את גבולות הגובה והרוחב.
בדף הזה נסביר איך משתני שרשרת משפיעים על אילוצים, ובתגובה על המדידה והמיקום של נכסי ה-Compose.
גורמי שינוי בעץ של ממשק המשתמש
כדי להבין איך המשתנים המשתנים משפיעים זה על זה, כדאי להציג אותם באופן חזותי בעץ של ממשק המשתמש שנוצר בשלב היצירה. למידע נוסף, קראו את הקטע הרכב.
בעץ של ממשק המשתמש, אפשר לראות את המשתנים כצומתי עטיפה לצמתי הפריסה:

הוספת יותר ממאפיין אחד של שינוי לרכיב מורכב יוצרת שרשרת של מאפייני שינוי. כשמחברים יחד כמה משתני אופן פעולה, כל צומת של משתנה אופן פעולה עוטף את שאר השרשרת ואת צומת הפריסה בתוכו. לדוגמה, כשמחברים יחד את המשתנה המשנה clip
עם המשתנה המשנה size
, צומת המשתנה המשנה clip
עוטף את צומת המשתנה המשנה size
, שעוטר את צומת הפריסה Image
.
בשלב הפריסה, האלגוריתם שמבצע סריקה של העץ נשאר ללא שינוי, אבל כל צומת של שינוי עובר גם הוא ביקורת. כך, המשתנה המשנה יכול לשנות את דרישות הגודל והמיקום של המשתנה המשנה או של צומת הפריסה שהוא עוטף.
כפי שמוצג באיור 2, ההטמעה של הרכיבים הניתנים לקישור Image
ו-Text
מורכבת משרשרת של מודיפיקרים שמקיפים צומת פריסה יחיד. ההטמעות של Row
ו-Column
הן פשוט צמתים של פריסה שמתארים איך למקם את הצאצאים שלהם.

לסיכום:
- מודификаторים עוטפים מודификатор יחיד או צומת פריסה יחיד.
- צמתים של פריסה יכולים לפרס כמה צמתים צאצאים.
בקטעים הבאים נסביר איך להשתמש במודל המנטלי הזה כדי להבין את השרשרת של המשתנים המשתנים ואת ההשפעה שלה על הגודל של הרכיבים הניתנים לקישור.
אילוצים בשלב הפריסה
בשלב הפריסה, המערכת פועלת לפי אלגוריתם בן שלושה שלבים כדי למצוא את הרוחב, הגובה והקואורדינטות x ו-y של כל צומת בפריסה:
- מדידת הצאצאים: צומת מודד את הצאצאים שלו, אם יש כאלה.
- קביעת הגודל בעצמו: על סמך המדידות האלה, הצומת קובע את הגודל שלו.
- מיקום הצאצאים: כל צומת צאצא ממוקם ביחס למיקום של הצומת עצמו.
Constraints
עוזרים למצוא את הגדלים המתאימים לצמתים בשני השלבים הראשונים של האלגוריתם. האילוצים מגדירים את הגבולות המינימליים והמקסימליים של רוחב הגובה של הצומת. כשהצומת מחליט על הגודל שלו, הגודל שנמדד אמור להיכלל בטווח הגודל הזה.
סוגי האילוצים
אילוץ יכול להיות אחד מהאפשרויות הבאות:
- מוגבל: לצומת יש רוחב וגובה מקסימליים ומינימליים.

- ללא הגבלת גודל: הצומת לא מוגבל לגודל מסוים. גבולות הגובה והרוחב המקסימליים מוגדרים כ'ללא הגבלה'.

- מדויק: הצומת מתבקש לעמוד בדרישת גודל מדויקת. הערכים המינימלי והמקסימלי מוגדרים לאותו ערך.

- שילוב: הצומת פועל לפי שילוב של סוגי האילוצים שלמעלה. לדוגמה, אילוץ יכול להגביל את הרוחב תוך מתן גובה מקסימלי ללא הגבלה, או להגדיר רוחב מדויק אבל לספק גובה מוגבל.

בקטע הבא מוסבר איך האילוצים האלה מועברים מהורה לצאצא.
איך האילוצים מועברים מהרכיב ההורה לרכיב הצאצא
בשלב הראשון של האלגוריתם שמתואר בקטע אילוצים בשלב הפריסה, האילוצים מועברים מהרכיב ההורה לרכיב הצאצא בעץ ממשק המשתמש.
כשצומת הורה מודד את הצמתים הצאצאים שלו, הוא מעביר את האילוצים האלה לכל צומת צאצא כדי להודיע לו כמה גדול או קטן הוא יכול להיות. לאחר מכן, כשהיא מחליטה על הגודל שלה, היא גם פועלת בהתאם למגבלות שהועברו על ידי ההורים שלה.
באופן כללי, האלגוריתם פועל באופן הבא:
- כדי לקבוע את הגודל שהוא רוצה לתפוס, צומת הבסיס בעץ ממשק המשתמש מודד את הצאצאים שלו ומעביר את אותן אילוצים לצאצא הראשון שלו.
- אם הצאצא הוא שינוי שלא משפיע על המדידה, הוא מעביר את האילוצים לשינוי הבא. האילוצים מועברים במורד שרשרת המשתנים כפי שהם, אלא אם מגיעים למשתנה שמשפיע על המדידה. לאחר מכן, המערכת תשנה את הגודל של האילוצים בהתאם.
- כשמגיעים לצומת שאין לו צאצאים (נקרא "צומת עלה"), הוא מחליט על הגודל שלו על סמך האילוצים שהועברו, ומחזיר את הגודל המחושב להורה שלו.
- הורה מתאים את האילוצים שלו על סמך המדידות של הצאצא הזה, ומפעיל את הצאצא הבא עם האילוצים המותאמים האלה.
- אחרי שכל הצאצאים של הצומת ההורה נמדדים, הצומת ההורה מחליט על הגודל שלו ומעביר את המידע הזה לצומת ההורה שלו.
- כך כל העץ עובר סריקה לפי עומק. בסופו של דבר, כל הצמתים מחליטים על הגדלים שלהם, ושלב המדידה מסתיים.
לדוגמה מפורטת, אפשר לצפות בסרטון Constraints and modifier order.
משתני אופן פעולה שמשפיעים על אילוצים
בקטע הקודם למדתם שחלק מהמפעילים יכולים להשפיע על גודל האילוצים. בקטעים הבאים מתוארים משתני אופן ספציפיים שמשפיעים על האילוצים.
המשתנה size
המאפיין size
מציין את הגודל המועדף של התוכן.
לדוגמה, יש ליצור את עץ ממשק המשתמש הבא בקונטיינר של 300dp
על ידי 200dp
. האילוצים מוגבלים, ומאפשרים רוחב בין 100dp
ל-300dp
וגובה בין 100dp
ל-200dp
:

המשתנה המשנה size
מתאים את האילוצים הנכנסים כך שיתאימו לערך שהוענק לו.
בדוגמה הזו, הערך הוא 150dp
:

size
שמתאים את האילוצים ל-150dp
.אם הרוחב והגובה קטנים מהגבול הקטן ביותר של האילוצים, או גדולים מהגבול הגדול ביותר של האילוצים, המשתנה המשנה יתאים לאילוצים שהועברו בצורה הקרובה ביותר האפשרית תוך שמירה על האילוצים שהועברו:

size
שעומד במגבלה שהועברה בצורה הקרובה ביותר.חשוב לזכור ששרשור של כמה משתני size
לא עובד. המשתנה המשנה הראשון size
מגדיר את המגבלות המינימליות והמקסימליות לערך קבוע. גם אם המשתנה השני של הגודל ידרוש גודל קטן או גדול יותר, הוא עדיין צריך לציית לגבולות המדויקים שהועברו, כך שהוא לא יחליף את הערכים האלה:

size
, שבה הערך השני שהוענק (50dp
) לא מבטל את הערך הראשון (100dp
).המשתנה requiredSize
אם אתם רוצים שהצומת יבטל את האילוצים הנכנסים, צריך להשתמש במערך requiredSize
במקום ב-size
. המשתנה המשנה requiredSize
מחליף את האילוצים הנכנסים ומעביר את הגודל שציינתם כגבולות מדויקים.
כשהגודל מועבר בחזרה למעלה בעץ, הצומת הצאצא ממורכז במרחב הזמין:

requiredSize
מבטל את האילוצים הנכנסים מהמאפיין size
.המשתנים width
ו-height
המשתנה המשנה size
מתאים את הרוחב והגובה של האילוצים. בעזרת המשתנה המשנה width
אפשר להגדיר רוחב קבוע אבל להשאיר את הגובה לא מוגדר.
באופן דומה, בעזרת המאפיין height
אפשר להגדיר גובה קבוע, אבל להשאיר את הרוחב לא מוגדר:

width
והמאפיין height
, שמגדירים רוחב וגובה קבועים, בהתאמה.המשתנה sizeIn
בעזרת המאפיין sizeIn
אפשר להגדיר מגבלות מדויקות של רוחב וגובה. אם אתם צריכים שליטה מפורטת על האילוצים, השתמשו במערך המשתנים sizeIn
.

sizeIn
עם הערכים minWidth
, maxWidth
, minHeight
ו-maxHeight
.דוגמאות
בקטע הזה מוצגים כמה קטעי קוד עם משתני משנה בשרשור, ומוסבר מהו הפלט שלהם.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .fillMaxSize() .size(50.dp) )
קטע הקוד הזה יוצר את הפלט הבא:
- המאפיין
fillMaxSize
משנה את האילוצים כך שהרוחב והגובה המינימליים יוגדרו לערך המקסימלי –300dp
ברוחב ו-200dp
בגובה. - גם אם המשתנה המשנה
size
רוצה להשתמש בגודל50dp
, הוא עדיין צריך לעמוד באילוצים המינימליים הנכנסים. לכן, המשתנה המשנהsize
יפיק גם את גבולות האילוצים המדויקים של300
לפי200
, ובאופן מעשי יתעלם מהערך שסופק במשתנה המשנהsize
. Image
פועל לפי המגבלות האלה ומדווח על גודל של300
על200
, שמועברים עד לחלק העליון של העץ.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .fillMaxSize() .wrapContentSize() .size(50.dp) )
קטע הקוד הזה יוצר את הפלט הבא:
- המאפיין המשנה
fillMaxSize
מתאים את האילוצים כך שהרוחב והגובה המינימליים יהיו שווים לערך המקסימלי –300dp
ברוחב ו-200dp
בגובה. - המשתנה המשנה
wrapContentSize
מאפס את האילוצים המינימליים. לכן, בעוד ש-fillMaxSize
גרם להגבלות קבועות,wrapContentSize
מאפס אותו חזרה להגבלות מוגבלות. הצומת הבא יכול עכשיו לתפוס שוב את כל המרחב, או להיות קטן יותר מהמרחב כולו. - המאפיין
size
מגדיר את המגבלות לגבולות המינימום והמקסימום של50
. - הערך של
Image
מוגדר לגודל50
על50
, והתוסףsize
מעביר את הערך הזה. - למשתנה
wrapContentSize
יש מאפיין מיוחד. הוא לוקח את הצאצא שלו ומקם אותו במרכז של גבולות המינימום הזמינים שהועברו אליו. לכן, הגודל שהוא מעביר להורים שלו שווה למגבלות המינימליות שהועברו אליו.
שילוב של שלושה מודיפיקרים בלבד מאפשר להגדיר את הגודל של הרכיב הניתן לקיבוץ ולמקם אותו במרכז הרכיב ההורה.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .clip(CircleShape) .padding(10.dp) .size(100.dp) )
קטע הקוד הזה יוצר את הפלט הבא:
- המשתנה
clip
לא משנה את האילוצים.- המאפיין
padding
מקטין את האילוצים המקסימליים. - המקש
size
מגדיר את כל האילוצים ל-100dp
. - המאפיין
Image
מציית למגבלות האלה ומדווח על גודל של100
על100dp
. - המשתנה
padding
מוסיף10dp
לכל הגדלים, כך שהוא מגדיל את הרוחב והגובה שמדווחים ב-20dp
. - בשלב הציור, מקש המקש
clip
פועל על לוח של120
לפי120dp
. לכן, יוצרים מסכה עגולה באותו גודל. - לאחר מכן, המשתנה המשנה
padding
גורם להכנסת התוכן שלו ב-10dp
בכל הגדלים, כך שהוא מקטין את גודל ההדפסה על קנבס ל-100
ב-100dp
. - ה-
Image
מצויר בלוח הציור הזה. התמונה נחתכת על סמך העיגול המקורי של120dp
, כך שהפלט הוא תוצאה לא עגולה.
- המאפיין