מהנדס תוכנה
במפגש הזה נתעמק בהיבטים הטכניים של המעבר מכרטיסי מידע במסך מלא לווידג'טים דינמיים בגובה חלקי ל-Wear.
נבחן את היתרונות הטכניים של Jetpack Glance API המאוחד ושל מנוע Remote Compose החדש, ונסביר איך הם משתלבים בצורה חלקה עם Modern Android Development.
בסוף נשתף את ההנחיות העדכניות ביותר בנושא חוויית המשתמש ונעבור על אסטרטגיות מעשיות להעברה, כדי לעזור לכם ליצור את הדור הבא של ממשק משתמש שקל להבין במבט חטוף.
תמליל
שלום לכולם,
קוראים לי פרנק, ואני מוביל את צוות הפיתוח של חוויות השימוש במבט חטוף ב-Wear OS.
השעונים הם פריטים חיוניים שמלווים את המשתמשים לאורך כל היום, והיום נסביר לכם איך לנצל את חוויית השימוש החדשה בווידג'טים של Wear.
נבחן שתי דרכים להעביר את התכונות הכי חשובות ישירות לפרק כף היד של המשתמשים, ונעשה את זה באמצעות ממשקי ה-API העדכניים ביותר, ממשקי API שנועדו לגרום לפיתוח עבור Wear OS להרגיש מוכר ואינטואיטיבי למפתחי Android, כמוכם.
כדי להראות לכם איך בדיוק אנחנו עושים את זה, מצטרף אליי לבמה יורי, הקולגה המבריק שלי והשותף שלי לשולחן העבודה.
שלום, אני יורי שימקה.
אני מהנדס בצוות Wear OS, והתפקיד העיקרי שלי הוא לעבוד על ממשקי ה-API של Remote Compose.
היום אתן לכם הקדמה קצרה על Remote Compose ואדבר גם על תהליך המעבר מכרטיסי מידע לווידג'טים של Wear.
עכשיו אחזיר אתכם לפרנק.
נהדר.
תודה, Yuri.
אנחנו מביאים באופן רשמי את פרק כף היד לסביבה המאוחדת של הווידג'טים ב-Android, והופכים את כרטיסי המידע במסך מלא לווידג'טים ל-Wear.
מכיוון שהחוויות האלה מבוססות עכשיו על Jetpack Glance, אפשר לראות שזו אותה תשתית בסיסית שמשמשת לווידג'טים לנייד.
בעתיד, תהליך הפיתוח ל-Wear יהיה מוכר לכם עוד יותר.
כדי להפעיל את החוויות האלה, אנחנו מפתחים את מחסנית ממשק המשתמש – מחסנית ממשק המשתמש הבסיסית.
הווידג'טים של Wear מופעלים באמצעות Remote Compose, framework חדש של Android לממשק משתמש מרוחק.
זה אומר שסוף סוף אתם יכולים להשתמש ב-API הצהרתי שמתאים מאוד ל-Jetpack Compose כדי ליצור חוויות שימוש מחוץ לאפליקציה, כמו ווידג'טים.
התכונה "כתיבה מרחוק" מאפשרת להוסיף לווידג'טים גרפיקה מודרנית ופריסות רספונסיביות, תוך שמירה על ביצועים וחיסכון בסוללה.
הפרדת ממשק המשתמש מתהליך האפליקציה מאפשרת להעביר את הווידג'טים בבטחה ולעבד אותם בקלות במגוון רחב של מכשירי Android.
זה אומר שאתם יכולים להביא את החוויות העשירות האלה כמעט לכל הפלטפורמות המרוחקות הנתמכות במינימום מאמץ.
כדי שהמעבר ממשבצות לווידג'טים יהיה חלק ככל האפשר, אנחנו מציגים שני גדלים סטנדרטיים של קונטיינרים: קטן וגדול.
הם נועדו להתאים לפורמטים של ווידג'טים שמבוססים על רשת של 2x1 ו-2x2, שאתם כבר מכירים מיצירת ווידג'טים בנייד.
בנוסף, החל מגרסה Wear 7, אצל חלק מיצרני החומרה, הווידג'טים של Wear יופיעו במגש עם גלילה אנכית לצד הווידג'טים של אפליקציות אחרות.
לדוגמה, כך נראים ווידג'טים של Wear ב-Samsung Galaxy Watch.
הארכיטקטורה של הפלטפורמה בנויה לתמוך במגשים עם גלילה אנכית, כי יצרני החומרה יאמצו את הדפוס הזה בעתיד.
ואתם לא צריכים לדאוג שמשתמשים חדשים או קיימים יישארו מאחור.
ממשקי ה-API של Jetpack Glance Wear נועדו לתמוך בתאימות לדורות קודמים עד Wear 4.
במכשירים ישנים יותר שתומכים במגש אופקי של ווידג'טים או של כרטיסי מידע, המערכת תטפל בזה בשבילכם.
אתם רק צריכים לציין בקוד שאתם רוצים לתמוך במצב מסך מלא, והמערכת תציג את הווידג'ט הגדול שלכם כמשבצת רגילה במסך מלא במכשירים האלה.
עכשיו יורי יסביר לנו על הקוד כדי להראות בדיוק איך להעביר את המשבצות הקיימות לווידג'טים של Wear.
תודה, Frank.
אם אתם יוצרים ווידג'ט חדש ל-Wear OS מאפס, זה פשוט.
אתם רק צריכים להגדיר GlanceWearWidgetService ולבנות את ממשק המשתמש באמצעות Remote Compose.
אבל אם לאפליקציה שלכם כבר יש משבצת בסביבת הייצור, תצטרכו להעביר את השירותים, ממשק המשתמש והנתונים.
כדי שהמעבר יהיה חלק ככל האפשר, סיפקנו דרכים להבטיח חוויה חלקה למשתמשים קיימים.
לגבי השירות, אתם יכולים לבחור בין שתי אסטרטגיות: שירות כפול או שירות יחיד.
עם שירות כפול, שאנחנו ממליצים עליו, אתם יכולים להמשיך להשתמש ב-TileService הקיים למכשירי Wear OS ישנים יותר ולהוסיף GlanceWearWidgetService חדש ל-Wear OS 7 ואילך.
לעומת זאת, בשירות היחיד, אתם יוצרים GlanceWearWidgetService חדש ויחיד שמטפל בשני הפרוטוקולים, ופועל במצב תאימות כדי לתרגם את הווידג'ט לכרטיס במכשירים ישנים יותר.
בכל מקרה, תמשיכו להגיע למשתמשים שלכם.
הוא משפיע רק על הקוד שאתם מתחזקים בהמשך.
בנוסף, פרסמנו באתר למפתחים של Android מסמכים מקיפים שמסבירים בדיוק איך ומתי להשתמש בשתי התבניות האלה.
כדאי לעיין בו כדי להבין איזו אסטרטגיה הכי מתאימה לאפליקציה שלכם.
עכשיו נדבר על שכבת ממשק המשתמש.
כשעוברים למודל חדש, צריך לשנות את הגישה.
בעבר, המשבצות השתמשו ב-ProtoLayout, ספרייה שנוצרה במיוחד בשביל משבצות ב-Wear.
לעומת זאת, הווידג'טים של Wear מבוססים על Remote Compose.
Remote Compose מבוסס על אותה תשתית כמו ממשק המשתמש של Jetpack Compose, ומשתמש באותו קומפיילר ליבה ובאותו זמן ריצה.
הוא נועד להיות מוכר, ותואם באופן הדוק לספריות של ממשק המשתמש של Compose כמו Foundation ו-Material 3.
אבל במקום תיבה, עמודה או טקסט, פשוט מחליפים אותם ב-RemoteBox, RemoteColumn או RemoteText.
במקרה כזה, תצטרכו לכתוב הרבה את המילה "remote".
כדי לזרז את תהליך העבודה, כללנו גם קבוצה מלאה של רכיבי Remote Compose מוכנים לשימוש, שתוכננו במיוחד לווידג'טים.
זה אומר שאתם יכולים להתאים בקלות את העיצובים הקיימים של Wear Material 3, כולל מה שיש לכם ב-Figma, לווידג'טים, כך שהם יהיו מוכרים גם למהנדסים וגם למעצבים.
כדי להבין עד כמה המסגרות האלה תואמות, נבחן דוגמה קונקרטית.
אנחנו הולכים לבנות רכיב אפליקציה משלנו על גבי כפתור ההחלפה של Material 3.
בצד ימין, יש לנו את רכיב Wear Compose הרגיל שכותבים בתוך האפליקציה, ובצד שמאל יש את הגרסה של Remote Compose.
// Wear Compose
@Composable
fun HistoryEraserButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
checked: Boolean = true,
onCheckedChange: (Boolean) -> Unit = {},
)// Wear RemoteCompose
@RemoteComposable
@Composable
fun RemoteHistoryEraserButton(
onClick: Action,
modifier: RemoteModifier = RemoteModifier,
checked: RemoteBoolean = true.rb,
onCheckedChange: Action = Action.Empty,
)שימו לב כמה הדפוסים דומים.
עם זאת, כשכותבים קוד של Remote Compose, משתמשים בהערה RemoteComposable.
ובמקרים שבהם אתם משתמשים בפרמטרים מוכרים כמו modifier ו-boolean, יש להם סוגים מקבילים ב-Remote Compose כמו RemoteModifier ו-RemoteBoolean.
ואתם משתמשים בפעולות במקום בביטויי למבדה.
במקום להגדיר את הקוד להפעלה בתוך ה-lambda, צריך להצהיר על פעולה כמו הפעלת intent בהמתנה, קריאה לשירות או עדכון ערך.
בואו נעבור לגוף הרכיב.
אתם תראו שגם העיצוב תואם.
אתם יכולים להחיל את ערכת הצבעים של Material 3 על רכיב ה-Remote Compose בדיוק כמו ב-Compose רגיל, כך שהווידג'ט יתאים בדיוק למיתוג של האפליקציה.
// Wear Compose
val colors = MaterialTheme.colorScheme
SplitSwitchButton(
checked = checked,
onCheckedChange = onCheckedChange,
toggleContentDescription = "Arm Eraser",
onContainerClick = onClick,
modifier = modifier.fillMaxWidth(),
colors =
SwitchButtonDefaults.splitSwitchButtonColors(
checkedContainerColor = colors.errorContainer, …
),
label = { Text("History Eraser") },
secondaryLabel = { Text("Don't touch it!") },
)// Wear RemoteCompose
val colors = RemoteMaterialTheme.colorScheme
RemoteSplitSwitchButton(
checked = checked,
onCheckedChange = onCheckedChange,
toggleContentDescription = "Arm Eraser".rs,
onContainerClick = onClick,
modifier = modifier.fillMaxWidth(),
colors =
RemoteSplitSwitchButtonDefaults.splitSwitchButtonColors(
checkedContainerColor = colors.errorContainer, …
),
label = { RemoteText("History Eraser".rs) },
secondaryLabel = { RemoteText("Don't touch it!".rs) },
)ולסיום, בואו נראה את התוצאה. ממשק המשתמש שנוצר הוא בדיוק מה שציפיתם לו: מתג נקי, רספונסיבי ומונפש.
קשה להבחין בהבדל.
כדי לעזור לכם לעצב, לשפר ולאמת את הפריסות של הווידג'טים בלי להפעיל אותם כל הזמן במכשיר או באמולטור, הוספנו תמיכה בתצוגה מקדימה של Compose לווידג'טים של Wear.
מכיוון שהווידג'טים תלויים במגבלות של מאגרים ספציפיים של יצרן הציוד המקורי (OEM), כמו גודל, צורה, ריפוד ורדיוס פינה, אנחנו מתבססים על הערת התצוגה המקדימה הרגילה, אבל עם ספק פרמטרים נוסף כדי להוסיף את ההגדרות האלה.
@Preview(name = "Squircle Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetSquirclePreview(
@PreviewParameter(SquircleAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)
@Preview(name = "Round Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetRoundPreview(
@PreviewParameter(RoundAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)הספרייה מספקת הטמעות של ספקי PreviewParameter שהוגדרו מראש, שתואמות למכשירי Wear OS בעולם האמיתי.
ההערות האלה לתצוגה המקדימה מאפשרות לכם לאמת בקלות את הפריסה במגוון צורות שונות של חומרה.
בנוסף לבדיקת הפריסות, אתם יכולים להשתמש בתצוגות המקדימות האלה כדי ליצור את התמונות הסטטיות שנדרשות לבחירת הווידג'טים במכשיר.
@Preview(name = "Widget Picker Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetRectangularPreview(
@PreviewParameter(RectangularAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)הספרייה מספקת פרמטר לצורת תצוגה מקדימה מלבנית שמדמה את המכלים המלבניים המלאים ללא חיתוך.
כדי לראות איך בדיוק זה עובד בפועל, עדכנו את האפליקציה לדוגמה Horologist Media כך שתכלול ווידג'ט חדש שמציג את ה-API הזה.
אנחנו מראים איך להוסיף את הגרסאות הקטנה והגדולה של ווידג'ט המדיה.
אפשר לבדוק את זה ב-GitHub כדי לראות השוואה בין הקוד הקודם של ProtoLayout לבין ההטמעה החדשה של Remote Compose.
אנחנו בטוחים שתאהבו את זה.
ולסיום, אי אפשר לדבר על הנושא בלי להזכיר AI.
כדי לזרז את המעבר, פרסמנו ב-GitHub מיומנות חדשה להעברת משבצות לווידג'טים.
אתם יכולים להשתמש בו עם הסוכן שבחרתם, או להוסיף אותו ישירות ל-Android Studio באמצעות ה-Android CLI.
android skills add wear-widgets
android skills add --allעכשיו אחזיר אתכם לפרנסואה כדי לסיים את הדברים.
תודה.
תודה, Yuri.
כמו שאתם רואים, קל מאוד להפוך את המשבצות לווידג'טים ל-Wear.
לסיכום, המעבר ל-Jetpack Glance Wear ול-Remote Compose הוא לא רק עדכון של ממשק המשתמש, אלא הצטרפות לסביבה עסקית מאוחדת יותר של ווידג'טים ל-Android.
עכשיו אתם יכולים ליצור ווידג'טים יפים שתואמים לדורות קודמים באמצעות מסגרת מודרנית והצהרתית שתואמת באופן מלא ל-Jetpack Compose.
כדי להתחיל להעביר את המשבצות, אתם יכולים לעבור למדריך לתחילת הדרך באתר מפתחי Android.
אנחנו כבר מצפים לראות את כל החוויות האקספרסיביות והמהירות שתיצרו לשעונים.
תודה רבה שהצטרפתם אלינו היום, הבוקר, ואנחנו מקווים שתיהנו משאר הכנס.
תודה.
// Wear Compose
@Composable
fun HistoryEraserButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
checked: Boolean = true,
onCheckedChange: (Boolean) -> Unit = {},
)// Wear RemoteCompose
@RemoteComposable
@Composable
fun RemoteHistoryEraserButton(
onClick: Action,
modifier: RemoteModifier = RemoteModifier,
checked: RemoteBoolean = true.rb,
onCheckedChange: Action = Action.Empty,
)// Wear Compose
val colors = MaterialTheme.colorScheme
SplitSwitchButton(
checked = checked,
onCheckedChange = onCheckedChange,
toggleContentDescription = "Arm Eraser",
onContainerClick = onClick,
modifier = modifier.fillMaxWidth(),
colors =
SwitchButtonDefaults.splitSwitchButtonColors(
checkedContainerColor = colors.errorContainer, …
),
label = { Text("History Eraser") },
secondaryLabel = { Text("Don't touch it!") },
)// Wear RemoteCompose
val colors = RemoteMaterialTheme.colorScheme
RemoteSplitSwitchButton(
checked = checked,
onCheckedChange = onCheckedChange,
toggleContentDescription = "Arm Eraser".rs,
onContainerClick = onClick,
modifier = modifier.fillMaxWidth(),
colors =
RemoteSplitSwitchButtonDefaults.splitSwitchButtonColors(
checkedContainerColor = colors.errorContainer, …
),
label = { RemoteText("History Eraser".rs) },
secondaryLabel = { RemoteText("Don't touch it!".rs) },
)@Preview(name = "Squircle Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetSquirclePreview(
@PreviewParameter(SquircleAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)
@Preview(name = "Round Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetRoundPreview(
@PreviewParameter(RoundAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)@Preview(name = "Widget Picker Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetRectangularPreview(
@PreviewParameter(RectangularAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)android skills add wear-widgets
android skills add --all