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