כדי לעדכן את פריסת האפליקציה, צריך סוגים שונים של מידע, כמו יכולות המכשיר וסטטוס האפליקציה. המידע הנפוץ ביותר הוא הרוחב והגובה של החלון. בנוסף, אפשר לעיין במידע הבא:
- תנוחת החלון
- דיוק של אמצעי הצבעה
- סוג מקלדת
- האם המכשיר תומך במצלמה ובמיקרופון
- המרחק בין המשתמש לבין מסך המכשיר
המידע מתעדכן באופן דינמי, ולכן צריך לעקוב אחריו ולהפעיל את ההרכבה מחדש בכל פעם שמתבצע עדכון.
הפונקציה mediaQuery מסתירה את הפרטים של אחזור המידע ומאפשרת לכם להתמקד בהגדרת התנאי להפעלת העדכונים של הפריסה.
בדוגמה הבאה, הפריסה משתנה ל-TabletopLayout כשמצב המכשיר המתקפל הוא 'על משטח, מסך למעלה':
@Composable fun VideoPlayer( // ... ) { // ... if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) { TabletopLayout() } else { FlatLayout() } // ... }
הפעלת הפונקציה mediaQuery
כדי להפעיל את הפונקציה mediaQuery, מגדירים את המאפיין isMediaQueryIntegrationEnabled של האובייקט ComposeUiFlags לערך true:
class MyApplication : Application() { override fun onCreate() { ComposeUiFlags.isMediaQueryIntegrationEnabled = true super.onCreate() } }
הגדרת תנאי עם פרמטרים
אפשר להגדיר תנאי כפונקציית lambda שמוערכת בתוך UiMediaScope.
הפונקציה mediaQuery מעריכה את התנאי בהתאם לסטטוס הנוכחי וליכולות המכשיר.
הפונקציה מחזירה ערך בוליאני, כך שאפשר לקבוע את הפריסה באמצעות הסתעפויות מותנות כמו ביטוי if.
בטבלה 1 מפורטים הפרמטרים שזמינים ב-UiMediaScope.
| פרמטר | סוג הערך | תיאור |
|---|---|---|
windowWidth |
Dp |
רוחב החלון הנוכחי ביחידות dp. |
windowHeight |
Dp |
גובה החלון הנוכחי ב-dp. |
windowPosture |
UiMediaScope.Posture |
המיקום הנוכחי של חלון האפליקציה. |
pointerPrecision |
UiMediaScope.PointerPrecision |
הדיוק הכי גבוה של מכשירי ההצבעה הזמינים. |
keyboardKind |
UiMediaScope.KeyboardKind |
סוג המקלדת שזמינה או מחוברת. |
hasCamera |
Boolean |
האם המכשיר תומך במצלמה. |
hasMicrophone |
Boolean |
האם המיקרופון נתמך במכשיר. |
viewingDistance |
UiMediaScope.ViewingDistance |
המרחק האופייני בין המשתמש למסך המכשיר. |
אובייקט UiMediaScope פותר את הערכים של הפרמטרים.
הפונקציה mediaQuery משתמשת ב-LocalUiMediaScope.current כדי לגשת לאובייקט UiMediaScope, שמייצג את היכולות וההקשר הנוכחיים של המכשיר.
האובייקט הזה מתעדכן באופן דינמי כשמתבצעים שינויים, למשל כשהמשתמש משנה את מצב המכשיר.
הפונקציה mediaQuery בודקת את הביטוי query lambda עם האובייקט UiMediaScope המעודכן ומחזירה ערך בוליאני.
לדוגמה, בקטע הקוד הבא מתבצעת בחירה בין TabletopLayout
לבין FlatLayout על סמך ערך הפרמטר windowPosture.
@Composable fun VideoPlayer( // ... ) { // ... if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) { TabletopLayout() } else { FlatLayout() } // ... }
קבלת החלטה על סמך גודל החלון
סיווגים של גודל חלון הם קבוצה של נקודות עצירה (breakpoints) מוגדרות מראש של אזור התצוגה, שעוזרות לכם לעצב, לפתח ולבדוק פריסות מותאמות.
אפשר להשוות בין שני הפרמטרים שמייצגים את גודל החלון הנוכחי לבין הסף שמוגדר במחלקות של גודל החלון.
בדוגמה הבאה, מספר החלוניות משתנה בהתאם לרוחב החלון.
בכיתה WindowSizeClass יש קבועים לספי הגודל של חלונות (איור 1).
הפונקציה derivedMediaQuery מחשבת את הביטוי query lambda ועוטפת את התוצאה ב-derivedStateOf.
מכיוון שהפונקציות windowWidth ו-windowHeight יכולות להתעדכן לעיתים קרובות, כשמפנים לפרמטרים האלה בפונקציית ה-lambda query, צריך להפעיל את הפונקציה derivedMediaQuery במקום את הפונקציה mediaQuery.
val narrowerThanMedium by derivedMediaQuery { windowWidth < WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND.dp } val narrowerThanExpanded by derivedMediaQuery { windowWidth < WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND.dp } when { narrowerThanMedium -> SinglePaneLayout() narrowerThanExpanded -> TwoPaneLayout() else -> ThreePaneLayout() }
עדכון הפריסה בהתאם למיקום החלון
הפרמטר windowPosture מתאר את המיקום הנוכחי של החלון כאובייקט UiMediaScope.Posture.
כדי לבדוק את התנוחה הנוכחית, משווים את הפרמטר לערכים שמוגדרים במחלקה UiMediaScope.Posture.
בדוגמה הבאה הפריסה משתנה בהתאם למיקום החלון:
when { mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout() }
בדיקת הדיוק של מכשיר ההצבעה הזמין
מכשיר הצבעה ברמת דיוק גבוהה עוזר למשתמשים להצביע על רכיב בממשק המשתמש בצורה מדויקת. רמת הדיוק של מכשיר ההצבעה תלויה בסוג המכשיר.
הפרמטר pointerPrecision מתאר את הדיוק של מכשירי ההצבעה הזמינים, כמו עכבר ומסך מגע.
יש ארבעה ערכים שמוגדרים במחלקה UiMediaScope.PointerPrecision: Fine, Coarse, Blunt ו-None.
None מציין שאין מכשיר הצבעה זמין.
הדיוק נע בין הגבוה ביותר לנמוך ביותר בסדר הזה:
Fine, Coarse ו-Blunt.
אם יש כמה מכשירי הצבעה והדיוק שלהם שונה,
הפרמטר נפתר עם הדיוק הגבוה ביותר.
לדוגמה, אם יש שני מכשירי הצבעה – מכשיר Fine מדויק ומכשיר Blunt מדויק – Fine הוא הערך של הפרמטר pointerPrecision.
בדוגמה הבאה מוצג לחצן גדול יותר כשהמשתמש משתמש במכשיר הצבעה עם דיוק נמוך:
if (mediaQuery { pointerPrecision == UiMediaScope.PointerPrecision.Blunt }) { LargeSizeButton() } else { NormalSizeButton() }
בדיקת סוג המקלדת הזמין
הפרמטר keyboardKind מייצג את סוג המקלדות הזמינות:
Physical, Virtual ו-None.
אם מוצגת מקלדת וירטואלית ובמקביל יש מקלדת פיזית, הפרמטר יקבל את הערך Physical.
אם אף אחד מהם לא מזוהה, הערך של הפרמטר הוא None.
בדוגמה הבאה מוצגת הודעה שמופיעה למשתמשים כשלא מזוהה מקלדת, עם הצעה לחבר מקלדת:
if (mediaQuery { keyboardKind == UiMediaScope.KeyboardKind.None }) { SuggestKeyboardConnect() }
בדיקה אם המכשיר תומך במצלמה ובמיקרופון
חלק מהמכשירים לא תומכים במצלמות או במיקרופונים.
אפשר לבדוק אם המכשיר תומך במצלמה ובמיקרופון באמצעות הפרמטרים hasCamera ו-hasMicrophone.
בדוגמה הבאה מוצגים כפתורים לשימוש במצלמה ובמיקרופון כשהמכשיר תומך בהם:
Row { OutlinedTextField(state = rememberTextFieldState()) // Show the MicButton when the device supports a microphone. if (mediaQuery { hasMicrophone }) { MicButton() } // Show the CameraButton when the device supports a camera. if (mediaQuery { hasCamera }) { CameraButton() } }
שינוי ממשק המשתמש בהתאם למרחק הצפייה המשוער
מרחק הצפייה הוא גורם שעוזר לקבוע את הפריסה.
אם המשתמש משתמש באפליקציה מרחוק,
הוא מצפה שהטקסט ורכיבי ממשק המשתמש יהיו גדולים יותר.
הפרמטר viewingDistance מספק הערכה של מרחק הצפייה על סמך סוג המכשיר וההקשר האופייני של השימוש בו.
יש שלושה ערכים שמוגדרים במחלקה UiMediaScope.ViewingDistance:
Near, Medium ו-Far.
Near מציין שהמסך נמצא בטווח קרוב, ו-Far מציין שצופים במכשיר מרחוק.
בדוגמה הבאה, גודל הגופן גדל כשהמרחק מהמסך הוא Far או Medium:
val fontSize = when { mediaQuery { viewingDistance == UiMediaScope.ViewingDistance.Far } -> 20.sp mediaQuery { viewingDistance == UiMediaScope.ViewingDistance.Medium } -> 18.sp else -> 16.sp }
תצוגה מקדימה של רכיב ממשק משתמש
אפשר לקרוא לפונקציות mediaQuery ו-derivedMediaQuery בפונקציות שניתנות להרכבה כדי לראות תצוגה מקדימה של רכיבי ממשק המשתמש.
הקטע הבא בוחר בין TabletopLayout
לבין FlatLayout על סמך ערך הפרמטר windowPosture.
כדי לראות תצוגה מקדימה של TabletopLayout, הפרמטר windowPosture צריך להיות UiMediaScope.Posture.Tabletop.
when { mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout() }
הפונקציות mediaQuery ו-derivedMediaQuery מחשבות את הביטוי query למדה שצוין באובייקט UiMediaScope, שמועבר כ-LocalUiMediaScope.current.
כדי לשנות את הגדרת ברירת המחדל, פועלים לפי השלבים הבאים:
- מפעילים את הפונקציה
mediaQuery. - מגדירים אובייקט בהתאמה אישית שמטמיע את הממשק
UiMediaScope. - מגדירים את האובייקט המותאם אישית ל-
LocalUiMediaScopeבאמצעות הפונקציהCompositionLocalProvider. - קוראים לרכיב הקומפוזבילי כדי להציג תצוגה מקדימה בלמדה של התוכן של הפונקציה
CompositionLocalProvider.
בדוגמה הבאה אפשר לראות תצוגה מקדימה של TabletopLayout:
@Preview @Composable fun PreviewLayoutForTabletop() { // Step 1: Enable the mediaQuery function ComposeUiFlags.isMediaQueryIntegrationEnabled = true val currentUiMediaScope = LocalUiMediaScope.current // Step 2: Define a custom object implementing the UiMediaScope interface. // The object overrides the windowPosture parameter. // The resolution of the remaining parameters is deferred to the currentUiMediaScope object. val uiMediaScope = remember(currentUiMediaScope) { object : UiMediaScope by currentUiMediaScope { override val windowPosture: UiMediaScope.Posture = UiMediaScope.Posture.Tabletop } } // Step 3: Set the object to the LocalUiMediaScope. CompositionLocalProvider(LocalUiMediaScope provides uiMediaScope) { // Step 4: Call the composable to preview. when { mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout() } } }