כדי להתחיל לספק משבצות מהאפליקציה, צריך לכלול את יחסי התלות הבאים בקובץ build.gradle
של האפליקציה.
Groovy
dependencies { // Use to implement support for wear tiles implementation "androidx.wear.tiles:tiles:1.5.0-alpha04" // Use to utilize standard components and layouts in your tiles implementation "androidx.wear.protolayout:protolayout:1.3.0-alpha04" // Use to utilize components and layouts with Material Design in your tiles implementation "androidx.wear.protolayout:protolayout-material:1.3.0-alpha04" // Use to include dynamic expressions in your tiles implementation "androidx.wear.protolayout:protolayout-expression:1.3.0-alpha04" // Use to preview wear tiles in your own app debugImplementation "androidx.wear.tiles:tiles-renderer:1.5.0-alpha04" // Use to fetch tiles from a tile provider in your tests testImplementation "androidx.wear.tiles:tiles-testing:1.5.0-alpha04" }
Kotlin
dependencies { // Use to implement support for wear tiles implementation("androidx.wear.tiles:tiles:1.5.0-alpha04") // Use to utilize standard components and layouts in your tiles implementation("androidx.wear.protolayout:protolayout:1.3.0-alpha04") // Use to utilize components and layouts with Material Design in your tiles implementation("androidx.wear.protolayout:protolayout-material:1.3.0-alpha04") // Use to include dynamic expressions in your tiles implementation("androidx.wear.protolayout:protolayout-expression:1.3.0-alpha04") // Use to preview wear tiles in your own app debugImplementation("androidx.wear.tiles:tiles-renderer:1.5.0-alpha04") // Use to fetch tiles from a tile provider in your tests testImplementation("androidx.wear.tiles:tiles-testing:1.5.0-alpha04") }
יצירת משבצת
כדי לספק משבצת מהאפליקציה, יוצרים כיתה שמרחיבה את TileService
ומטמיעים את השיטות, כפי שמתואר בדוגמת הקוד הבאה:
class MyTileService : TileService() { override fun onTileRequest(requestParams: RequestBuilders.TileRequest) = Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( Text.Builder(this, "Hello World!") .setTypography(Typography.TYPOGRAPHY_BODY1) .setColor(argb(0xFFFFFFFF.toInt())) .build() ) ) .build() ) override fun onTileResourcesRequest(requestParams: ResourcesRequest) = Futures.immediateFuture( Resources.Builder() .setVersion(RESOURCES_VERSION) .build() ) }
בשלב הבא, מוסיפים שירות בתוך התג <application>
בקובץ AndroidManifest.xml
.
<service android:name=".snippets.tile.MyTileService" android:label="@string/tile_label" android:description="@string/tile_description" android:icon="@mipmap/ic_launcher" android:exported="true" android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER"> <intent-filter> <action android:name="androidx.wear.tiles.action.BIND_TILE_PROVIDER" /> </intent-filter> <meta-data android:name="androidx.wear.tiles.PREVIEW" android:resource="@drawable/tile_preview" /> </service>
מסנן ההרשאות והכוונות רושם את השירות הזה כספק משבצות.
הסמל, התווית והתיאור מוצגים למשתמש כשהוא מגדיר את המשבצות בטלפון או בשעון.
אפשר להשתמש בתג המטא-נתונים של התצוגה המקדימה כדי להציג תצוגה מקדימה של המשבצת כשמגדירים אותה בטלפון.
סקירה כללית על מחזור החיים של שירות של קטעי מפות
אחרי שיוצרים את TileService
ומצהירים עליו במניפסט של האפליקציה, אפשר להגיב לשינויים במצב של שירות המשבצת.
TileService
הוא שירות מחויב. ה-TileService
מחויב כתוצאה מהבקשה של האפליקציה או אם המערכת צריכה לתקשר איתו. מחזור החיים של שירות מקושר כולל את ארבע שיטות הקריאה החוזרת הבאות: onCreate()
, onBind()
, onUnbind()
ו-onDestroy()
. המערכת מפעילה את השיטות האלה בכל פעם שהשירות נכנס לשלב חדש במחזור החיים.
בנוסף לקריאות החזרה (callbacks) ששולטות במחזור החיים של השירות המקושר, אפשר להטמיע שיטות אחרות שספציפיות למחזור החיים של TileService
. כל שירותי המשבצות חייבים להטמיע את onTileRequest()
ואת onTileResourcesRequest()
כדי להגיב לבקשות לעדכונים מהמערכת.
onTileAddEvent()
: המערכת קוראת לשיטה הזו רק כשהמשתמש מוסיף את המשבצת בפעם הראשונה, וגם אם המשתמש מסיר את המשבצת ומוסיף אותה שוב. זהו הזמן הטוב ביותר לבצע אתחול חד-פעמי.onTileAddEvent()
נקראת רק כשמגדירים מחדש את קבוצת המשבצות, ולא בכל פעם שהמערכת יוצרת משבצת. לדוגמה, כשמפעילים מחדש את המכשיר או מפעילים אותו, לא מתבצעת קריאה ל-onTileAddEvent()
עבור המשבצות שכבר נוספו. במקום זאת, אפשר להשתמש ב-getActiveTilesAsync()
כדי לקבל תמונת מצב של המשבצות ששייכות לכם שפעילות.onTileRemoveEvent()
: המערכת קוראת לשיטה הזו רק אם המשתמש מסיר את המשבצת שלכם.onTileEnterEvent()
: המערכת קוראת לשיטה הזו כשמשבצת שמספקת הספק הזה מופיעה במסך.onTileLeaveEvent()
: המערכת קוראת לשיטה הזו כשמשבצת שמספקת הספק הזה יוצאת מהמסך.onTileRequest()
: המערכת קוראת לשיטה הזו כשהיא מבקשת ציר זמן חדש מהספק הזה.onTileResourcesRequest()
: המערכת קוראת לשיטה הזו כשהיא מבקשת חבילת משאבים מהספק הזה. זה יכול לקרות בפעם הראשונה שמשאב מסוים נטען או בכל פעם שגרסת המשאב משתנה.
שאילתות לגבי המשבצות הפעילות
אריחים פעילים הם אריחים שנוספו כדי להציג אותם בשעון. משתמשים ב-method הסטטי getActiveTilesAsync()
של TileService
כדי לשלוח שאילתה לגבי המשבצות ששייכות לאפליקציה שפעילות.
יצירת ממשק משתמש לאריחים
פריסת המשבצת נכתבת באמצעות תבנית build. הפריסה של המשבצת מורכבת מעץ שמכיל קונטיינרים של פריסה ורכיבי פריסה בסיסיים. לכל רכיב פריסה יש מאפיינים שאפשר להגדיר באמצעות שיטות שונות להגדרת מאפיינים.
רכיבי פריסה בסיסיים
יש תמיכה ברכיבים החזותיים הבאים מהספרייה protolayout
, יחד עם רכיבי Material:
Text
: הפיכת מחרוזת טקסט לתמונה, עם אפשרות לגלישת הטקסט.Image
: הפיכת תמונה לתמונה מוצגת.Spacer
: מגדיר את הריווח בין הרכיבים או יכול לשמש כמפריד כשמגדירים את צבע הרקע שלו.
רכיבי חומר
בנוסף לרכיבים הבסיסיים, הספרייה protolayout-material
מספקת רכיבים שמאפשרים ליצור עיצוב של משבצות בהתאם להמלצות לממשק המשתמש של Material Design.
Button
: רכיב עגול שניתן ללחוץ עליו, שנועד להכיל סמל.Chip
: רכיב בצורת אצטדיון שניתן ללחוץ עליו, שמיועד להכיל עד שתי שורות טקסט ואיקון אופציונלי.CompactChip
: רכיב בצורת אצטדיון שניתן ללחוץ עליו, שנועד להכיל שורה של טקסט.TitleChip
: רכיב בצורת אצטדיון שניתן ללחוץ עליו, בדומה ל-Chip
, אבל עם גובה גדול יותר כדי להכיל טקסט של כותר.CircularProgressIndicator
: אינדיקטור התקדמות מעגלי שאפשר להציב בתוךEdgeContentLayout
כדי להציג את ההתקדמות בקצוות המסך.
קונטיינרים של פריסה
אפשר להשתמש בקונטיינרים הבאים, יחד עם פריסות של Material Design:
Row
: הרכיבים הצאצאים מוצגים בפריסה אופקית, אחד אחרי השני.Column
: הרכיבים הצאצאים מוצגים אנכית, אחד אחרי השני.Box
: שכבות-על של רכיבי הצאצאים מעל אחד לשני.Arc
: הצגת הרכיבים הצאצאים במעגל.Spannable
: הוספתFontStyles
ספציפי לקטע טקסט, יחד עם הטמעת טקסט ותמונות. למידע נוסף, ראו Spannables.
כל קונטיינר יכול להכיל צאצא אחד או יותר, שגם הם יכולים להיות קונטיינרים. לדוגמה, רכיב Column
יכול להכיל כמה רכיבי Row
בתור צאצאים, וכך ליצור פריסה שדומה לחלוקה לרשת.
לדוגמה, משבצת עם פריסה של קונטיינר ושני רכיבי פריסה של צאצאים יכולה להיראות כך:
Kotlin
private fun myLayout(): LayoutElement = Row.Builder() .setWidth(wrap()) .setHeight(expand()) .setVerticalAlignment(VALIGN_BOTTOM) .addContent(Text.Builder() .setText("Hello world") .build() ) .addContent(Image.Builder() .setResourceId("image_id") .setWidth(dp(24f)) .setHeight(dp(24f)) .build() ).build()
Java
private LayoutElement myLayout() { return new Row.Builder() .setWidth(wrap()) .setHeight(expand()) .setVerticalAlignment(VALIGN_BOTTOM) .addContent(new Text.Builder() .setText("Hello world") .build() ) .addContent(new Image.Builder() .setResourceId("image_id") .setWidth(dp(24f)) .setHeight(dp(24f)) .build() ).build(); }
פריסות של Material
בנוסף לפריסות בסיסיות, בספרייה protolayout-material
יש כמה פריסות מוגדרות מראש שנועדו להכיל רכיבים ב'משבצות' ספציפיות.
PrimaryLayout
: תוצג פעולה ראשית אחת (CompactChip
) בתחתית המסך, והתוכן יוצג במרכז מעליו.MultiSlotLayout
: תוויות ראשיות ומשניות עם תוכן אופציונלי ביניהן וCompactChip
אופציונלי בתחתית המסך.MultiButtonLayout
: ממקם קבוצת לחצנים שמסודרים בהתאם להנחיות של Material.EdgeContentLayout
: תוכלו להשתמש בו כדי למקם תוכן סביב קצה המסך, למשלCircularProgressIndicator
. כשמשתמשים בפריסה הזו, התוכן שבתוכה מקבל באופן אוטומטי את השוליים והרווחים המתאימים.
קשתות
יש תמיכה בצאצאים הבאים של קונטיינר Arc
:
ArcLine
: הופך את הקו העקום סביב Arc למודל תלת-ממדי.ArcText
: הפיכת הטקסט לעקום ב-Arc.ArcAdapter
: המערכת תיצור עיבוד (רנדר) של אלמנט פריסה בסיסי בתוך הקשת, שתוחם את הקשת.
מידע נוסף זמין במאמרי העזרה של כל אחד מסוגי הרכיבים.
גורמי שינוי
אפשר להחיל משתני אופן פעולה על כל אלמנט פריסה זמין. אפשר להשתמש במקשי השינוי האלה למטרות הבאות:
- שינוי המראה החזותי של הפריסה. לדוגמה, מוסיפים רקע, גבול או ריפוד לאלמנט הפריסה.
- מוסיפים מטא-נתונים לגבי הפריסה. לדוגמה, אפשר להוסיף רכיב לשינוי סמנטיקה לרכיב הפריסה לשימוש עם קוראי מסך.
- הוספת פונקציונליות. לדוגמה, אפשר להוסיף רכיב שינוי שאפשר ללחוץ עליו לרכיב הפריסה כדי להפוך את המשבצת לאינטראקטיבית. מידע נוסף זמין במאמר אינטראקציה עם משבצות.
לדוגמה, אפשר להתאים אישית את המראה והמטא-נתונים שמוגדרים כברירת מחדל של Image
, כפי שמתואר בקטע הקוד הבא:
Kotlin
private fun myImage(): LayoutElement = Image.Builder() .setWidth(dp(24f)) .setHeight(dp(24f)) .setResourceId("image_id") .setModifiers(Modifiers.Builder() .setBackground(Background.Builder().setColor(argb(0xFFFF0000)).build()) .setPadding(Padding.Builder().setStart(dp(12f)).build()) .setSemantics(Semantics.builder() .setContentDescription("Image description") .build() ).build() ).build()
Java
private LayoutElement myImage() { return new Image.Builder() .setWidth(dp(24f)) .setHeight(dp(24f)) .setResourceId("image_id") .setModifiers(new Modifiers.Builder() .setBackground(new Background.Builder().setColor(argb(0xFFFF0000)).build()) .setPadding(new Padding.Builder().setStart(dp(12f)).build()) .setSemantics(new Semantics.Builder() .setContentDescription("Image description") .build() ).build() ).build(); }
מודעות Spannable
Spannable
הוא סוג מיוחד של מאגר שמציג את הרכיבים באופן דומה לזה שבו מוצג טקסט. האפשרות הזו שימושית כשרוצים להחיל סגנון שונה רק על מחרוזת משנה אחת בבלוק טקסט גדול יותר, דבר שלא ניתן לעשות באמצעות הרכיב Text
.
קונטיינר Spannable
מלא בSpan
צאצאים. אסור להוסיף צאצאים אחרים או מכונות Spannable
בתצוגת עץ.
יש שני סוגים של צאצאים של Span
:
לדוגמה, אפשר להדגיש את המילה 'world' בכותרת 'Hello world' ולהוסיף תמונה בין המילים, כמו בקטע הקוד הבא:
Kotlin
private fun mySpannable(): LayoutElement = Spannable.Builder() .addSpan(SpanText.Builder() .setText("Hello ") .build() ) .addSpan(SpanImage.Builder() .setWidth(dp(24f)) .setHeight(dp(24f)) .setResourceId("image_id") .build() ) .addSpan(SpanText.Builder() .setText("world") .setFontStyle(FontStyle.Builder() .setItalic(true) .build()) .build() ).build()
Java
private LayoutElement mySpannable() { return new Spannable.Builder() .addSpan(new SpanText.Builder() .setText("Hello ") .build() ) .addSpan(new SpanImage.Builder() .setWidth(dp(24f)) .setHeight(dp(24f)) .setResourceId("image_id") .build() ) .addSpan(new SpanText.Builder() .setText("world") .setFontStyle(newFontStyle.Builder() .setItalic(true) .build()) .build() ).build(); }
עבודה עם משאבים
לכרטיסי המידע אין גישה למשאבים של האפליקציה. המשמעות היא שאי אפשר להעביר מזהה תמונה של Android לרכיב פריסה מסוג Image
ולצפות שהוא יפתור את הבעיה. במקום זאת, צריך לשנות את השיטה onTileResourcesRequest()
ולספק את המשאבים באופן ידני.
יש שתי דרכים לספק תמונות בתוך השיטה onTileResourcesRequest()
:
- מציינים משאב drawable באמצעות
setAndroidResourceByResId()
. - מספקים תמונה דינמית כ-
ByteArray
באמצעותsetInlineResource()
.
Kotlin
override fun onTileResourcesRequest( requestParams: ResourcesRequest ) = Futures.immediateFuture( Resources.Builder() .setVersion("1") .addIdToImageMapping("image_from_resource", ImageResource.Builder() .setAndroidResourceByResId(AndroidImageResourceByResId.Builder() .setResourceId(R.drawable.image_id) .build() ).build() ) .addIdToImageMapping("image_inline", ImageResource.Builder() .setInlineResource(InlineImageResource.Builder() .setData(imageAsByteArray) .setWidthPx(48) .setHeightPx(48) .setFormat(ResourceBuilders.IMAGE_FORMAT_RGB_565) .build() ).build() ).build() )
Java
@Override protected ListenableFuture<Resources> onTileResourcesRequest( @NonNull ResourcesRequest requestParams ) { return Futures.immediateFuture( new Resources.Builder() .setVersion("1") .addIdToImageMapping("image_from_resource", new ImageResource.Builder() .setAndroidResourceByResId(new AndroidImageResourceByResId.Builder() .setResourceId(R.drawable.image_id) .build() ).build() ) .addIdToImageMapping("image_inline", new ImageResource.Builder() .setInlineResource(new InlineImageResource.Builder() .setData(imageAsByteArray) .setWidthPx(48) .setHeightPx(48) .setFormat(ResourceBuilders.IMAGE_FORMAT_RGB_565) .build() ).build() ).build() ); }
מומלץ עבורך
- הערה: טקסט הקישור מוצג כש-JavaScript מושבת
- מעבר למרחבי שמות של ProtoLayout
ConstraintLayout
ב-Compose- יצירת משבצות בהתאמה אישית להגדרות המהירות של האפליקציה