Na urządzeniach z Wear OS kafelki są renderowane przez 2 kluczowe komponenty z niezależnym wersjonowaniem. Aby mieć pewność, że kafelki aplikacji działają prawidłowo na wszystkich urządzeniach, musisz zrozumieć tę podstawową architekturę.
- Biblioteki związane z kafelkami Jetpacka: te biblioteki (w tym Wear Tiles i Wear ProtoLayout) są osadzone w aplikacji, a Ty jako deweloper kontrolujesz ich wersje. Aplikacja korzysta z tych bibliotek, aby w odpowiedzi na wywołanie
onTileRequest()
systemu utworzyć obiektTileBuilder.Tile
(strukturę danych reprezentującą kafelek). - ProtoLayout Renderer: ten komponent systemu odpowiada za renderowanie obiektu
Tile
na wyświetlaczu i zarządzanie interakcjami użytkownika. Wersja renderera nie jest kontrolowana przez dewelopera aplikacji i może się różnić na różnych urządzeniach, nawet tych z identycznym sprzętem.
Wygląd i zachowanie kafelka mogą się różnić w zależności od wersji biblioteki Jetpack Tiles w aplikacji oraz wersji interfejsu ProtoLayout Renderer na urządzeniu użytkownika. Na przykład jedno urządzenie może obsługiwać obrót lub wyświetlanie danych o tętnie, a drugie nie.
Z tego dokumentu dowiesz się, jak zapewnić zgodność aplikacji z różnymi wersjami biblioteki Tiles i renderowania ProtoLayout oraz jak przejść na nowsze wersje biblioteki Jetpack.
Zgodność
Aby utworzyć kafelek, który działa prawidłowo na różnych urządzeniach, weź pod uwagę te kwestie.
Wykrywanie wersji renderera
- Użyj metody
getRendererSchemaVersion()
obiektuDeviceParameters
przekazanego do metody onTileRequest(). Ta metoda zwraca główne i mniejsze numery wersji interfejsu API ProtoLayout na urządzeniu. - Następnie możesz użyć logiki warunkowej w implementacji
onTileRequest()
, aby dostosować wygląd lub zachowanie kafelka na podstawie wykrytej wersji renderera.- Jeśli na przykład dana animacja nie jest obsługiwana, możesz wyświetlić obraz statyczny.
Adnotacja @RequiresSchemaVersion
- Adnotacja
@RequiresSchemaVersion
przy metodzie ProtoLayout wskazuje minimalną wersję schematu renderera wymaganą, aby ta metoda działała zgodnie z opisem (przykład).- Mimo że wywołanie metody, która wymaga nowszej wersji renderera niż ta dostępna na urządzeniu, nie spowoduje awarii aplikacji, może spowodować, że treści nie będą wyświetlane lub funkcja zostanie zignorowana.
Przykład
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())
}
Testowanie z różnymi wersjami silnika
Aby przetestować kafelki w różnych wersjach silnika renderowania, wdrocz je w różnych wersjach emulatora Wear OS. (Na urządzeniach fizycznych aktualizacje biblioteki ProtoLayout Renderer są dostarczane przez Sklep Play lub aktualizacje systemu. Nie można wymusić instalacji określonej wersji modułu renderującego.)
Funkcja podglądu kafelków w Android Studio korzysta z renderowania zawartego w bibliotece Jetpack ProtoLayout, na której opiera się kod. Innym podejściem jest korzystanie z różnych wersji biblioteki Jetpack podczas testowania kafelków.
Migracja do wersji Tiles 1.5 lub ProtoLayout 1.3 (Material 3 Expressive)
Zaktualizuj biblioteki Jetpack Tile, aby korzystać z najnowszych ulepszeń, w tym zmian interfejsu, które umożliwiają płynną integrację kafelków z systemem.
Wersje Jetpack Tiles 1.5 i Jetpack ProtoLayout 1.3 wprowadzają kilka istotnych ulepszeń i zmian. Należą do nich:
- Interfejs API podobny do Compose do opisywania interfejsu użytkownika.
- Komponenty Material 3 Expressive, w tym przycisk z zaokrąglonymi krawędziami u dołu, oraz obsługa ulepszonych wizualizacji: animacji Lottie, większej liczby typów gradientów i nowych stylów łuków. – Uwaga: niektórych z tych funkcji można używać bez migracji do nowego interfejsu API.
Rekomendacje
- Przenieś wszystkie karty jednocześnie. Unikaj mieszania wersji kafelków w aplikacji. Chociaż komponenty Material 3 znajdują się w oddzielnym pliku (
androidx.wear.protolayout:protolayout-material3
), co technicznie umożliwia używanie w tej samej aplikacji zarówno kafelków M2.5, jak i M3, zdecydowanie odradzamy stosowanie tego podejścia, chyba że jest to absolutnie konieczne (np. jeśli aplikacja zawiera dużą liczbę kafelków, których nie da się przenieść naraz). - Zastosowanie wskazówek dotyczących UX kafelków. Biorąc pod uwagę to, że kafelki są bardzo uporządkowane i stworzone na podstawie szablonów, za punkt wyjścia do własnych projektów użyj projektów z dotychczasowych przykładów.
- Testuj na różnych ekranach i przy różnych rozmiarach czcionki. Płytki często zawierają dużo informacji, przez co tekst (zwłaszcza umieszczony na przyciskach) może być za długi lub przycięty. Aby zminimalizować ryzyko, używaj gotowych komponentów i unikaj rozbudowanych dostosowań. Przetestuj projekt, korzystając z funkcji podglądu układu w Android Studio, a także na wielu rzeczywistych urządzeniach.
Proces migracji
Aktualizowanie zależności
Najpierw zaktualizuj plik build.gradle.kts
. Zaktualizuj wersje i zmień zależność protolayout-material
na protolayout-material3
, jak pokazano poniżej:
// 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")
}
Usługa TileService pozostaje w dużej mierze niezmieniona
Główne zmiany w ramach tej migracji dotyczą komponentów interfejsu użytkownika. W związku z tym implementacja TileService
, w tym wszelkie mechanizmy ładowania zasobów, powinna wymagać minimalnych modyfikacji lub nie wymagać ich wcale.
Główne wyjątki dotyczą śledzenia aktywności na kafelku: jeśli Twoja aplikacja używa funkcji onTileEnterEvent()
lub onTileLeaveEvent()
, musisz przejść na onRecentInteractionEventsAsync()
. Od wersji API 36 te zdarzenia będą grupowane.
Dostosowywanie kodu generowania układu
W ProtoLayout 1.2 (M2.5) metoda onTileRequest()
zwraca TileBuilders.Tile
. Obiekt zawierał różne elementy, w tym TimelineBuilders.Timeline
, który z kolei zawierał LayoutElement
opis interfejsu kafelka.
W ProtoLayout 1.3 (M3) ogólna struktura danych i przepływ danych nie uległy zmianie, ale element LayoutElement
jest teraz tworzony w sposób zainspirowany Compose, z układem opartym na zdefiniowanych miejscach, które są (od góry do dołu) titleSlot
(zazwyczaj tytuł główny lub nagłówek), mainSlot
(główna treść) i bottomSlot
(często działania takie jak przycisk krawędziowy lub dodatkowe informacje, np. krótki tekst). Ten układ jest tworzony przez funkcję primaryLayout()
.

Porównanie funkcji układu M2.5 i 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) })
}
Oto najważniejsze różnice:
- Usunięcie Builders. Tradycyjny wzór konstruktora dla komponentów UI Material3 został zastąpiony bardziej deklaratywną składnią inspirowaną Compose. (Nowe wrappery Kotlina otrzymują też komponenty inne niż UI, takie jak ciągi znaków, kolory i modyfikatory).
- Standardowe funkcje inicjowania i układania. Układy M3 korzystają ze sformalizowanych funkcji inicjalizowania i tworzenia struktury:
materialScope()
iprimaryLayout()
. Te obowiązkowe funkcje inicjują środowisko M3 (motyw, zakres komponentu za pomocąmaterialScope
) i określają układ główny na podstawie slotu (za pomocąprimaryLayout
). Obie muszą być wywoływane dokładnie raz na układ.
Motywy
Kolor
Wyróżniającą cechą Material 3 Expressive jest „dynamiczne motywy”. Płytki, które mają włączoną tę funkcję (domyślnie), będą wyświetlane w ramach motywu udostępnionego przez system (dostępność zależy od urządzenia i konfiguracji użytkownika).
Kolejną zmianą w M3 jest zwiększenie liczby tokenów kolorów z 4 do 29. Nowe tokeny kolorów znajdziesz w klasie ColorScheme
.
Typografia
Podobnie jak M2.5, M3 w dużej mierze korzysta z wstępnie zdefiniowanych stałych rozmiarów czcionki. Nie zalecamy bezpośredniego określania rozmiaru czcionki. Te stałe znajdują się w klasie Typography
i zapewniają nieco szerszy zakres bardziej wyrazistych opcji.
Szczegółowe informacje znajdziesz w dokumentacji dotyczącej typografii.
Kształt
Większość komponentów M3 może się różnić pod względem kształtu i koloru.
textButton
(w mainSlot
) o kształcie full
:

Ten sam przycisk tekstowy o kształcie small
:

Komponenty
Komponenty M3 są znacznie bardziej elastyczne i możliwe do skonfigurowania niż ich odpowiedniki M2.5. Podczas gdy M2.5 często wymagało oddzielnych komponentów do różnych wizualnych efektów, M3 często wykorzystuje ogólny, ale bardzo konfigurowalny „podstawowy” komponent z dobrymi wartościami domyślnymi.
Ta zasada dotyczy układu „root”. W wersji M2.5 był to element PrimaryLayout
lub EdgeContentLayout
. W M3 po utworzeniu pojedynczej funkcji MaterialScope
najwyższego poziomu wywoływana jest funkcja primaryLayout()
. Zwraca ona bezpośrednio główny układ (nie trzeba używać żadnych narzędzi do tworzenia). Akceptuje ona LayoutElements
w kilku „boksach”, np. titleSlot
, mainSlot
i bottomSlot
. Te sloty mogą być wypełniane konkretnymi komponentami UI, takimi jak zwracane przez text(), button() lub card(), lub struktury układu, takie jak Row
lub Column
z LayoutElementBuilders
.
Motywy to kolejne ważne ulepszenie M3. Domyślnie elementy interfejsu użytkownika automatycznie stosują specyfikacje stylów M3 i obsługują dynamiczne motywy.
M2,5 | M3 |
---|---|
Elementy interaktywne | |
Button lub Chip |
|
Text | |
Text |
text() |
Wskaźniki postępu | |
CircularProgressIndicator |
circularProgressIndicator() lub segmentedCircularProgressIndicator() |
Układ | |
PrimaryLayout lub EdgeContentLayout |
primaryLayout() |
– | buttonGroup() |
Obrazy | |
– | icon() , avatarImage() lub backgroundImage() |
Modyfikatory
W M3 elementy Modifiers
, których używasz do dekorowania lub rozszerzania komponentu, są bardziej podobne do elementów w Compose. Ta zmiana może zmniejszyć ilość kodu stałego dzięki automatycznemu tworzeniu odpowiednich typów wewnętrznych. (Ta zmiana jest niezależna od korzystania z komponentów UI M3. W razie potrzeby możesz używać modyfikatorów w stylu kreatora z ProtoLayout 1.2 z komponentami UI M3 i na odwrót).
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)
Możesz tworzyć modyfikatory, używając dowolnego stylu interfejsu API. Możesz też użyć funkcji rozszerzenia toProtoLayoutModifiers()
, aby przekształcić LayoutModifier
w ModifiersBuilders.Modifier
.
Funkcje pomocnicze
Chociaż interfejs ProtoLayout 1.3 umożliwia definiowanie wielu komponentów UI za pomocą interfejsu API inspirowanego Compose, podstawowe elementy układu, takie jak wiersze i kolumny z LayoutElementBuilders
, nadal korzystają z schematu konstruktora. Aby zniwelować tę różnicę stylistyczną i zapewnić spójność z nowymi interfejsami API komponentów M3, rozważ użycie funkcji pomocniczych.
Bez pomocy
primaryLayout(
mainSlot = {
LayoutElementBuilders.Column.Builder()
.setWidth(expand())
.setHeight(expand())
.addContent(text("A".layoutString))
.addContent(text("B".layoutString))
.addContent(text("C".layoutString))
.build()
}
)
Z pomocnikami
// 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))
}
}
)
Migracja do wersji 1.2 usługi Tiles lub ProtoLayout 1.0
Od wersji 1.2 większość interfejsów API układu kafelków znajduje się w przestrzeni nazw androidx.wear.protolayout
. Aby korzystać z najnowszych interfejsów API, wykonaj w kodu te czynności związane z migracją.
Aktualizowanie zależności
W pliku kompilacji modułu aplikacji wprowadź te zmiany:
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")
Aktualizowanie przestrzeni nazw
W plikach kodu Kotlina i Javę w aplikacji wprowadź te zmiany. Możesz też uruchomić ten skrypt do zmiany nazwy przestrzeni nazw.
- Zastąp wszystkie importowane dane
androidx.wear.tiles.material.*
elementemandroidx.wear.protolayout.material.*
. Wykonaj ten krok również w przypadku bibliotekiandroidx.wear.tiles.material.layouts
. Zastąp większość innych importowanych ontologii
androidx.wear.tiles.*
ontologiąandroidx.wear.protolayout.*
.Importy dotyczące zasad
androidx.wear.tiles.EventBuilders
,androidx.wear.tiles.RequestBuilders
,androidx.wear.tiles.TileBuilders
iandroidx.wear.tiles.TileService
powinny pozostać bez zmian.Zmieniono nazwy kilku przestarzałych metod z klas TileService i TileBuilder:
TileBuilders
:getTimeline()
togetTileTimeline()
, asetTimeline()
tosetTileTimeline()
TileService
: zonResourcesRequest()
naonTileResourcesRequest()
RequestBuilders.TileRequest
:getDeviceParameters()
zmieni się nagetDeviceConfiguration()
,setDeviceParameters()
nasetDeviceConfiguration()
,getState()
nagetCurrentState()
, asetState()
nasetCurrentState()