Per iniziare a fornire riquadri dalla tua app, includi le seguenti dipendenze nel file build.gradle
dell'app.
Trendy
dependencies { // Use to implement support for wear tiles implementation "androidx.wear.tiles:tiles:1.4.0-alpha01" // Use to utilize standard components and layouts in your tiles implementation "androidx.wear.protolayout:protolayout:1.2.0-alpha01" // Use to utilize components and layouts with Material Design in your tiles implementation "androidx.wear.protolayout:protolayout-material:1.2.0-alpha01" // Use to include dynamic expressions in your tiles implementation "androidx.wear.protolayout:protolayout-expression:1.2.0-alpha01" // Use to preview wear tiles in your own app debugImplementation "androidx.wear.tiles:tiles-renderer:1.4.0-alpha01" // Use to fetch tiles from a tile provider in your tests testImplementation "androidx.wear.tiles:tiles-testing:1.4.0-alpha01" }
Kotlin
dependencies { // Use to implement support for wear tiles implementation("androidx.wear.tiles:tiles:1.4.0-alpha01") // Use to utilize standard components and layouts in your tiles implementation("androidx.wear.protolayout:protolayout:1.2.0-alpha01") // Use to utilize components and layouts with Material Design in your tiles implementation("androidx.wear.protolayout:protolayout-material:1.2.0-alpha01") // Use to include dynamic expressions in your tiles implementation("androidx.wear.protolayout:protolayout-expression:1.2.0-alpha01") // Use to preview wear tiles in your own app debugImplementation("androidx.wear.tiles:tiles-renderer:1.4.0-alpha01") // Use to fetch tiles from a tile provider in your tests testImplementation("androidx.wear.tiles:tiles-testing:1.4.0-alpha01") }
Crea un riquadro
Per fornire un riquadro dalla tua applicazione, crea una classe che estenda
TileService
e implementa i metodi, come mostrato nel seguente esempio di codice:
Kotlin
// Uses the ProtoLayout namespace for tile timeline objects. // If you haven't done so already, migrate to the ProtoLayout namespace. import androidx.wear.protolayout.TimelineBuilders.Timeline import androidx.wear.protolayout.material.Text import androidx.wear.tiles.TileBuilders.Tile private val RESOURCES_VERSION = "1" 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_DISPLAY1) .setColor(argb(0xFF000000.toInt())) .build())) .build()) override fun onTileResourcesRequest(requestParams: ResourcesRequest) = Futures.immediateFuture(Resources.Builder() .setVersion(RESOURCES_VERSION) .build() ) }
Java
// Uses the ProtoLayout namespace for tile timeline objects. // If you haven't done so already, migrate to the ProtoLayout namespace. import androidx.wear.protolayout.TimelineBuilders.Timeline; import androidx.wear.protolayout.material.Text; import androidx.wear.tiles.TileBuilders.Tile; public class MyTileService extends TileService { private static final String RESOURCES_VERSION = "1"; @NonNull @Override protected ListenableFuture<Tile> onTileRequest( @NonNull TileRequest requestParams ) { return Futures.immediateFuture(new Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( new Text.Builder(this, "Hello world!") .setTypography(Typography.TYPOGRAPHY_DISPLAY1) .setColor(ColorBuilders.argb(0xFF000000)) .build())) .build() ); } @NonNull @Override protected ListenableFuture<Resources> onTileResourcesRequest( @NonNull ResourcesRequest requestParams ) { return Futures.immediateFuture(new Resources.Builder() .setVersion(RESOURCES_VERSION) .build() ); } }
Quindi, aggiungi un servizio all'interno del tag <application>
del
file AndroidManifest.xml
.
<service android:name=".MyTileService" android:label="@string/tile_label" android:description="@string/tile_description" android:icon="@drawable/tile_icon_round" android:roundIcon="@drawable/tile_icon_round" 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>
Il filtro di autorizzazione e intent registra questo servizio come fornitore di riquadri.
L'icona, l'etichetta e la descrizione vengono mostrate all'utente quando configura i riquadri sul suo smartphone o smartwatch.
Utilizza il tag metadati di anteprima per mostrare un'anteprima del riquadro durante la configurazione sul telefono.
Panoramica del ciclo di vita del servizio riquadri
Dopo aver creato e dichiarato TileService
nel file manifest dell'app, puoi rispondere alle modifiche di stato del servizio dei riquadri.
TileService
è un servizio associato. TileService
è vincolato a seguito della richiesta della tua app o se il sistema deve comunicare con l'app. Un tipico
ciclo di vita di bound-service include i seguenti quattro metodi di callback:
onCreate()
, onBind()
, onUnbind()
e
onDestroy()
. Il sistema li richiama ogni volta
che il servizio entra in una nuova fase del ciclo di vita.
Oltre ai callback che controllano il ciclo di vita di bound-service, puoi implementare altri metodi specifici del ciclo di vita di TileService
. Tutti i servizi
dei riquadri devono implementare onTileRequest()
e onTileResourcesRequest()
per
rispondere alle richieste di aggiornamenti dal sistema.
onTileAddEvent()
: il sistema chiama questo metodo solo quando l'utente aggiunge il riquadro per la prima volta e se l'utente lo rimuove e lo aggiunge di nuovo. Questo è il momento migliore per eseguire un'inizializzazione una tantum.onTileAddEvent()
viene chiamato solo quando l'insieme di riquadri viene riconfigurato, non quando un riquadro viene creato dal sistema. Ad esempio, quando il dispositivo viene riavviato o acceso,onTileAddEvent()
non viene chiamato per i riquadri già aggiunti. Puoi utilizzaregetActiveTilesAsync()
per ottenere un'istantanea dei riquadri di tua proprietà attivi.onTileRemoveEvent()
: il sistema chiama questo metodo solo se l'utente rimuove il tuo riquadro.onTileEnterEvent()
: il sistema chiama questo metodo quando un riquadro fornito da questo fornitore appare sullo schermo.onTileLeaveEvent()
: il sistema chiama questo metodo quando un riquadro fornito da questo fornitore non è visibile sullo schermo.onTileRequest()
: il sistema chiama questo metodo quando il sistema richiede una nuova cronologia al fornitore.onTileResourcesRequest()
: il sistema chiama questo metodo quando il sistema richiede un pacchetto di risorse al provider. Ciò può verificarsi la prima volta che un riquadro viene caricato o ogni volta che la versione della risorsa cambia.
Query sui riquadri attivi
I riquadri attivi sono riquadri che sono stati aggiunti per essere visualizzati sull'orologio. Usa il
metodo statico getActiveTilesAsync()
di TileService
per eseguire query sui riquadri
appartenenti alla tua app attivi.
Crea UI per i riquadri
Il layout di un riquadro è scritto utilizzando un pattern di creazione. Il layout di un riquadro è costituito da un albero, costituito da contenitori di layout ed elementi di layout di base. Ogni elemento del layout ha delle proprietà che puoi impostare con vari metodi di setter.
Elementi del layout di base
Sono supportati i seguenti elementi visivi della libreria protolayout
,
insieme ai componenti Material:
Text
: esegue il rendering di una stringa di testo, eventualmente a capo.Image
: consente di eseguire il rendering di un'immagine.Spacer
: fornisce spaziatura interna tra gli elementi o può fungere da divisore quando imposti il colore di sfondo.
Componenti del materiale
Oltre agli elementi di base, la libreria protolayout-material
fornisce componenti che garantiscono un design dei riquadri in linea con i suggerimenti dell'interfaccia utente di Material Design.
Button
: componente circolare cliccabile progettato per contenere un'icona.Chip
: componente cliccabile a forma di stadio progettato per contenere fino a due righe di testo e un'icona facoltativa.CompactChip
: componente a forma di stadio cliccabile progettato per contenere una riga di testo.TitleChip
: componente a forma di stadio cliccabile simile aChip
ma con un'altezza maggiore per contenere il testo del titolo.CircularProgressIndicator
: indicatore di avanzamento circolare che può essere posizionato all'interno di un elementoEdgeContentLayout
per visualizzare l'avanzamento intorno ai bordi dello schermo.
Contenitori di layout
Sono supportati i seguenti container, insieme ai layout dei materiali:
Row
: dispone gli elementi secondari orizzontalmente, uno dopo l'altro.Column
: dispone gli elementi secondari verticalmente, uno dopo l'altro.Box
: consente di sovrapporre gli elementi secondari uno sopra l'altro.Arc
: dispone gli elementi secondari in un cerchio.Spannable
: si applica a sezioni di testo specificheFontStyles
insieme a testo e immagini interfolianti. Per ulteriori informazioni, consulta la sezione Spannable.
Ogni container può contenere uno o più elementi secondari, che a loro volta possono essere anche
container. Ad esempio, un elemento Column
può contenere più elementi Row
come elementi secondari, il che genera un layout di griglia.
Ad esempio, un riquadro con un layout del contenitore e due elementi secondari di layout potrebbe avere il seguente aspetto:
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(); }
Layout dei materiali
Oltre ai layout di base, la libreria protolayout-material
fornisce alcuni layout di opinione pensati per contenere elementi in "slot" specifici.
PrimaryLayout
: posiziona una singola azione principaleCompactChip
in basso con i contenuti centrati sopra.MultiSlotLayout
: posiziona le etichette principali e secondarie con contenuti facoltativi intermedi e unCompactChip
facoltativo in basso.MultiButtonLayout
: consente di posizionare un insieme di pulsanti disposti secondo le linee guida sui materiali.EdgeContentLayout
: posiziona i contenuti intorno al bordo dello schermo, ad esempio unCircularProgressIndicator
. Quando usi questo layout, ai contenuti al suo interno vengono applicati automaticamente i margini e la spaziatura interna appropriati.
Archi
Sono supportati i seguenti container Arc
secondari:
ArcLine
: esegue il rendering di una linea curva intorno all'arco.ArcText
: visualizza il testo inclinato nell'arco.ArcAdapter
: visualizza un elemento di layout di base nell'arco, disegnato in base a una tangente all'arco.
Per ulteriori informazioni, consulta la documentazione di riferimento per ciascun tipo di elemento.
Modificatori
A ogni elemento di layout disponibile è possibile applicare facoltativamente modificatori. Utilizza questi modificatori per i seguenti scopi:
- Modificare l'aspetto visivo del layout. Ad esempio, aggiungi uno sfondo, un bordo o una spaziatura interna all'elemento del layout.
- Aggiungi metadati relativi al layout. Ad esempio, aggiungi un modificatore di semantica all'elemento del layout per utilizzarlo con gli screen reader.
- Aggiungi funzionalità. Ad esempio, aggiungi un modificatore cliccabile all'elemento di layout per rendere interattivo il riquadro. Per maggiori informazioni, consulta Interagire con i riquadri.
Ad esempio, possiamo personalizzare l'aspetto e i metadati predefiniti di una Image
, come mostrato nel seguente esempio di codice:
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(); }
Estraibili
Un Spannable
è un tipo speciale di contenitore che dispone gli elementi in modo simile al testo. Questo è utile quando vuoi applicare uno stile diverso a una sola
sottostringa in un blocco di testo più grande, cosa che non è possibile con l'elemento
Text
.
Un container Spannable
contiene
Span
elementi secondari. Non sono consentiti altri elementi secondari o istanze Spannable
nidificate.
Esistono due tipi di elementi secondari Span
:
SpanText
: visualizza il testo con uno stile specifico.SpanImage
: visualizza un'immagine in linea con il testo.
Ad esempio, puoi mettere in corsivo la parola "mondo" in un riquadro "Hello world" e inserire un'immagine tra le parole, come mostrato nel seguente esempio di codice:
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(); }
Lavorare con le risorse
I riquadri non hanno accesso ad alcuna risorsa della tua app. Ciò significa che
non puoi passare un ID immagine Android a un elemento di layout Image
e aspettarti che venga risolto. Puoi invece sostituire il metodo onTileResourcesRequest()
e fornire le risorse manualmente.
Esistono due modi per fornire immagini con il
metodo onTileResourcesRequest()
:
- Fornisci una risorsa disegnabile utilizzando
setAndroidResourceByResId()
. - Fornisci un'immagine dinamica come
ByteArray
utilizzandosetInlineResource()
.
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() ); }
Consigliato per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Dati attivi ed allenamenti
- Aggiornamenti di dati passivi
- Aggiungere una schermata iniziale