Pierwsze kroki z kafelkami


Aby zacząć udostępniać kafelki z aplikacji, dodaj te zależności do pliku build.gradle aplikacji.

Odlotowe

dependencies {
    // Use to implement support for wear tiles
    implementation "androidx.wear.tiles:tiles:1.6.2"

    // Use to utilize standard components and layouts in your tiles
    implementation "androidx.wear.protolayout:protolayout:1.4.2"

    // Use to utilize components and layouts with Material Design in your tiles
    implementation "androidx.wear.protolayout:protolayout-material:1.4.2"

    // Use to include dynamic expressions in your tiles
    implementation "androidx.wear.protolayout:protolayout-expression:1.4.2"

    // Use to preview wear tiles in your own app
    debugImplementation "androidx.wear.tiles:tiles-renderer:1.6.2"

    // Use to fetch tiles from a tile provider in your tests
    testImplementation "androidx.wear.tiles:tiles-testing:1.6.2"
}

Kotlin

dependencies {
    // Use to implement support for wear tiles
    implementation("androidx.wear.tiles:tiles:1.6.2")

    // Use to utilize standard components and layouts in your tiles
    implementation("androidx.wear.protolayout:protolayout:1.4.2")

    // Use to utilize components and layouts with Material Design in your tiles
    implementation("androidx.wear.protolayout:protolayout-material:1.4.2")

    // Use to include dynamic expressions in your tiles
    implementation("androidx.wear.protolayout:protolayout-expression:1.4.2")

    // Use to preview wear tiles in your own app
    debugImplementation("androidx.wear.tiles:tiles-renderer:1.6.2")

    // Use to fetch tiles from a tile provider in your tests
    testImplementation("androidx.wear.tiles:tiles-testing:1.6.2")
}

Kluczowych pojęć

Kafelki nie są tworzone w taki sam sposób jak aplikacje na Androida i wykorzystują inne koncepcje:

  • Szablony układu: określają ogólny układ elementów wizualnych na wyświetlaczu. Można to zrobić za pomocą funkcji primaryLayout().
  • Elementy układu:reprezentują pojedynczy element graficzny, np. przycisk lub kartę, albo kilka takich elementów zgrupowanych za pomocą kolumny, buttonGroup lub podobnego elementu. Są one umieszczone w szablonie układu.
  • Zasoby: obiekty ResourceBuilders.Resources składają się z mapy par klucz-wartość zasobów Androida (obrazów) wymaganych do renderowania układu oraz z wersji.
  • Oś czasu: obiekt TimelineBuilders.Timeline to lista co najmniej 1 instancji obiektu układu. Możesz podać różne mechanizmy i wyrażenia, aby wskazać, kiedy moduł renderujący ma przełączyć się z jednego obiektu układu na inny, np. aby przestać wyświetlać układ o określonej godzinie.
  • Stan: struktura danych typu StateBuilders.State, która jest przekazywana między kafelkiem a aplikacją, aby umożliwić komunikację między tymi 2 komponentami. Jeśli na przykład na kafelku klikniesz przycisk, stan będzie zawierać identyfikator tego przycisku. Możesz też wymieniać typy danych za pomocą mapy.
  • Kafelek: obiekt TileBuilders.Tile reprezentujący kafelek, składający się z osi czasu, identyfikatora wersji zasobów, interwału świeżości i stanu.
  • Protolayout: ten termin pojawia się w nazwach różnych klas związanych z kafelkami i odnosi się do biblioteki Protolayout na Wear OS, czyli biblioteki graficznej używanej na różnych platformach Wear OS.

Tworzenie kafelka

Użyj Material3TileService (zalecane)

Podczas tworzenia kafelków Material 3 (androidx.wear.tiles:tiles:1.6.0 i wyższych) zawsze rozszerzaj klasę Material3TileService zamiast klasy niższego poziomu TileService. Material3TileService zapewnia opiniową architekturę opartą na języku Kotlin, która upraszcza tworzenie kafelków:

  • Wbudowane współprogramy Kotlin: zaimplementuj jedną funkcję zawieszającąMaterialScope.tileResponse(requestParams: TileRequest): Tile zamiast używać ListenableFuture i zastępować onTileRequest().
  • Wstępnie skonfigurowany MaterialScope: tileResponse() działa z MaterialScope jako odbiorcą (skonfigurowanym za pomocą parametrów konstruktora, takich jak allowDynamicTheme i defaultColorScheme), więc nie musisz umieszczać układu w nadmiarowym wywołaniu materialScope().
  • Rejestracja zasobów w ramach jednego wywołania: obejmuje ProtoLayoutScope, aby automatycznie rejestrować zasoby obrazów wbudowanych i zwracać układ kafelków oraz zasoby w ramach jednego wywołania bindera systemowego. Ponieważ Material3TileService automatycznie zarządza zasobami (final onTileResourcesRequest()), nie zastępuj onTileResourcesRequest().
class MyTileService : Material3TileService() {

    override suspend fun MaterialScope.tileResponse(requestParams: TileRequest): Tile =
        tile(
            timeline =
            Timeline.fromLayoutElement(
                primaryLayout(
                    mainSlot = {
                        text("Hello, World!".layoutString, typography = BODY_LARGE)
                    }
                )
            )
        )
}

Architektura bazowa TileService

Material3TileService jest rozszerzeniem podstawowej klasy TileService, z której korzystają pozostałe przykłady w tym przewodniku, aby zilustrować koncepcje niskiego poziomu.

Aby udostępnić kafelek z aplikacji, zaimplementuj usługę typu TileService i zarejestruj ją w pliku manifestu. Na tej podstawie system żąda niezbędnych kafelków podczas wywołań onTileRequest() i zasobów podczas wywołań onTileResourcesRequest().

class MyTileService : TileService() {

    override fun onTileRequest(requestParams: RequestBuilders.TileRequest) =
        Futures.immediateFuture(
            Tile.Builder()
                .setResourcesVersion(RESOURCES_VERSION)
                .setTileTimeline(
                    Timeline.fromLayoutElement(
                        materialScope(this, requestParams.deviceConfiguration) {
                            primaryLayout(
                                mainSlot = {
                                    text("Hello, World!".layoutString, typography = BODY_LARGE)
                                }
                            )
                        }
                    )
                )
                .build()
        )

    override fun onTileResourcesRequest(requestParams: ResourcesRequest) =
        Futures.immediateFuture(Resources.Builder().setVersion(RESOURCES_VERSION).build())
}

Następnie dodaj usługę w tagu <application> w pliku AndroidManifest.xml.

<service
    android:name=".snippets.m3.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>

Uprawnienie i filtr intencji rejestrują tę usługę jako dostawcę kafelków.

Ikona, etykieta, opis i zasób podglądu są wyświetlane użytkownikowi, gdy konfiguruje on kafelki na telefonie lub zegarku. Pamiętaj, że zasób podglądu obsługuje wszystkie standardowe kwalifikatory zasobów Androida, więc podgląd można dostosowywać do takich czynników jak rozmiar ekranu czy język urządzenia. Dodatkowe rekomendacje znajdziesz na liście kontrolnej podglądu.

Wdróż aplikację i dodaj kartę do karuzeli kart (istnieje też wygodniejszy sposób wyświetlania podglądu karty, ale na razie zrób to ręcznie).

Kafelek Wear OS utworzony w Material 3, wyświetlający tekst „Hello World”.
Rysunek 1. kafelka „Hello World”,

Pełny przykład znajdziesz w przykładowym kodzie w GitHubie lub w samouczku.

Tworzenie interfejsu kafelków

Elementy interfejsu Material 3 Expressive są tworzone przy użyciu strukturalnego podejścia opartego na wzorze kreatora bezpiecznego pod względem typów w Kotlinie.

Układ

Wskazówki dotyczące zasad projektowania skutecznych i elastycznych układów kafelków znajdziesz w artykule Typowe układy kafelków.

Aby utworzyć układ:

  1. Zainicjuj zakres Material Design: wywołaj funkcję materialScope(), podając wymagane wartości context i deviceConfiguration. Możesz uwzględnić parametry opcjonalne, takie jak allowDynamicTheme i defaultColorScheme. Wartość allowDynamicTheme jest domyślnie ustawiona na true, a defaultColorScheme reprezentuje ColorScheme używany, gdy dynamiczne kolory są niedostępne (np. gdy użytkownik wyłączył tę funkcję) lub gdy nie są obsługiwane przez urządzenie albo gdy wartość allowDynamicTheme to false).

  2. Twórz interfejs w odpowiednim zakresie: wszystkie komponenty interfejsu dla danego układu kafelka muszą być zdefiniowane w lambdzie pojedynczego wywołania materialScope() najwyższego poziomu. Te funkcje komponentu, takie jak primaryLayout() i textEdgeButton(), są funkcjami rozszerzającymi MaterialScope i są dostępne tylko wtedy, gdy są wywoływane w tym zakresie odbiornika.

    materialScope(
        context = context,
        deviceConfiguration =
        requestParams.deviceConfiguration, // requestParams is passed to onTileRequest
        defaultColorScheme = myFallbackColorScheme
    ) {
        // inside the MaterialScope, you can call functions like primaryLayout()
        primaryLayout(
            titleSlot = { text(text = "Title".layoutString) },
            mainSlot = { text(text = "Main Content".layoutString) },
            bottomSlot = {
                textEdgeButton(
                    labelContent = { text("Action".layoutString) },
                    onClick = clickable()
                )
            }
        )
    }

Przedziały

W M3 układ kafelków wykorzystuje podejście inspirowane Compose, które korzysta z 3 różnych slotów. Od góry do dołu są to:

  1. titleSlot, zwykle w przypadku głównego tytułu lub nagłówka.
  2. mainSlot w przypadku podstawowych treści.
  3. bottomSlot, często używany do działań lub dodatkowych informacji. W tym miejscu pojawia się też przycisk krawędziowy.
Układ kafelków z polami titleSlot, mainSlot i bottomSlot
Rysunek 2. titleSlot, mainSlot i bottomSlot.

Zawartość poszczególnych slotów jest następująca:

  • titleSlot (opcjonalnie): zwykle kilka słów wygenerowanych przez text().
  • mainSlot (obowiązkowe): komponenty uporządkowane w struktury takie jak wiersze, kolumny i grupy przycisków. Te komponenty mogą być też zagnieżdżone w sobie nawzajem, np. kolumna może zawierać wiersze.
  • bottomSlot (opcjonalnie): zwykle wypełniony przyciskiem przylegającym do krawędzi lub etykietą tekstową.

Kafelków nie można przewijać, więc nie ma komponentów do stronicowania, przewijania ani obsługi długich list treści. Zadbaj o to, aby treść pozostała widoczna po zwiększeniu rozmiaru czcionki lub wydłużeniu tekstu w wyniku tłumaczenia.

Komponenty interfejsu

Biblioteka protolayout-material3 zawiera wiele komponentów zaprojektowanych zgodnie ze specyfikacjami Material 3 Expressive i zaleceniami dotyczącymi interfejsu użytkownika.

Przyciski

Przyciski są przede wszystkim zorientowane na działanie. Służą one do wywoływania określonych działań. Zawartość każdego przycisku, np. ikona lub krótki tekst, określa działanie.

  • textButton(): przycisk z 1 miejscem na (krótką) treść tekstową.
  • iconButton(): przycisk z 1 miejscem na ikonę.
  • avatarButton(): przycisk awatara w kształcie pigułki, który oferuje maksymalnie 3 miejsca na treści reprezentujące etykietę i etykietę dodatkową ułożone pionowo oraz obraz (awatar) obok nich.
  • imageButton(): klikalny przycisk obrazu, który nie oferuje dodatkowych miejsc, tylko obraz (np. backgroundImage jako tło).
  • compactButton(): kompaktowy przycisk z maksymalnie 2 slotami na ułożoną poziomo zawartość, która reprezentuje ikonę i tekst obok niej.
  • button(): przycisk w kształcie pigułki, który oferuje do 3 miejsc na treści reprezentujące etykietę i etykietę dodatkową ułożone pionowo oraz ikonę obok nich.

Przyciski na krawędzi

Przycisk krawędziowy to specjalny przycisk o pełnej szerokości, który jest umieszczony u dołu okrągłego ekranu zegarka i reprezentuje najważniejsze działanie, jakie można wykonać na bieżącym ekranie kafelka.

  • iconEdgeButton(): przycisk krawędziowy z jednym miejscem na ikonę lub podobną okrągłą, małą treść.
  • textEdgeButton(): przycisk na krawędzi, który oferuje jedno miejsce na tekst lub podobnie długie i szerokie treści.

Karty

Karty mają przede wszystkim charakter informacyjny. Wyświetlają one zbiory powiązanych, uporządkowanych danych. Możesz tworzyć interaktywne karty, ale zwykle zawierają one podsumowanie informacji, które użytkownik może kliknąć, aby wyświetlić więcej szczegółów lub wykonać powiązane działanie.

  • titleCard(): karta tytułowa z 1–3 slotami, zwykle tekstowymi.
  • appCard(): karta aplikacji, która oferuje do 5 miejsc, zwykle opartych na tekście.
  • textDataCard(): karta danych, która oferuje maksymalnie 3 ułożone pionowo miejsca, zwykle oparte na tekście lub liczbach.
  • iconDataCard(): karta danych, która oferuje do 3 ułożonych pionowo slotów, zwykle tekstowych lub numerycznych, z ikoną.
  • graphicDataCard(): karta danych graficznych, która zawiera miejsce na dane graficzne, np. wskaźnik postępu, oraz maksymalnie 2 miejsca ułożone pionowo, zwykle na opisy tekstowe.

Wskaźniki postępu

Grupowanie elementów układu

  • buttonGroup(): układ komponentu, który umieszcza elementy podrzędne w sekwencji poziomej.
  • primaryLayout(): układ pełnoekranowy, który reprezentuje sugerowany styl układu M3, który jest elastyczny i odpowiada za rozmieszczenie elementów, a także za zastosowanie zalecanych marginesów i wypełnienia.

Stosowanie motywu

W Material 3 Expressive system kolorów jest zdefiniowany przez 29 standardowych ról kolorów podzielonych na 6 grup: podstawowe, dodatkowe, trzeciorzędowe, błędu, powierzchni i konturu.

System kolorów Material 3 Expressive, w którym role kolorów są podzielone na grupy, takie jak podstawowy, dodatkowy, trzeciorzędowy, błąd, powierzchnia i kontur.
Rysunek 3. System kolorów Material 3 Expressive.

ColorScheme przypisuje każdą z tych 29 ról do odpowiedniego koloru, a ponieważ jest to część MaterialScope i komponenty muszą być w nim tworzone, automatycznie przyjmują kolory z tego schematu. Dzięki temu wszystkie elementy interfejsu użytkownika automatycznie dostosowują się do standardów Material Design.

Aby umożliwić użytkownikom wybór między zdefiniowanym przez Ciebie schematem kolorów (np. odzwierciedlającym kolory Twojej marki) a schematem dostarczonym przez system (pochodzącym z bieżącej tarczy zegarka użytkownika lub wybranym przez niego), zainicjuj MaterialScope w ten sposób:

val myColorScheme =
    ColorScheme(
        primary = Color.rgb(0, 0, 255).argb, // Blue
        onPrimary = Color.rgb(255, 255, 255).argb, // White
        // 27 more
    )

materialScope(
    context = context,
    deviceConfiguration = requestParams.deviceConfiguration,
    defaultColorScheme = myColorScheme
) {
    // If the user selects "no theme" in settings, myColorScheme is used.
    // Otherwise, the system-provided theme is used.
}

Jeśli wybierzesz tę opcję, podaj monochromatyczną ikonę kafelka, aby można było ją prawidłowo zabarwić i zapewnić optymalną widoczność na każdym motywie.

Aby wymusić wyświetlanie kafelków w podanym schemacie kolorów, wyłącz obsługę dynamicznego motywu, ustawiając wartość allowDynamicTheme na false:

materialScope(
    context = context,
    deviceConfiguration = requestParams.deviceConfiguration,
    allowDynamicTheme = false,
    defaultColorScheme = myColorScheme
) {
    // myColorScheme is *always* used.
}

Kolor

Każdy komponent korzysta z podzbioru 29 ról kolorów zdefiniowanych przez ColorScheme. Na przykład przyciski używają maksymalnie 4 kolorów, które domyślnie pochodzą z grupy „podstawowej” aktywnego ColorScheme:

ButtonColors token komponentu, ColorScheme rola
containerColor podstawowe
iconColor onPrimary
labelColor onPrimary
secondaryLabelColor onPrimary (nieprzezroczystość 0,8)

Szczegółowe wskazówki dotyczące stosowania kolorów w projektach na Wear OS znajdziesz w przewodniku po projektowaniu kolorów.

W przypadku niektórych elementów interfejsu może być konieczne odstąpienie od domyślnych tokenów kolorów. Możesz na przykład użyć textEdgeButton kolorów z grupy „drugorzędne” lub „trzeciorzędne” zamiast „podstawowych”, aby wyróżnić się i zapewnić lepszy kontrast.

Kolory komponentów możesz dostosować na kilka sposobów:

  1. Użyj funkcji pomocniczej dla wstępnie zdefiniowanych kolorów. Używaj funkcji pomocniczych, takich jak filledTonalButtonColors(), aby zastosować standardowe style przycisków w przypadku Material 3 Expressive. Te funkcje tworzą wstępnie skonfigurowane ButtonColors instancje, które mapują typowe style, takie jak wypełniony, tonalny lub konturowy, na odpowiednie role z aktywnego ColorScheme w MaterialScope. Dzięki temu możesz stosować spójne style bez ręcznego definiowania każdego koloru dla typowych rodzajów przycisków.

    textEdgeButton(
        colors = filledButtonColors(), // default
        /* OR colors = filledTonalButtonColors() */
        /* OR colors = filledVariantButtonColors() */
        // ... other parameters
    )

    W przypadku kart użyj odpowiedniej rodziny funkcji filledCardColors().

    Możesz też zmodyfikować obiekt ButtonColors zwracany przez funkcje pomocnicze, używając ich metody copy(), jeśli chcesz zmienić tylko 1 lub 2 tokeny:

    textEdgeButton(
        colors =
        filledButtonColors()
            .copy(
                containerColor = colorScheme.tertiary,
                labelColor = colorScheme.onTertiary
            ),
        // ... other parameters
    )

  2. Wyraźnie podaj role kolorów zastępczych. Utwórz własny obiekt ButtonColors i przekaż go do komponentu. W przypadku kart użyj odpowiedniego obiektu CardColors.

    textEdgeButton(
        colors =
        ButtonColors(
            // the materialScope makes colorScheme available
            containerColor = colorScheme.secondary,
            iconColor = colorScheme.secondaryDim,
            labelColor = colorScheme.onSecondary,
            secondaryLabelColor = colorScheme.onSecondary
        ),
        // ... other parameters
    )

  3. Określ stałe kolory (używaj z rozwagą). Zalecamy określanie kolorów według ich roli semantycznej (np. colorScheme.primary), ale możesz też podać bezpośrednie wartości kolorów. To podejście należy stosować oszczędnie, ponieważ może prowadzić do niespójności z ogólnym motywem, zwłaszcza jeśli motyw zmienia się dynamicznie.

    textEdgeButton(
        colors = filledButtonColors().copy(
            containerColor = android.graphics.Color.RED.argb, // Using named colors
            labelColor = 0xFFFFFF00.toInt().argb // Using a hex code for yellow
        ),
        // ... other parameters
    )

Typografia

Więcej informacji o skutecznym wykorzystaniu typografii w projektach znajdziesz w przewodniku po projektowaniu typografii.

Aby zapewnić spójność wizualną na platformie Wear OS i zoptymalizować wydajność, cały tekst na kartach jest renderowany przy użyciu czcionki dostarczonej przez system. Oznacza to, że kafelki nie obsługują niestandardowych krojów pisma. W przypadku Wear OS 6 i nowszych jest to czcionka specyficzna dla producenta OEM. W większości przypadków będzie to czcionka zmienna, która zapewnia większą ekspresję i bardziej szczegółową kontrolę.

Aby utworzyć styl tekstu, zwykle używa się metody text() w połączeniu ze stałymi typograficznymi. Ten komponent umożliwia korzystanie z wstępnie zdefiniowanych ról typograficznych w Material 3 Expressive, co pomaga w przypadku kafelka zachować sprawdzone metody typograficzne dotyczące czytelności i hierarchii. Biblioteka oferuje zestaw 18 stałych semantycznych typografii, takich jak BODY_MEDIUM. Te stałe wpływają też na osie czcionki inne niż rozmiar.

text(
    text = "Hello, World!".layoutString,
    typography = BODY_MEDIUM,
)

Aby mieć większą kontrolę, możesz podać dodatkowe ustawienia. W Wear OS 6 i nowszych wersjach prawdopodobnie używana jest czcionka zmienna, którą możesz modyfikować wzdłuż osi kursywa, grubość, szerokość i zaokrąglenie. Możesz kontrolować te osie za pomocą parametru settings:

text(
    text = "Hello, World".layoutString,
    italic = true,

    // Use elements defined in androidx.wear.protolayout.LayoutElementBuilders.FontSetting
    settings =
    listOf(
        weight(500),
        width(100F),
        roundness(100)
    ),
)

Jeśli chcesz kontrolować rozmiar lub odstępy między literami (niezalecane), użyj funkcji basicText() zamiast text() i utwórz wartość właściwości fontStyle za pomocą funkcji fontStyle()).

Kształt i marginesy

Za pomocą właściwości shape możesz zmienić promień zaokrąglenia niemal każdego komponentu. Wartości pochodzą z właściwości MaterialScope shapes:

textButton(
    height = expand(),
    width = expand(),
    shape = shapes.medium, // OR another value like shapes.full
    colors = filledVariantButtonColors(),
    labelContent = { text("Hello, World!".layoutString) },
)

Jeśli po zmianie kształtu komponentu uznasz, że pozostawia on zbyt dużo lub zbyt mało miejsca na krawędzi wyświetlacza, dostosuj marginesy za pomocą parametru margin funkcji primaryLayout():

primaryLayout(
    mainSlot = {
        textButton(
            shape = shapes.small,
            /* ... */
        )
    },
    // margin constants defined in androidx.wear.protolayout.material3.PrimaryLayoutMargins
    margins = MAX_PRIMARY_LAYOUT_MARGIN,
)

Łuki

Obsługiwane są te elementy podrzędne kontenera Arc:

  • ArcLine: renderuje zakrzywioną linię wokół łuku.
  • ArcText: renderuje zakrzywiony tekst w Arcu.
  • ArcAdapter: renderuje podstawowy element układu w łuku, narysowany stycznie do łuku.

Więcej informacji znajdziesz w dokumentacji referencyjnej dotyczącej każdego typu elementu.

Modyfikatory

Do każdego dostępnego elementu układu można opcjonalnie zastosować modyfikatory. Używaj tych modyfikatorów w tych celach:

  • Zmień wygląd układu. Możesz na przykład dodać tło, obramowanie lub dopełnienie do elementu układu.
  • Dodaj metadane dotyczące układu. Możesz na przykład dodać modyfikator semantyczny do elementu układu, aby używać go z czytnikami ekranu.
  • Dodaj funkcje. Możesz na przykład dodać do elementu układu modyfikator z możliwością klikania, aby kafel był interaktywny. Więcej informacji znajdziesz w rozdziale Korzystanie z kart.

Możemy na przykład dostosować domyślny wygląd i metadane elementu Image, jak w tym przykładowym kodzie:

private fun myImage(): LayoutElement =
    Image.Builder()
        .setWidth(dp(24f))
        .setHeight(dp(24f))
        .setResourceId("image_id")
        .setModifiers(
            Modifiers.Builder()
                .setBackground(Background.Builder().setColor(argb(0xFFFF0000.toInt())).build())
                .setPadding(ModifiersBuilders.Padding.Builder().setStart(dp(12f)).build())
                .setSemantics(Semantics.Builder().setContentDescription("Image description").build())
                .build()
        )
        .build()

Elementy rozciągane

Spannable to specjalny rodzaj kontenera, który rozmieszcza elementy podobnie jak tekst. Jest to przydatne, gdy chcesz zastosować inny styl tylko do jednego podciągu w większym bloku tekstu, co nie jest możliwe w przypadku elementu Text.

Kontener Spannable jest wypełniony elementami podrzędnymi Span. Inne elementy podrzędne lub zagnieżdżone instancje Spannable są niedozwolone.

Istnieją 2 rodzaje Span dzieci:

  • SpanText: renderuje tekst w określonym stylu.
  • SpanImage: renderuje obraz w treści tekstu.

Możesz na przykład zapisać słowo „world” kursywą w karcie „Hello world” i wstawić obraz między słowami, jak pokazano w tym przykładowym kodzie:

private fun mySpannable(): LayoutElement =
    LayoutElementBuilders.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()

Praca z zasobami

Kafelki nie mają dostępu do żadnych zasobów aplikacji. Oznacza to, że nie możesz przekazać identyfikatora obrazu Androida do elementu układu Image i oczekiwać, że zostanie on rozpoznany. Zamiast tego zastąp metodę onTileResourcesRequest() i ręcznie podaj dowolne zasoby.

Obrazy w metodzie onTileResourcesRequest() możesz podać na 2 sposoby:

override fun onTileResourcesRequest(
    requestParams: ResourcesRequest
) = Futures.immediateFuture(
    Resources.Builder()
        .setVersion("1")
        .addIdToImageMapping(
            "image_from_resource",
            ResourceBuilders.ImageResource.Builder()
                .setAndroidResourceByResId(
                    ResourceBuilders.AndroidImageResourceByResId.Builder()
                        .setResourceId(R.drawable.ic_walk)
                        .build()
                ).build()
        )
        .addIdToImageMapping(
            "image_inline",
            ResourceBuilders.ImageResource.Builder()
                .setInlineResource(
                    ResourceBuilders.InlineImageResource.Builder()
                        .setData(imageAsByteArray)
                        .setWidthPx(48)
                        .setHeightPx(48)
                        .setFormat(ResourceBuilders.IMAGE_FORMAT_RGB_565)
                        .build()
                ).build()
        ).build()
)

Lista kontrolna obrazu podglądu kafelka

W edytorze karuzeli kafelków system wyświetla obraz podglądu kafelka, do którego odwołuje się plik manifestu aplikacji na Androida, aby umożliwić dodanie nowego kafelka. Edytor ten jest dostępny zarówno na urządzeniach z Wear OS, jak i w aplikacji towarzyszącej zegarkowi na telefonach.

Aby pomóc użytkownikom w pełni wykorzystać możliwości tego obrazu podglądu, sprawdź te informacje o kafelku:

  • Odzwierciedla najnowszy projekt. Podgląd powinien dokładnie odzwierciedlać najnowszy projekt kafelka.
  • Używa zalecanych wymiarów. Aby zapewnić jak najlepszą jakość wyświetlania i dobre wrażenia użytkowników, obraz podglądu powinien mieć wymiary 400 x 400 pikseli.
  • Używa statycznego motywu kolorystycznego. Użyj statycznego motywu kolorystycznego kafelka, a nie dynamicznego.
  • Zawiera ikonę aplikacji Sprawdź, czy ikona aplikacji pojawia się u góry obrazu podglądu.
  • Wyświetla stan wczytania lub zalogowania. Podgląd powinien wyświetlać w pełni funkcjonalny stan „załadowany” lub „zalogowany”, bez pustych lub przykładowych treści.
  • Wykorzystaj reguły rozwiązywania zasobów do dostosowywania (opcjonalnie). Aby udostępniać podglądy dopasowane do rozmiaru wyświetlacza urządzenia, języka lub ustawień regionalnych, możesz skorzystać z zasad dotyczących rozdzielczości zasobów w Androidzie. Jest to szczególnie przydatne, jeśli wygląd kafelka różni się na różnych urządzeniach.