Sur les appareils Wear OS, les cartes sont affichées par deux composants clés avec une gestion des versions indépendante. Pour vous assurer que les cartes de vos applications fonctionnent correctement sur tous les appareils, il est important de comprendre cette architecture sous-jacente.
- Bibliothèques liées aux cartes Jetpack: ces bibliothèques (y compris Wear Tiles et Wear ProtoLayout) sont intégrées à votre application, et vous, en tant que développeur, contrôlez leurs versions. Votre application utilise ces bibliothèques pour créer un objet
TileBuilder.Tile
(la structure de données représentant votre carte) en réponse à l'appelonTileRequest()
du système. - ProtoLayout Renderer:ce composant système est responsable de l'affichage de l'objet
Tile
à l'écran et de la gestion des interactions utilisateur. La version du moteur de rendu n'est pas contrôlée par le développeur de l'application et peut varier d'un appareil à l'autre, même ceux dont le matériel est identique.
L'apparence ou le comportement d'une carte peut varier en fonction des versions de la bibliothèque Jetpack Tiles de votre application et de la version du moteur de rendu ProtoLayout sur l'appareil de l'utilisateur. Par exemple, un appareil peut prendre en charge la rotation ou l'affichage des données de fréquence cardiaque, et un autre non.
Ce document explique comment vous assurer que votre application est compatible avec différentes versions de la bibliothèque Tiles et du moteur de rendu ProtoLayout, et comment migrer vers des versions supérieures de la bibliothèque Jetpack.
Tenir compte de la compatibilité
Pour créer une carte qui fonctionne correctement sur une gamme d'appareils, vous devez tenir compte des points suivants.
Détecter la version du moteur de rendu
- Utilisez la méthode
getRendererSchemaVersion()
de l'objetDeviceParameters
transmis à votre méthode onTileRequest(). Cette méthode renvoie les numéros de version majeure et mineure du moteur de rendu ProtoLayout sur l'appareil. - Vous pouvez ensuite utiliser une logique conditionnelle dans votre implémentation
onTileRequest()
pour adapter la conception ou le comportement de votre carte en fonction de la version du moteur de rendu détectée.- Par exemple, si une animation spécifique n'est pas prise en charge, vous pouvez afficher une image statique à la place.
@RequiresSchemaVersion
annotation
- L'annotation
@RequiresSchemaVersion
sur les méthodes ProtoLayout indique la version minimale du schéma du moteur de rendu requise pour que cette méthode se comporte comme indiqué dans la documentation (exemple).- Bien que l'appel d'une méthode nécessitant une version de rendu supérieure à celle disponible sur l'appareil ne provoque pas le plantage de votre application, il peut entraîner l'absence d'affichage du contenu ou l'ignorer.
Exemple
override fun onTileRequest(
requestParams: TileService.TileRequest
): ListenableFuture<Tile> {
val rendererVersion =
requestParams.deviceConfiguration.rendererSchemaVersion
val tile = Tile.Builder()
if (
rendererVersion.major > 1 ||
(rendererVersion.major == 1 && rendererVersion.minor >= 300)
) {
// Use a feature supported in renderer version 1.300 or later
tile.setTileTimeline(/* ... */ )
} else {
// Provide fallback content for older renderers
tile.setTileTimeline(/* ... */ )
}
return Futures.immediateFuture(tile.build())
}
Tester avec différentes versions du moteur de rendu
Pour tester vos cartes sur différentes versions de moteur de rendu, déployez-les sur différentes versions de l'émulateur Wear OS. (Sur les appareils physiques, les mises à jour du moteur de rendu ProtoLayout sont fournies par le Play Store ou les mises à jour du système. Il n'est pas possible de forcer l'installation d'une version de rendu spécifique.)
La fonctionnalité d'aperçu des cartes d'Android Studio utilise un moteur de rendu intégré à la bibliothèque Jetpack ProtoLayout sur laquelle votre code dépend. Une autre approche consiste donc à dépendre de différentes versions de la bibliothèque Jetpack lors des tests des cartes.
Migrer vers Tiles 1.5 / ProtoLayout 1.3 (Material 3 Expressive)
Mettez à jour vos bibliothèques de cartes Jetpack pour profiter des dernières améliorations, y compris des modifications de l'interface utilisateur pour intégrer vos cartes de manière transparente au système.
Jetpack Tiles 1.5 et Jetpack ProtoLayout 1.3 apportent plusieurs améliorations et modifications notables. En voici quelques exemples :
- API semblable à Compose pour décrire l'UI.
- Composants Material 3 Expressive, y compris le bouton de bord inférieur et la prise en charge des visuels améliorés: animations Lottie, plus de types de dégradés et nouveaux styles de lignes d'arc. - Remarque: certaines de ces fonctionnalités peuvent également être utilisées sans migrer vers la nouvelle API.
Recommandations
- Migrer toutes vos cartes simultanément Évitez de mélanger les versions de cartes dans votre application. Bien que les composants Material 3 résident dans un artefact distinct (
androidx.wear.protolayout:protolayout-material3
), ce qui rend techniquement possible d'utiliser à la fois des cartes M2.5 et M3 dans la même application, nous vous déconseillons vivement cette approche, sauf si elle est absolument nécessaire (par exemple, si votre application comporte un grand nombre de cartes qui ne peuvent pas toutes être migrées en même temps). - Suivez les consignes relatives à l'expérience utilisateur des cartes. Compte tenu de la nature hautement structurée et modélisée des cartes, utilisez les conceptions des exemples existants comme point de départ pour vos propres conceptions.
- Testez sur différentes tailles d'écran et de police. Les cartes sont souvent denses en informations, ce qui rend le texte (en particulier lorsqu'il est placé sur des boutons) susceptible de déborder et d'être coupé. Pour réduire ce problème, utilisez les composants prédéfinis et évitez toute personnalisation étendue. Effectuez des tests à l'aide de la fonction d'aperçu des cartes d'Android Studio, ainsi que sur plusieurs appareils physiques.
Processus de migration
Mettre à jour les dépendances
Commencez par mettre à jour votre fichier build.gradle.kts
. Mettez à jour les versions et remplacez la dépendance protolayout-material
par protolayout-material3
, comme illustré:
// In build.gradle.kts
//val tilesVersion = "1.4.1"
//val protoLayoutVersion = "1.2.1"
// Use these versions for M3.
val tilesVersion = "1.5.0-rc01"
val protoLayoutVersion = "1.3.0-rc01"
dependencies {
// Use to implement support for wear tiles
implementation("androidx.wear.tiles:tiles:$tilesVersion")
// Use to utilize standard components and layouts in your tiles
implementation("androidx.wear.protolayout:protolayout:$protoLayoutVersion")
// Use to utilize components and layouts with Material Design in your tiles
// implementation("androidx.wear.protolayout:protolayout-material:$protoLayoutVersion")
implementation("androidx.wear.protolayout:protolayout-material3:$protoLayoutVersion")
// Use to include dynamic expressions in your tiles
implementation("androidx.wear.protolayout:protolayout-expression:$protoLayoutVersion")
// Use to preview wear tiles in your own app
debugImplementation("androidx.wear.tiles:tiles-renderer:$tilesVersion")
// Use to fetch tiles from a tile provider in your tests
testImplementation("androidx.wear.tiles:tiles-testing:$tilesVersion")
}
TileService reste largement inchangé
Les principales modifications de cette migration affectent les composants de l'interface utilisateur. Par conséquent, votre implémentation de TileService
, y compris les mécanismes de chargement de ressources, ne devrait nécessiter que des modifications minimales, voire aucune.
La principale exception concerne le suivi de l'activité des cartes: si votre application utilise onTileEnterEvent()
ou onTileLeaveEvent()
, vous devez migrer vers onRecentInteractionEventsAsync()
. À partir de l'API 36, ces événements seront groupés.
Adapter votre code de génération de mise en page
Dans ProtoLayout 1.2 (M2.5), la méthode onTileRequest()
renvoie un TileBuilders.Tile
. Cet objet contenait divers éléments, y compris un TimelineBuilders.Timeline
, qui contenait à son tour le LayoutElement
décrivant l'UI de la carte.
Avec ProtoLayout 1.3 (M3), bien que la structure et le flux de données globaux n'aient pas changé, le LayoutElement
est désormais construit à l'aide d'une approche inspirée de Compose, avec une mise en page basée sur des emplacements définis, qui sont (de haut en bas) le titleSlot
(généralement pour un titre ou un en-tête principal), le mainSlot
(pour le contenu principal) et le bottomSlot
(souvent pour des actions telles qu'un bouton de bord ou des informations supplémentaires telles qu'un texte court). Cette mise en page est créée par la fonction primaryLayout()
.

Comparaison des fonctions de mise en page M2.5 et M3
M2.5
fun myLayout(
context: Context,
deviceConfiguration: DeviceParametersBuilders.DeviceParameters
) =
PrimaryLayout.Builder(deviceConfiguration)
.setResponsiveContentInsetEnabled(true)
.setContent(
Text.Builder(context, "Hello World!")
.setTypography(Typography.TYPOGRAPHY_BODY1)
.setColor(argb(0xFFFFFFFF.toInt()))
.build()
)
.build()
M3
fun myLayout(
context: Context,
deviceConfiguration: DeviceParametersBuilders.DeviceParameters,
) =
materialScope(context, deviceConfiguration) {
primaryLayout(mainSlot = { text("Hello, World!".layoutString) })
}
Pour mettre en évidence les principales différences:
- Suppression des outils de création Le modèle de constructeur traditionnel pour les composants d'interface utilisateur Material3 est remplacé par une syntaxe plus déclarative, inspirée de Compose. (Les composants autres que l'UI tels que String/Color/Modifiers reçoivent également de nouveaux wrappers Kotlin.)
- Fonctions d'initialisation et de mise en page standardisées Les mises en page M3 s'appuient sur des fonctions d'initialisation et de structuration standardisées:
materialScope()
etprimaryLayout()
. Ces fonctions obligatoires initialisent l'environnement M3 (thématisation, portée du composant viamaterialScope
) et définissent la mise en page principale basée sur les emplacements (viaprimaryLayout
). Les deux doivent être appelées exactement une fois par mise en page.
Personnalisation des thèmes
Couleur
Une fonctionnalité remarquable de Material 3 Expressive est la thématisation dynamique : les cartes qui activent cette fonctionnalité (activée par défaut) s'affichent dans le thème fourni par le système (la disponibilité dépend de l'appareil et de la configuration de l'utilisateur).
Autre modification apportée dans M3 : le nombre de jetons de couleur est passé de 4 à 29. Les nouveaux jetons de couleur se trouvent dans la classe ColorScheme
.
Typographie
Comme M2.5, M3 s'appuie fortement sur des constantes de taille de police prédéfinies. Il est déconseillé de spécifier directement une taille de police. Ces constantes se trouvent dans la classe Typography
et offrent une gamme légèrement élargie d'options plus expressives.
Pour en savoir plus, consultez la documentation sur la typographie.
Forme
La plupart des composants M3 peuvent varier en termes de forme et de couleur.
Un textButton
(dans le mainSlot
) avec la forme full
:

Même bouton de texte avec la forme small
:

Composants
Les composants M3 sont beaucoup plus flexibles et configurables que leurs homologues M2.5. Alors que M2.5 nécessitait souvent des composants distincts pour des traitements visuels variés, M3 utilise fréquemment un composant de base généralisé, mais hautement configurable, avec de bonnes valeurs par défaut.
Ce principe s'applique à la mise en page racine. Dans M2.5, il s'agissait d'un PrimaryLayout
ou d'un EdgeContentLayout
. Dans M3, une fois qu'un seul MaterialScope
de niveau supérieur est établi, la fonction primaryLayout()
est appelée. Cela renvoie directement la mise en page racine (aucun compilateur n'est nécessaire) et accepte LayoutElements
pour plusieurs "emplacements", tels que titleSlot
, mainSlot
et bottomSlot
. Ces emplacements peuvent être remplis avec des composants d'UI concrets (tels que renvoyés par text(), button() ou card()) ou des structures de mise en page, telles que Row
ou Column
à partir de LayoutElementBuilders
.
Les thèmes constituent une autre amélioration majeure de M3. Par défaut, les éléments d'interface utilisateur respectent automatiquement les spécifications de style M3 et sont compatibles avec la thématisation dynamique.
M2.5 | M3 |
---|---|
Éléments interactifs | |
Button ou Chip |
|
Texte | |
Text |
text() |
Indicateurs de progression | |
CircularProgressIndicator |
circularProgressIndicator() ou segmentedCircularProgressIndicator() |
Disposition | |
PrimaryLayout ou EdgeContentLayout |
primaryLayout() |
— | buttonGroup() |
Images | |
— | icon() , avatarImage() ou backgroundImage() |
Modificateurs
Dans M3, Modifiers
, que vous utilisez pour décorer ou améliorer un composant, ressemble davantage à Compose. Cette modification peut réduire le code standard en construisant automatiquement les types internes appropriés. (Cette modification est orthogonale à l'utilisation des composants d'interface utilisateur M3. Si nécessaire, vous pouvez utiliser des modificateurs de style de compilateur à partir de ProtoLayout 1.2 avec les composants d'interface utilisateur M3, et inversement.)
M2.5
// A Builder-style modifier to set the opacity of an element to 0.5
fun myModifier(): ModifiersBuilders.Modifiers =
ModifiersBuilders.Modifiers.Builder()
.setOpacity(TypeBuilders.FloatProp.Builder(0.5F).build())
.build()
M3
// The equivalent Compose-like modifier is much simpler
fun myModifier(): LayoutModifier = LayoutModifier.opacity(0.5F)
Vous pouvez créer des modificateurs à l'aide de l'un ou l'autre style d'API. Vous pouvez également utiliser la fonction d'extension toProtoLayoutModifiers()
pour convertir un LayoutModifier
en ModifiersBuilders.Modifier
.
Fonctions d'assistance
Bien que ProtoLayout 1.3 permette d'exprimer de nombreux composants d'interface utilisateur à l'aide d'une API inspirée de Compose, les éléments de mise en page de base tels que les lignes et les colonnes de LayoutElementBuilders
continuent d'utiliser le modèle de compilateur. Pour combler cette lacune stylistique et favoriser la cohérence avec les nouvelles API de composants M3, envisagez d'utiliser des fonctions d'assistance.
Sans assistants
primaryLayout(
mainSlot = {
LayoutElementBuilders.Column.Builder()
.setWidth(expand())
.setHeight(expand())
.addContent(text("A".layoutString))
.addContent(text("B".layoutString))
.addContent(text("C".layoutString))
.build()
}
)
Avec assistants
// Function literal with receiver helper function
fun column(builder: Column.Builder.() -> Unit) =
Column.Builder().apply(builder).build()
primaryLayout(
mainSlot = {
column {
setWidth(expand())
setHeight(expand())
addContent(text("A".layoutString))
addContent(text("B".layoutString))
addContent(text("C".layoutString))
}
}
)
Migrer vers Tiles 1.2 / ProtoLayout 1.0
Depuis la version 1.2, la plupart des API de mise en page de cartes se trouvent dans l'espace de noms androidx.wear.protolayout
. Pour utiliser les dernières API, suivez la procédure de migration suivante dans votre code.
Mettre à jour les dépendances
Dans le fichier de compilation de votre module d'application, apportez les modifications suivantes :
Groovy
// Removeimplementation 'androidx.wear.tiles:tiles-material:version'// Include additional dependencies implementation "androidx.wear.protolayout:protolayout:1.2.1" implementation "androidx.wear.protolayout:protolayout-material:1.2.1" implementation "androidx.wear.protolayout:protolayout-expression:1.2.1" // Update implementation "androidx.wear.tiles:tiles:1.4.1"
Kotlin
// Removeimplementation("androidx.wear.tiles:tiles-material:version")// Include additional dependencies implementation("androidx.wear.protolayout:protolayout:1.2.1") implementation("androidx.wear.protolayout:protolayout-material:1.2.1") implementation("androidx.wear.protolayout:protolayout-expression:1.2.1") // Update implementation("androidx.wear.tiles:tiles:1.4.1")
Mettre à jour les espaces de noms
Dans les fichiers de code basés sur Kotlin et Java de votre application, effectuez les mises à jour suivantes. Vous pouvez également exécuter ce script de modification du nom d'un espace de noms.
- Remplacez toutes les importations
androidx.wear.tiles.material.*
parandroidx.wear.protolayout.material.*
. Effectuez également cette étape pour la bibliothèqueandroidx.wear.tiles.material.layouts
. Remplacez la plupart des autres importations
androidx.wear.tiles.*
parandroidx.wear.protolayout.*
.Les importations pour
androidx.wear.tiles.EventBuilders
,androidx.wear.tiles.RequestBuilders
,androidx.wear.tiles.TileBuilders
etandroidx.wear.tiles.TileService
ne doivent pas changer.Renommez quelques méthodes obsolètes des classes TileService et TileBuilder :
TileBuilders
:getTimeline()
engetTileTimeline()
, etsetTimeline()
ensetTileTimeline()
TileService
:onResourcesRequest()
enonTileResourcesRequest()
RequestBuilders.TileRequest
:getDeviceParameters()
engetDeviceConfiguration()
,setDeviceParameters()
ensetDeviceConfiguration()
,getState()
engetCurrentState()
, etsetState()
ensetCurrentState()