ב-Compose, אפשר לשרשר כמה משנים כדי לשנות את המראה והתחושה של רכיב שאפשר להוסיף. שרשראות של מגדירי מאפיינים יכולות להשפיע על האילוצים שמועברים לרכיבים הניתנים להרכבה, שמגדירים את הגבולות של הרוחב והגובה.
בדף הזה מוסבר איך מגבילים משורשרים משפיעים על אילוצים, ובתורם על המדידה והמיקום של רכיבים הניתנים להרכבה.
גורמי שינוי בעץ ממשק המשתמש
כדי להבין איך משנים משפיעים אחד על השני, כדאי לראות איך הם מופיעים בעץ ממשק המשתמש שנוצר במהלך שלב ההרכבה. מידע נוסף זמין בקטע הרכב.
בעץ ממשק המשתמש, אפשר לראות את שינויי התצוגה כצמתי wrapper עבור צמתי הפריסה:
אם מוסיפים יותר משינוי אחד לרכיב שאפשר להרכיב, נוצרת שרשרת של שינויים. כשמשרשרים כמה משנים, כל צומת משנה עוטף את שאר השרשרת ואת צומת הפריסה בתוכו. לדוגמה, כשמשרשרים משנה clip ומשנה size, צומת המשנה clip עוטף את צומת המשנה size, שבתורו עוטף את צומת הפריסה Image.
בשלב הפריסה, האלגוריתם שסורק את העץ נשאר זהה, אבל כל צומת של משנה עובר ביקור גם כן. כך, משנה יכול לשנות את דרישות הגודל והמיקום של המשנה או של צומת הפריסה שהוא עוטף.
כפי שמוצג באיור 2, ההטמעה של הרכיבים הקומפוזביליים Image ו-Text מורכבת משרשרת של משנים שעוטפים צומת פריסה יחיד.
ההטמעות של Row ושל Column הן צמתי פריסה שמתארים איך לפרוס את הצמתים הצאצאים שלהם.
לסיכום:
- המאפיינים לשינוי מקיפים מאפיין לשינוי יחיד או צומת פריסה.
- צמתי פריסה יכולים לפרוס כמה צמתי צאצא.
בקטעים הבאים מוסבר איך להשתמש במודל המנטלי הזה כדי להבין את שרשור שינויי המאפיינים ואת ההשפעה שלו על הגודל של רכיבי ה-Composable.
אילוצים בשלב הפריסה
בשלב הפריסה, אלגוריתם בן שלושה שלבים מוצא את הרוחב, הגובה וקואורדינטות ה-x וה-y של כל צומת פריסה:
- מדידת ילדים: צומת מודד את הילדים שלו, אם יש כאלה.
- קביעת גודל עצמאי: על סמך המידות האלה, הצומת קובע את הגודל שלו.
- מיקום ילדים: כל צומת צאצא ממוקם ביחס למיקום של הצומת עצמו.
Constraints עוזרים למצוא את הגדלים הנכונים של הצמתים במהלך שני השלבים הראשונים של האלגוריתם. האילוצים מגדירים את הגבולות המינימליים והמקסימליים של הרוחב והגובה של צומת. כשצומת מחליט על הגודל שלו, הגודל הנמדד שלו צריך להיות בטווח הגדלים הזה.
סוגים של אילוצים
אילוצים יכולים להיות אחד מהסוגים הבאים:
- מוגבל: ל-node יש רוחב וגובה מקסימליים ומינימליים.
- Unbounded: הגודל של הצומת לא מוגבל. הגבולות המקסימליים של הרוחב והגובה מוגדרים כאינסוף.
- מדויק: הצומת מתבקש לפעול לפי דרישת גודל מדויקת. הגבולות המינימלי והמקסימלי מוגדרים לאותו ערך.
- שילוב: הצומת פועל לפי שילוב של סוגי האילוצים הקודמים. לדוגמה, אפשר להגביל את הרוחב ולאפשר גובה מקסימלי לא מוגבל, או להגדיר רוחב מדויק אבל לספק גובה מוגבל.
בקטע הבא מוסבר איך ההגבלות האלה מועברות מהורה לצאצא.
איך אילוצים מועברים מרכיב ראשי לרכיב משני
בשלב הראשון של האלגוריתם שמתואר בקטע Constraints in the layout phase, האילוצים מועברים מהרכיב האב לרכיב הבן בעץ ממשק המשתמש.
כשצומת אב מודד את צאצאיו, הוא מספק את האילוצים האלה לכל צאצא כדי להודיע לו מה הגודל המקסימלי או המינימלי שלו. לאחר מכן, כשהוא מחליט על הגודל שלו, הוא פועל בהתאם למגבלות שהועברו אליו על ידי רכיבי ההורה שלו.
באופן כללי, האלגוריתם פועל כך:
- כדי להחליט על הגודל שהוא רוצה לתפוס, צומת הבסיס בעץ ממשק המשתמש מודד את צאצאיו ומעביר את אותן מגבלות לצאצא הראשון שלו.
- אם רכיב ה-child הוא modifier שלא משפיע על המדידה, הוא מעביר את האילוצים אל ה-modifier הבא. האילוצים מועברים בשרשרת של משני המדידה כמו שהם, אלא אם מגיעים למשנה מדידה שמשפיע על המדידה. לאחר מכן, המערכת משנה את הגודל של האילוצים בהתאם.
- אחרי שמגיעים לצומת שאין לו צאצאים (שנקרא 'צומת עלה'), הוא מחליט על הגודל שלו על סמך האילוצים שהועברו, ומחזיר את הגודל הזה להורה שלו.
- האב מתאים את האילוצים שלו על סמך המידות של הצאצא הזה, וקורא לצאצא הבא שלו עם האילוצים המותאמים האלה.
- אחרי שמודדים את כל הילדים של הורה מסוים, צומת ההורה מחליט על הגודל שלו ומודיע על כך להורה שלו.
- כך מתבצעת סריקה של כל העץ לעומק. בסופו של דבר, כל הצמתים מחליטים על הגדלים שלהם, ושלב המדידה מסתיים.
דוגמה מפורטת מופיעה בסרטון אילוצים וסדר שינויים.
משנים שמשפיעים על אילוצים
בקטע הקודם למדתם שחלק מהמשנים יכולים להשפיע על גודל האילוץ. בקטעים הבאים מתוארים משנים ספציפיים שמשפיעים על אילוצים.
הערך המקדם 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) )
קטע הקוד הזה יוצר את הפלט הבא:
Image מתמלא כתוצאה משרשרת המשנים.- המשנה
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) )
קטע הקוד הזה יוצר את הפלט הבא:
Image ממוקם במרכז וגודלו 50dp.- המשנה
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פועלת בהתאם למגבלות האלה ומחזירה את הגודל100dpעל100dp. - המשנה
paddingמוסיף10dpלכל הצדדים של הגודל שמדווח על ידי התגImage, כך שהפריסה עם הריווח מדווחת על רוחב וגובה של120dp. - עכשיו, בשלב הציור, מקש הצירוף
clipפועל על בד ציור בגודל120dpעל120dp. הוא יוצר מסכת עיגול בגודל הזה. - המשנה
paddingמוסיף ריווח פנימי של10dpלכל הצדדים של התוכן, וכך מקטין את גודל אזור הציור שלImageל-100dpעל100dp. - הציור של
Imageמתבצע בקנבס הקטן הזה. התמונה נחתכת על סמך העיגול המקורי של120dp, ולכן הפלט הוא לא עיגול.