התאמת ממשק המשתמש לשורת הסטטוס של המערכת

עד Wear OS 7 (API 37), הפלטפורמה לא הציגה שורת סטטוס של המערכת מעל חלונות האפליקציה – האפליקציות שלטו בכל המסך ויכלו להציג כל תוכן בחלק העליון (השעה 12:00) (למשל שעון TimeText בתוך האפליקציה, כותרות מעוקלות בהתאמה אישית או אמצעי בקרה בחלק העליון).

החל מ-Wear OS 8 – וזמינה עכשיו לבדיקה בגרסת טרום-השקה מוקדמת באמולטור של גרסת טרום-השקה בטא של Wear OS 7.1 (API 37.2-beta1) – המערכת מעבדת שורת סטטוס מעל חלונות האפליקציה במיקום של השעה 12:00 כדי להציג את השעה ואת אינדיקטורי הסטטוס. כדי למנוע חפיפה עם שורת הסטטוס של המערכת, האפליקציות צריכות להפסיק להציג שעון משלהן (TimeText) ולכבד את השוליים של חלון שורת הסטטוס העליונה (מטופל באופן אוטומטי על ידי AppScaffold ו-ScreenScaffold מ-Wear Compose בגרסה 1.8 ואילך), או להסתיר את שורת הסטטוס של המערכת כשנדרשת חוויה סוחפת במסך מלא.

שורת הסטטוס של המערכת ב-Wear OS 8
תרשים 1. שורת הסטטוס של המערכת ב-Wear OS 8.

אלה חלק מהיתרונות המרכזיים שלהם:

  • עקביות חזותית: משפחת גופנים, מיקום ורקע אחידים לשעון בכל המערכת ובכל האפליקציות.
  • אינדיקטורים של סטטוס המערכת: מאפשרים לפלטפורמה להציג סמלי סטטוס (כמו אינדיקטורים של מיקרופון ומיקום פעילים, סטטוס קישוריות או מידע על הסוללה) ואת השעה בממשקים שונים. בכל פעם מוצג רק סמל אחד, לפי סדר העדיפות.
  • תיאום אוטומטי של גלילה ומעבר: בשילוב עם Jetpack Compose ל-Wear OS 1.8, שורת הסטטוס של המערכת מוסתרת באופן אוטומטי כשהמשתמשים גוללים בתוכן, ומופיעה שוב אחרי השהיה קצרה (שתי שניות) של חוסר פעילות.

הגדרת האפליקציה

כדי להתחיל, צריך לבצע את השלבים הבאים:

  1. מתקינים את Android Studio Preview (Canary).
  2. ב-SDK Manager, מורידים את קובץ האימג' של מערכת האמולטור של גרסת טרום-ההשקה של Wear OS 7.1 (API 37.2-beta1). הגרסה הזו מספקת גישה מוקדמת לשורת הסטטוס של מערכת Wear OS 8 לפני Wear OS 8 SDK.
  3. ב-Device Manager, יוצרים ומפעילים מכשיר וירטואלי של Wear OS באמצעות קובץ האימג' API 37.2-beta1.

כדי לתמוך בשורת הסטטוס של המערכת באפליקציה, צריך לעדכן את גרסת targetSdk של האפליקציה ל-35 ומעלה. כדי לשמור על תאימות לדורות קודמים של אפליקציות, הפלטפורמה מפעילה את שורת הסטטוס של המערכת רק באפליקציות שמטרגטות את API 35 ואילך. בנוסף, מעדכנים את יחסי התלות של Wear Compose לגרסת האלפא האחרונה – כרגע 1.8.0-alpha03 – כמו שמוצג בקטע הקוד הבא. אם באפליקציה שלכם מותקנת גרסה ישנה יותר של Wear Compose, אתם יכולים להשתמש במיומנות המעבר ל-Wear Compose Material 3 כדי להקל על המעבר.

android {
    defaultConfig {
        targetSdk = 35
    }
}

dependencies {
    implementation("androidx.wear.compose:compose-foundation:1.8.0-alpha03")
    implementation("androidx.wear.compose:compose-material3:1.8.0-alpha03")
}

שימוש בשורת הסטטוס של המערכת

בגרסת האלפא האחרונה של Wear Compose Material 3 1.8.0 (כרגע 1.8.0-alpha03), הספרייה מצרפת את האפליקציה באופן אוטומטי על ידי מיזוג המאפיין com.google.wear.ENABLE_GLOBAL_STATUS_BAR <meta-data> עם AndroidManifest.xml. בזמן הריצה, AppScaffold ו-ScreenScaffold בודקים אם שורת הסטטוס של המערכת מופעלת במכשיר ואם מאפיין ההצטרפות הזה במניפסט מוגדר ל-true:

  • באמולטור של גרסת טרום-ההשקה / Wear OS 8 ואילך (אם הצטרפתם): AppScaffold מבטל את TimeText הפנימי שלו כדי ששורת הסטטוס של המערכת תופיע בצורה נקייה במיקום של השעה 12:00 בלי כפילויות. ScreenScaffold מחשב מחדש את contentPadding כדי להביא בחשבון את גבולות ההוספה של שורת הסטטוס, ומתאם את ההסתרה וההצגה של שורת הסטטוס בזמן הגלילה ברשימה.
  • במכשירים עם Wear OS 7 וגרסאות קודמות (או כשלא מצטרפים): AppScaffold חוזר אוטומטית לעיבוד של TimeText הרגיל בתוך האפליקציה, ושומר על תאימות לדורות קודמים מבסיס קוד יחיד.

@Composable
fun GsbSampleApp() {
    // AppScaffold coordinates the system status bar across the app
    // and falls back to rendering TimeText on Wear OS 7 and earlier.
    AppScaffold {
        val columnState = rememberTransformingLazyColumnState()

        // ScreenScaffold includes status bar top inset clearance in
        // contentPadding and hides/shows the status bar during list scrolling.
        ScreenScaffold(scrollState = columnState) { contentPadding ->
            TransformingLazyColumn(
                state = columnState,
                contentPadding = contentPadding,
            ) {
                item {
                    ListHeader { Text("Hello Status Bar") }
                }
                items(count = 15) { index ->
                    Button(onClick = { /* Handle click */ }) {
                        Text("Item #${index + 1}")
                    }
                }
            }
        }
    }
}

זה מה שצפוי לקרות כשמריצים את הדוגמה:

  • במצב מנוחה (בראש הרשימה): שורת הסטטוס של המערכת מוצגת במיקום של השעה 12:00. הכותרת "Hello Status Bar" ממוקמת מתחת לאזור של שורת הסטטוס, בלי חיתוך או חפיפה.
  • גלילה למטה: כשגוללים בין הפריטים ברשימה, שורת הסטטוס מוסתרת והפריטים ברשימה נגללים מקצה לקצה מאחורי המסגרת העליונה.
  • במצב חוסר פעילות: כשמפסיקים לגלול ומשחררים את המסך, שורת הסטטוס מופיעה שוב באופן אוטומטי אחרי כ-2 שניות.

טיפול בתרחישים נפוצים ובהתאמות אישיות

בקטעים הבאים מוסבר איך לטפל בתרחישים נפוצים שבהם אתם עשויים להיתקל כשאתם עובדים עם שורת הסטטוס של המערכת.

טיפול במסכים ללא גלילה (סטטיים)

במסכים שמשתמשים בפריסה סטטית (כמו Column או Box) במקום ברשימה שניתן לגלול, צריך להחיל את contentPadding שסופק על ידי ScreenScaffold על פריסת הבסיס כדי שרכיבי ממשק המשתמש העליונים לא יחפפו לשורת הסטטוס של המערכת:

AppScaffold {
    ScreenScaffold { contentPadding ->
        Column(modifier = Modifier.padding(contentPadding)) {
            Text("Static Screen Content")
        }
    }
}

עבודה עם רכיבים אינטראקטיביים במסך מלא

רכיבים אינטראקטיביים במסך מלא ב-Wear Compose Material 3 – כולל AlertDialog,‏ Dialog,‏ Stepper,‏ TimePicker ו-DatePicker – מסתירים באופן אוטומטי את שורת הסטטוס של המערכת כשהם מוצגים במסך, כדי שלפקדים שלהם תהיה גישה מלאה לחלק העליון של התצוגה המעגלית. כשסוגרים את המסך, שורת הסטטוס של המערכת משוחזרת באופן אוטומטי באמצעות ה-API של הבקר של WindowInsets.

מעבר למצב אימרסיבי

כדי לעבור למצב אימרסיבי – שבו גם שורת הסטטוס של המערכת וגם TimeText המקומי מוסתרים – צריך להחיל את המשתנה Modifier.suppressStatusBar על האפליקציה, המסך או הרכיב. שמרו את המצב האימרסיבי למסכים שהמשתמש רואה לזמן קצר (שכבות-על לאישור, תיבות דו-שיח) או למסכים שמשתמשים בכל התצוגה (אינדיקטורים של התקדמות במסך מלא).

מתי כדאי להשתמש במצב אימרסיבי ברמת המסך

אם רק מסך ספציפי באפליקציה צריך להיות במסך מלא או במצב סוחף, צריך להחיל את Modifier.suppressStatusBar על ScreenScaffold. כשהמסך הזה פעיל, ScreenScaffold מסתיר אוטומטית את שורת הסטטוס של המערכת ומכווץ את המרווח הפנימי של שורת הסטטוס העליונה ל-0.dp. כשעוברים חזרה למסכים אחרים, ScreenScaffold משחזר את שורת הסטטוס של המערכת:

AppScaffold {
    ScreenScaffold(modifier = Modifier.suppressStatusBar()) { contentPadding ->
        Box(modifier = Modifier.fillMaxSize().padding(contentPadding)) {
            // Full-screen immersive content
        }
    }
}

כדי להסתיר את שורת הסטטוס של המערכת כשרכיב מסוים מוצג במסך, צריך להחיל את Modifier.suppressStatusBar ישירות על הרכיב הזה. המשתנה הזה שימושי לרכיבים במסך מלא, כמו אינדיקטורים של התקדמות במסך מלא וחלונות של תיבות דו-שיח בהתאמה אישית.

מתי כדאי להשתמש במצב אימרסיבי ברמת האפליקציה

אם כל האפליקציה היא חוויה עשירה במסך מלא, צריך להחיל את Modifier.suppressStatusBar על AppScaffold כדי להסתיר את שורת הסטטוס של המערכת בכל המסכים:

// Apply Modifier.suppressStatusBar() to AppScaffold to suppress the status bar
// and collapse insets across all child screens.
AppScaffold(modifier = Modifier.suppressStatusBar()) {
    SwipeDismissableNavHost(
        navController = navController,
        startDestination = "home",
    ) {
        // Nested screens inherit suppression and 0.dp padding
    }
}

הצגת שינויים מותאמים אישית בטקסט של השעה

אם אתם צריכים להציג כותרת מעוקלת בהתאמה אישית או להשבית באופן זמני את שורת הסטטוס של המערכת במסך ספציפי או בכל האפליקציה במהלך המעבר ל-Wear OS 8, העברת timeText בהתאמה אישית תסתיר את שורת הסטטוס של המערכת:

// Screen-level custom TimeText override:
ScreenScaffold(
    timeText = { TimeText { timeTextCurvedText("Custom Status") } },
) {
    // Content
}

// App-level opt-out using in-app TimeText:
AppScaffold(
    timeText = { TimeText() },
) {
    // Screens
}

הטמעה באמצעות תצוגות (לא מומלץ)

אם האפליקציה משתמשת בתצוגות של Android במקום ב-Jetpack Compose ל-Wear OS, צריך להביע הסכמה באמצעות AndroidManifest.xml. בניגוד לגרסת האלפא האחרונה של Wear Compose Material 3, שבה שורת הסטטוס של המערכת מופעלת באופן אוטומטי, באפליקציות שמבוססות על תצוגה צריך להוסיף את התג ENABLE_GLOBAL_STATUS_BAR <meta-data> בתוך <application> כדי להפעיל את שורת הסטטוס:

<meta-data
    android:name="com.google.wear.ENABLE_GLOBAL_STATUS_BAR"
    android:value="true" />

מעקב אחרי הוספות בחלון העליון

משתמשים ב-ViewCompat.setOnApplyWindowInsetsListener ובודקים את הערך של windowInsets.getInsets(WindowInsetsCompat.Type.statusBars()). כאשר statusBarInsets.top > 0, הסירו את ממשק המשתמש הקודם של השעה 12:00 והתאימו את המרווח הפנימי העליון. אחרת, חזרו לממשק המשתמש הקודם:

ViewCompat.setOnApplyWindowInsetsListener(rootView) { view, windowInsets ->
    val statusBarInsets = windowInsets.getInsets(
        WindowInsetsCompat.Type.statusBars()
    )

    if (statusBarInsets.top > 0) {
        // status bar is visible: remove legacy 12 o'clock UI and apply top inset padding
        view.updatePadding(top = statusBarInsets.top)
    } else {
        // status bar is not visible: fall back to legacy UI and padding
    }

    WindowInsetsCompat.CONSUMED
}

הסתרה והצגה של שורת הסטטוס באופן פרוגרמטי

בניגוד ל-ScreenScaffold ב-Compose, באפליקציות שמבוססות על תצוגה צריך להסתיר או להציג באופן מפורש את שורת הסטטוס של המערכת (לדוגמה, כשנכנסים לתצוגה מקיפה במסך מלא או כשמתאמים את התנהגות הגלילה) באמצעות WindowInsetsControllerCompat:

val insetsController = WindowCompat.getInsetsController(window, window.decorView)

// Hide the status bar
insetsController.hide(WindowInsetsCompat.Type.statusBars())

// Show the status bar
insetsController.show(WindowInsetsCompat.Type.statusBars())

בדיקת האפליקציה

כשבודקים את האפליקציה באמולטור של גרסת טרום-ההשקה (Preview) של Wear OS 7.1 בטא (API 37.2-beta1), צריך לבדוק את הדברים הבאים:

  • השעון מופיע רק פעם אחת: מוודאים שרק השעה בשורת הסטטוס של המערכת מופיעה במיקום של השעה 12:00, ושאין חפיפה עם TimeText מדור קודם בתוך האפליקציה ועם תוכן האפליקציה.
  • מרווח פנימי עליון: מוודאים שכותרות המסך, הכותרות העליונות והכפתורים העליונים מופיעים מתחת לשורת הסטטוס.
  • שכבות-על ותיבות דו-שיח במסך מלא: ודאו שתיבות דו-שיח, בוררים, פקדי שלבים ופעילויות בהתאמה אישית במסך מלא מסתירים את שורת הסטטוס כשהם נפתחים, ומשחזרים אותה כשהם נסגרים.