תצוגה מקדימה של ממשק המשתמש עם תצוגות מקדימות קומפוזביליות

רכיב Composable מוגדר על ידי פונקציה ומסומן באמצעות @Composable:

@Composable
fun SimpleComposable() {
    Text("Hello World")
}

רכיב טקסט פשוט שמכיל את המילים "Hello World"

כדי להפעיל תצוגה מקדימה של ה-composable הזה, צריך ליצור composable אחר עם הערות של @Composable ו-@Preview. הרכיב הקומפוזבילי החדש עם ההערות מכיל עכשיו את הרכיב הקומפוזבילי שיצרתם בהתחלה, SimpleComposable:

@Preview
@Composable
fun SimpleComposablePreview() {
    SimpleComposable()
}

האנוטציה @Preview מציינת ל-Android Studio שצריך להציג את הפונקציה הקומפוזבילית בתצוגת העיצוב של הקובץ הזה. אתם יכולים לראות עדכונים בזמן אמת בתצוגה המקדימה של ה-composable כשאתם מבצעים את השינויים.

קובץ GIF שמציג עדכונים בזמן אמת באמצעות Compose Preview

אתם יכולים להוסיף פרמטרים באופן ידני בקוד כדי להתאים אישית את האופן שבו Android Studio מעבד את @Preview. אפשר אפילו להוסיף את ההערה @Preview לאותה פונקציה כמה פעמים כדי לראות תצוגה מקדימה של פונקציה קומפוזבילית עם מאפיינים שונים.

אחד מהיתרונות העיקריים של שימוש ברכיבים הקומפוזביליים @Preview הוא שלא צריך להסתמך על האמולטור ב-Android Studio. אתם יכולים לשמור את ההפעלה של האמולטור, שדורשת הרבה זיכרון, לשינויים סופיים יותר במראה ובתחושה, ולהשתמש ביכולת של @Preview לבצע ולבדוק שינויים קטנים בקוד בקלות.

כדי להשתמש בהערה @Preview בצורה הכי יעילה, חשוב להגדיר את המסכים לפי המצב שהם מקבלים כקלט והאירועים שהם מוציאים כפלט.

הגדרת @Preview

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

מידות

כברירת מחדל, המידות של @Preview נבחרות באופן אוטומטי כדי להתאים לתוכן שלו. כדי להגדיר את המידות באופן ידני, מוסיפים את הפרמטרים heightDp ו-widthDp. הערכים האלה כבר מפורשים כ-dp, כך שאין צורך להוסיף להם את .dp:

@Preview(widthDp = 50, heightDp = 50)
@Composable
fun SquareComposablePreview() {
    Box(Modifier.background(Color.Yellow)) {
        Text("Hello World")
    }
}

ריבוע צהוב עם הכיתוב "Hello World"

תצוגה מקדימה של צבע דינמי

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

שימוש במכשירים שונים

ב-Android Studio Flamingo, אתם יכולים לערוך את הפרמטר device של ההערה Preview כדי להגדיר את הרכיבים הניתנים לTexte שלכם במכשירים שונים.

דוגמה לפונקציה קומפוזבילית

כשהפרמטר device מכיל מחרוזת ריקה (@Preview(device = "")), אפשר להפעיל את ההשלמה האוטומטית על ידי לחיצה על Ctrl + Space. אחר כך אפשר להגדיר את הערכים של כל פרמטר.

עריכת הפונקציה לדוגמה

בהשלמה האוטומטית, אתם יכולים לבחור כל אפשרות של מכשיר מהרשימה, למשל @Preview(device = "id:pixel_4"). לחלופין, אפשר להזין מכשיר בהתאמה אישית על ידי בחירה באפשרות spec:width=px,height=px,dpi=int… כדי להגדיר את הערכים הנפרדים של כל פרמטר.

רשימת
מפרטים

כדי להחיל, לוחצים על Enter, או מבטלים באמצעות Esc.

אם מגדירים ערך לא חוקי, ההצהרה מסומנת בקו תחתון אדום ויכול להיות שיהיה תיקון זמין (Alt + Enter (⌥ + ⏎ ב-macOS) > החלפה ב…. הבדיקה מנסה לספק תיקון שהכי דומה לקלט שלכם.

דוגמה לערך לא תקין

לוקאל

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

@Preview(locale = "fr-rFR")
@Composable
fun DifferentLocaleComposablePreview() {
    Text(text = stringResource(R.string.greeting))
}

רכיב טקסט פשוט שמכיל את המילה "Bonjour" עם דגל צרפת

הגדרת צבע הרקע

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

@Preview(showBackground = true, backgroundColor = 0xFF00FF00)
@Composable
fun WithGreenBackground() {
    Text("Hello World")
}

מלבן ירוק עם הכיתוב "Hello World"

ממשק משתמש של המערכת

אם אתם צריכים להציג את שורת הסטטוס ואת סרגל הפעולות בתצוגה מקדימה, הוסיפו את הפרמטר showSystemUi:

@Preview(showSystemUi = true)
@Composable
fun DecoratedComposablePreview() {
    Text("Hello World")
}

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

מצב ממשק המשתמש

הפרמטר uiMode יכול לקבל כל אחד מהקבועים של Configuration.UI_*, ומאפשר לשנות את ההתנהגות של התצוגה המקדימה בהתאם. לדוגמה, אפשר להגדיר את התצוגה המקדימה למצב לילה כדי לראות איך העיצוב מגיב.

ממשק המשתמש של יצירת התצוגה המקדימה

LocalInspectionMode

אפשר לקרוא מ-LocalInspectionMode CompositionLocal כדי לבדוק אם הפונקציה הקומפוזבילית עוברת רינדור בתצוגה מקדימה (בתוך רכיב שניתן לבדיקה). אם הקומפוזיציה מוצגת בתצוגה מקדימה, הערך של LocalInspectionMode.current הוא true. המידע הזה מאפשר לכם להתאים אישית את התצוגה המקדימה. לדוגמה, אתם יכולים להציג תמונה לדוגמה בחלון התצוגה המקדימה במקום להציג נתונים אמיתיים.

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

@Composable
fun GreetingScreen(name: String) {
    if (LocalInspectionMode.current) {
        // Show this text in a preview window:
        Text("Hello preview user!")
    } else {
        // Show this text in the app:
        Text("Hello $name!")
    }
}

אינטראקציה עם @Preview

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

מצב אינטראקטיבי

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

המשתמש לוחץ על הכפתור "אינטראקטיבי" בתצוגה המקדימה

סרטון של המשתמש מבצע פעולות בתצוגה המקדימה

ניווט בקוד ומתארים של פונקציות קומפוזביליות

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

המשתמש מציב את הסמן מעל תצוגה מקדימה, וגורם ל-Studio להציג את קווי המתאר של הרכיבים הניתנים לשילוב (composables)

הפעלת תצוגה מקדימה

אתם יכולים להריץ @Preview ספציפי באמולטור או במכשיר פיזי. התצוגה המקדימה נפרסת באותה אפליקציית פרויקט בתור Activity חדש, ולכן היא חולקת את אותו הקשר ואותן הרשאות. לא צריך לכתוב קוד שחוזר על עצמו (boilerplate) כדי לבקש הרשאה אם היא כבר ניתנה.

לוחצים על הסמל סמל של הפעלת התצוגה המקדימה של Run Preview לצד ההערה @Preview או בחלק העליון של התצוגה המקדימה, ו-Android Studio פורס את @Preview במכשיר המחובר או באמולטור.

המשתמש לוחץ על התצוגה המקדימה

סרטון של המשתמש פורס תצוגה מקדימה במכשיר

העתקת עיבוד של @Preview

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

המשתמש לוחץ על תצוגה מקדימה כדי להעתיק אותה כתמונה.

כמה תצוגות מקדימות של אותה הערה מסוג @Preview

אתם יכולים להציג כמה גרסאות של אותה פונקציה קומפוזבילית @Preview עם מפרטים שונים, או להעביר פרמטרים שונים לפונקציה הקומפוזבילית. כך תוכלו לצמצם את הקוד שחוזר על עצמו (boilerplate) שהייתם צריכים לכתוב אחרת.

תבניות לתצוגה מקדימה מרובה

‫androidx.compose.ui:ui-tooling-preview 1.6.0-alpha01+‎ כוללת תבניות API של Multipreview: ‏@PreviewScreenSizes, ‏@PreviewFontScales, ‏@PreviewLightDark ו-@PreviewDynamicColors, כך שבאמצעות הערה אחת אפשר לראות תצוגה מקדימה של ממשק המשתמש של Compose בתרחישים נפוצים.

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

יצירת הערות מותאמות אישית לתצוגה מקדימה מרובה

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

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

@Preview(
    name = "small font",
    group = "font scales",
    fontScale = 0.5f
)
@Preview(
    name = "large font",
    group = "font scales",
    fontScale = 1.5f
)
annotation class FontScalePreviews

אתם יכולים להשתמש בהערה המותאמת אישית הזו לפונקציות ה-Composable של התצוגה המקדימה:

@FontScalePreviews
@Composable
fun HelloWorldPreview() {
    Text("Hello World")
}

כרטיסיית העיצוב ב-Android Studio שבה מוצג הרכיב הניתן לשילוב עם גופן קטן וגדול

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

@Preview(
    name = "Spanish",
    group = "locale",
    locale = "es"
)
@FontScalePreviews
annotation class CombinedPreviews

@CombinedPreviews
@Composable
fun HelloWorldPreview2() {
    MaterialTheme { Surface { Text(stringResource(R.string.hello_world)) } }
}

כרטיסיית העיצוב ב-Android Studio שבה מוצג הרכיב הקומפוזבילי בכל ההגדרות האישיות

האופי המגוון של התצוגה המקדימה המרובה – וגם של התצוגה המקדימה הרגילה – מאפשר לבדוק באופן מקיף יותר מאפיינים רבים של פרויקטים בקנה מידה גדול יותר.

‫@Preview וקבוצות נתונים גדולות

הרבה פעמים צריך להעביר קבוצת נתונים גדולה לתצוגה המקדימה של ה-composable. כדי לעשות את זה, פשוט מעבירים נתונים לדוגמה לפונקציה Composable Preview על ידי הוספת פרמטר עם ההערה @PreviewParameter.

@Preview
@Composable
fun UserProfilePreview(
    @PreviewParameter(UserPreviewParameterProvider::class) user: User
) {
    UserProfile(user)
}

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

class UserPreviewParameterProvider : PreviewParameterProvider<User> {
    override val values = sequenceOf(
        User("Elise"),
        User("Frank"),
        User("Julia")
    )
}

כך מוצגת תצוגה מקדימה אחת לכל רכיב נתונים ברצף:

תצוגות מקדימות של הרכיבים הקומפוזביליים Elise, ‏ Frank ו-Julia

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

@Preview
@Composable
fun UserProfilePreview2(
    @PreviewParameter(UserPreviewParameterProvider::class, limit = 2) user: User
) {
    UserProfile(user)
}

כברירת מחדל, התצוגות המקדימות שמשתמשות ב-@PreviewParameter נקראות לפי אינדקס הפרמטרים ושם המאפיין (משתמש 0, משתמש 1, משתמש 2 וכן הלאה), ולכן יכול להיות שיהיה קשה להבדיל ביניהן. כדי שהתצוגה המקדימה תהיה ברורה יותר, אתם יכולים לתת שם תצוגה מותאם אישית לכל תצוגה מקדימה על ידי שינוי של getDisplayName() ב-PreviewParameterProvider. כך אפשר להבחין בין וריאציות שונות של נתונים או מצבים שונים של ממשק המשתמש. לדוגמה, אפשר לתייג תצוגות מקדימות על סמך נתוני הקלט:

class UserAgePreviewParameterProvider : PreviewParameterProvider<User> {
    // Using a List internally for efficient index-based access
    private val userList = listOf(
        User(name = "Elise", age = 30),
        User(name = "Frank", age = 31),
        User(name = "Julia", age = 40)
    )

    override val values = userList.asSequence()

    override fun getDisplayName(index: Int): String? {
        // Return null or an empty string to use the default index-based name
        val user = userList.getOrNull(index) ?: return null
        return "${user.name} - ${user.age}"
    }
}

תצוגות מקדימות עם שמות מוצגים בהתאמה אישית שמציגות את הרכיבים הניתנים לשינוי אליס – 30, פרנק – 31 וג'וליה – 40

יצירת תצוגה מקדימה בעזרת AI

סוכן ה-AI ב-Android Studio יכול ליצור באופן אוטומטי תצוגות מקדימות של Compose לפונקציות ה-composable שלכם. לוחצים לחיצה ימנית על פונקציה קומפוזבילית ובוחרים באפשרות AI > Generate Preview for [Composable name]‎. הסוכן מנתח את הפונקציה הקומפוזבילית כדי ליצור את ה-boilerplate הנדרש של @Preview עם הפרמטרים הנכונים, וכך עוזר לכם לוודא במהירות שממשק המשתמש מוצג כמו שצריך.

יצירת תצוגה מקדימה של Compose באמצעות AI.

סיווג ההערה @Preview

אתם תמיד יכולים ללחוץ על "Ctrl או ⌘ + קליק" על ההערה @Preview ב-Android Studio כדי לראות רשימה מלאה של הפרמטרים שאפשר לשנות כשמתאימים אישית את התצוגה המקדימה.

annotation class Preview(
    val name: String = "",
    val group: String = "",
    @IntRange(from = 1) val apiLevel: Int = -1,
    val widthDp: Int = -1,
    val heightDp: Int = -1,
    val locale: String = "",
    @FloatRange(from = 0.01) val fontScale: Float = 1f,
    val showSystemUi: Boolean = false,
    val showBackground: Boolean = false,
    val backgroundColor: Long = 0,
    @UiMode val uiMode: Int = 0,
    @Device val device: String = Devices.DEFAULT,
    @Wallpaper val wallpaper: Int = Wallpapers.NONE,
)

מגבלות ושיטות מומלצות

‫Android Studio מריץ את הקוד של התצוגה המקדימה ישירות באזור התצוגה המקדימה. לא צריך להפעיל אמולטור או מכשיר פיזי כי הוא משתמש בחלק מועבר של מסגרת Android שנקרא Layoutlib. ‫Layoutlib היא גרסה מותאמת אישית של Android framework שמיועדת לפעול מחוץ למכשירי Android. מטרת הספרייה היא לספק תצוגה מקדימה של פריסה ב-Android Studio שקרובה מאוד לעיבוד שלה במכשירים.

מגבלות על גרסאות טרום-השקה (Preview)

בגלל האופן שבו התצוגות המקדימות מוצגות ב-Android Studio, הן קלות ולא דורשות את כל מסגרת Android כדי להציג אותן. אבל יש לזה כמה מגבלות:

  • אין גישה לרשת
  • אין גישה לקבצים
  • יכול להיות שחלק מממשקי ה-API של Context לא יהיו זמינים באופן מלא

תצוגות מקדימות וViewModels

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

כשמנסים להציג תצוגה מקדימה של רכיב Composable עם ViewModel, ב-Android Studio מוצגת שגיאה בזמן העיבוד של הרכיב הספציפי:

חלונית הבעיות ב-Android Studio עם ההודעה Failed to instantiate a `ViewModel`

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

@Composable
fun AuthorScreen(viewModel: AuthorViewModel = viewModel()) {
  AuthorScreen(
    name = viewModel.authorName,
    // ViewModel sends the network requests and makes posts available as a state
    posts = viewModel.posts
  )
}

@Composable
fun AuthorScreen(
  name: NameLabel,
  posts: PostsList
) {
  // ...
}

@Preview
@Composable
fun AuthorScreenPreview(
  // You can use some sample data to preview your composable without the need to construct the ViewModel
  name: String = sampleAuthor.name,
  posts: List<Post> = samplePosts[sampleAuthor]
) {
  AuthorScreen(
      name = NameLabel(name),
      posts = PostsList(posts)
  )
}

מקורות מידע נוספים

  • בפוסט בבלוג Compose Tooling מוסבר איך Android Studio מקל על השימוש ב-@Preview, ויש בו טיפים נוספים לשימוש בכלים.
  • להנחיות לגבי פריסות קודמות של תצוגות, ראו פיתוח פריסה עם תצוגות.