פיתוח למסכים בגדלים שונים

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

למידע נוסף על עקרונות העיצוב עבור פריסות מותאמות, כדאי לקרוא את הנחיות התכנון.

פיתוח פריסות רספונסיביות באמצעות הורולוג

פריסות צריכות להיות עם שולי רווח שמבוססים על אחוזים. כי התכונה 'כתיבה' פועלת על ידי כברירת מחדל בערכים מוחלטים, השתמשו ברכיבים ספריית הורולוגים, שכוללת את התכונות הבאות:

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

קטע הקוד הבא משתמש בגרסת ה-Horism פריסה של ScalingLazyColumn ליצירת תוכן שנראה מעולה במגוון רחב מהגדלים של המסכים ב-Wear OS:

val columnState = rememberResponsiveColumnState(
    contentPadding = ScalingLazyColumnDefaults.padding(
        first = ScalingLazyColumnDefaults.ItemType.Text,
        last = ScalingLazyColumnDefaults.ItemType.SingleButton
    )
)
ScreenScaffold(scrollState = columnState) {
    ScalingLazyColumn(
        columnState = columnState
    ) {
        item {
            ResponsiveListHeader(contentPadding = firstItemPadding()) {
                Text(text = "Header")
            }
        }
        // ... other items
        item {
            Button(
                imageVector = Icons.Default.Build,
                contentDescription = "Example Button",
                onClick = { }
            )
        }
    }
}

הדוגמה הזו כוללת גם את ScreenScaffold ואת AppScaffold. הקואורדינטות האלה בין האפליקציה למסכים נפרדים (נתיבי ניווט) כדי לוודא שהתנהגות הגלילה נכונה TimeText.

לגבי המרווח הפנימי העליון והתחתון, חשוב לשים לב גם לדברים הבאים:

  • המפרט של ItemType הראשון והאחרון, כדי לקבוע מרווח פנימי.
  • השימוש ב-ResponsiveListHeader עבור הפריט הראשון ברשימה, עקב סיבות Text כותרות לא יכולות לכלול מרווח פנימי.

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

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

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

ההשפעה של גודל מכשיר שונה ושינוי קנה מידה של גופן

ההשפעה של גדלים שונים של מכשירים ויכולת לשנות את גודל הגופנים.

תיבות דו-שיח

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

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

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

יכול להיות שבמסכים מותאמים אישית תידרש פריסות שאינן גלילה.

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

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

מספקים חוויות שונות דרך נקודות עצירה (breakpoint)

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

const val LARGE_DISPLAY_BREAKPOINT = 225

@Composable
fun isLargeDisplay() = LocalConfiguration.current.screenWidthDp >= LARGE_DISPLAY_BREAKPOINT

// ... use in your Composables:
if (isLargeDisplay()) {
    // Show additional content.
} else {
    // Show content only for smaller displays.
}

בהנחיות התכנון מתוארות חלק גדול יותר מההזדמנויות האלה.

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

תצוגות מקדימות של פיתוח נייטיב עוזרות לפתח מסכים למגוון גדלים של מסכים עם Wear OS. השתמשו גם בהגדרות המכשירים וגם בהגדרות התצוגה המקדימה של שינוי גודל הגופנים כדי לראות את הדברים הבאים:

  • איך המסכים נראים קיצוניות של שינוי הגודל, לדוגמה, הגופן הגדול ביותר מותאם למסך הקטן ביותר.
  • איך החוויה הייחודית מתנהגת בנקודות עצירה (breakpoint).

הקפידו להטמיע תצוגות מקדימות באמצעות WearPreviewDevices וגם WearPreviewFontScales לכל המסכים באפליקציה.

@WearPreviewDevices
@WearPreviewFontScales
@Composable
fun ListScreenPreview() {
    ListScreen()
}

בדיקה של צילום מסך

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

אפשר גם לבדוק צילומי מסך כדי לזהות רגרסיות במיקומים ספציפיים. ב-codebase,

בדוגמאות שלנו נעשה שימוש ב-Roborazzi לבדיקת צילומי מסך:

  1. מגדירים את קובצי build.gradle של הפרויקט והאפליקציה לשימוש רובורצי.
  2. יוצרים בדיקה של צילום מסך לכל מסך באפליקציה. לדוגמה, בדוגמה של ComposeStarter, הבדיקה של GreetingScreen היא מיושם כפי שמוצג ב-GreetingScreenTest:
@RunWith(ParameterizedRobolectricTestRunner::class)
class GreetingScreenTest(override val device: WearDevice) : WearScreenshotTest() {
    override val tolerance = 0.02f

    @Test
    fun greetingScreenTest() = runTest {
        AppScaffold(
            timeText = { ResponsiveTimeText(timeSource = FixedTimeSource) }
        ) {
            GreetingScreen(greetingName = "screenshot", onShowList = {})
        }
    }

    companion object {
        @JvmStatic
        @ParameterizedRobolectricTestRunner.Parameters
        fun devices() = WearDevice.entries
    }
}

נקודות חשובות שכדאי לציין:

  • FixedTimeSource מאפשר ליצור צילומי מסך שבהם TimeText לא ולגרום לכך שהבדיקות להיכשל באופן בלתי מכוון.
  • WearDevice.entries כולל הגדרות של רוב מכשירי Wear OS הפופולריים, לכן שהבדיקות מתבצעות על טווח מייצג של גודלי מסכים.

יצירת תמונות זהובות

כדי ליצור תמונות למסכים, מריצים את הפקודה הבאה בטרמינל:

./gradlew recordRoborazziDebug

אימות התמונות

כדי לאמת שינויים בתמונות קיימות, מריצים את הפקודה הבאה טרמינל:

./gradlew verifyRoborazziDebug

דוגמה מלאה לבדיקת צילומי מסך מופיעה בדוגמה של ComposeStarter.