Pembuatan versi kartu

Di perangkat Wear OS, kartu dirender oleh dua komponen utama dengan versi independen. Untuk memastikan kartu aplikasi Anda berfungsi dengan benar di semua perangkat, penting untuk memahami arsitektur yang mendasarinya.

  • Library terkait kartu Jetpack: Library ini (termasuk Kartu Wear dan ProtoLayout Wear) disematkan dalam aplikasi Anda, dan Anda, sebagai developer, mengontrol versinya. Aplikasi Anda menggunakan library ini untuk membuat objek TileBuilder.Tile (struktur data yang mewakili Kartu Anda) sebagai respons terhadap panggilan onTileRequest() sistem.
  • ProtoLayout Renderer: Komponen sistem ini bertanggung jawab untuk merender objek Tile di layar dan menangani interaksi pengguna. Versi renderer tidak dikontrol oleh developer aplikasi dan dapat bervariasi di perangkat, bahkan perangkat dengan hardware yang identik.

Tampilan atau perilaku Kartu dapat bervariasi berdasarkan versi library Jetpack Tiles aplikasi Anda dan versi ProtoLayout Renderer di perangkat pengguna. Misalnya, satu perangkat mungkin mendukung rotasi atau tampilan data detak jantung, dan perangkat lainnya mungkin tidak.

Dokumen ini menjelaskan cara memastikan aplikasi Anda kompatibel dengan berbagai versi library Kartu dan Renderer ProtoLayout, serta cara bermigrasi ke versi library Jetpack yang lebih tinggi.

Pertimbangkan kompatibilitas

Untuk membuat Kartu yang berfungsi dengan benar di berbagai perangkat, Anda harus mempertimbangkan hal berikut.

Mendeteksi versi perender

  • Gunakan metode getRendererSchemaVersion() dari objek DeviceParameters yang diteruskan ke metode onTileRequest(). Metode ini menampilkan nomor versi utama dan minor Renderer ProtoLayout di perangkat.
  • Kemudian, Anda dapat menggunakan logika kondisional dalam implementasi onTileRequest() untuk menyesuaikan desain atau perilaku Kartu berdasarkan versi perender yang terdeteksi.
    • Misalnya, jika animasi tertentu tidak didukung, Anda dapat menampilkan gambar statis.

Anotasi @RequiresSchemaVersion

  • Anotasi @RequiresSchemaVersion pada metode ProtoLayout menunjukkan versi skema perender minimum yang diperlukan agar metode tersebut berperilaku seperti yang didokumentasikan (contoh).
    • Meskipun memanggil metode yang memerlukan versi perender yang lebih tinggi daripada yang tersedia di perangkat tidak akan menyebabkan aplikasi Anda error, hal ini dapat menyebabkan konten tidak ditampilkan atau fitur diabaikan.

Contoh

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())
}

Menguji dengan versi perender yang berbeda

Untuk menguji kartu Anda terhadap versi perender yang berbeda, deploy ke versi emulator Wear OS yang berbeda. (Di perangkat fisik, update ProtoLayout Renderer dikirimkan oleh Play Store atau update sistem. Anda tidak dapat memaksa penginstalan versi perender tertentu.)

Fitur Pratinjau Kartu Android Studio menggunakan perender yang disematkan dalam library Jetpack ProtoLayout yang menjadi dependensi kode Anda, sehingga pendekatan lainnya adalah bergantung pada versi library Jetpack yang berbeda saat menguji kartu.

Bermigrasi ke Kartu 1.5 / ProtoLayout 1.3 (Material 3 Ekspresif)

Update library Jetpack Tile untuk memanfaatkan peningkatan terbaru, termasuk perubahan UI agar Kartu Anda terintegrasi dengan lancar dengan sistem.

Jetpack Tiles 1.5 dan Jetpack ProtoLayout 1.3 memperkenalkan beberapa peningkatan dan perubahan yang signifikan. Ini mencakup:

  • API seperti Compose untuk mendeskripsikan UI.
  • Komponen Material 3 Ekspresif, termasuk tombol tepi yang menempel di bagian bawah dan dukungan untuk visual yang ditingkatkan: animasi Lottie, lebih banyak jenis gradien, dan gaya garis busur baru. - Catatan: beberapa fitur ini juga dapat digunakan tanpa bermigrasi ke API baru.

Rekomendasi

  • Migrasi semua kartu secara bersamaan. Hindari mencampur versi kartu dalam aplikasi Anda. Meskipun komponen Material 3 berada di artefak terpisah (androidx.wear.protolayout:protolayout-material3)—sehingga secara teknis memungkinkan penggunaan Kartu M2.5 dan M3 di aplikasi yang sama—kami sangat menyarankan agar tidak menggunakan pendekatan ini kecuali jika benar-benar diperlukan (misalnya, jika aplikasi Anda memiliki banyak kartu yang tidak dapat dimigrasikan secara bersamaan).
  • Gunakan panduan UX Kartu. Mengingat sifat kartu yang sangat terstruktur dan bertemplate, gunakan desain dalam contoh yang ada sebagai titik awal untuk desain Anda sendiri.
  • Lakukan pengujian di berbagai ukuran layar dan font. Kartu sering kali berisi informasi yang padat, sehingga teks (terutama saat ditempatkan di tombol) rentan mengalami overflow dan pemangkasan. Untuk meminimalkannya, gunakan komponen bawaan dan hindari penyesuaian yang ekstensif. Uji menggunakan fitur pratinjau kartu Android Studio serta di beberapa perangkat sungguhan.

Proses migrasi

Memperbarui dependensi

Pertama, perbarui file build.gradle.kts Anda. Update versi dan ubah dependensi protolayout-material menjadi protolayout-material3, seperti yang ditunjukkan:

// 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 sebagian besar tetap tidak berubah

Perubahan utama dalam migrasi ini memengaruhi komponen UI. Akibatnya, penerapan TileService Anda, termasuk mekanisme pemuatan resource, harus memerlukan sedikit atau tidak ada modifikasi.

Pengecualian utama melibatkan pelacakan aktivitas kartu: jika aplikasi Anda menggunakan onTileEnterEvent() atau onTileLeaveEvent(), Anda harus bermigrasi ke onRecentInteractionEventsAsync(). Mulai API 36, peristiwa ini akan dikelompokkan.

Menyesuaikan kode pembuatan tata letak

Di ProtoLayout 1.2 (M2.5), metode onTileRequest() menampilkan TileBuilders.Tile. Objek ini berisi berbagai elemen, termasuk TimelineBuilders.Timeline, yang pada gilirannya menyimpan LayoutElement yang mendeskripsikan UI kartu.

Dengan ProtoLayout 1.3 (M3), meskipun struktur dan alur data secara keseluruhan belum berubah, LayoutElement kini dibuat menggunakan pendekatan yang terinspirasi Compose dengan tata letak berdasarkan slot yang ditentukan, yaitu (dari atas ke bawah) titleSlot (biasanya untuk judul atau header utama), mainSlot (untuk konten inti), dan bottomSlot (sering kali untuk tindakan seperti tombol tepi atau informasi tambahan seperti teks singkat). Tata letak ini dibuat oleh fungsi primaryLayout().

Tata letak kartu yang menampilkan mainSlot, titleSlot, bottomSlot
Gambar 1.: Slot kartu.
Perbandingan fungsi tata letak M2.5 dan 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) })
    }

Untuk menyoroti perbedaan utamanya:

  1. Penghapusan Builder. Pola builder tradisional untuk komponen UI Material3 diganti dengan sintaksis yang lebih deklaratif dan terinspirasi Compose. (Komponen non-UI seperti String/Warna/Pengubah juga mendapatkan wrapper Kotlin baru.)
  2. Fungsi Tata Letak dan Inisialisasi Standar. Tata letak M3 mengandalkan fungsi struktur dan inisialisasi standar: materialScope() dan primaryLayout(). Fungsi wajib ini melakukan inisialisasi lingkungan M3 (tema, cakupan komponen melalui materialScope) dan menentukan tata letak berbasis slot utama (melalui primaryLayout). Keduanya harus dipanggil tepat sekali per tata letak.

Tema

Warna

Fitur unggulan Material 3 Expressive adalah kartu "tema dinamis" yang mengaktifkan fitur ini (aktif secara default) akan ditampilkan dalam tema yang disediakan sistem (ketersediaan bergantung pada perangkat dan konfigurasi pengguna).

Perubahan lain di M3 adalah perluasan jumlah token warna, yang telah meningkat dari 4 menjadi 29. Token warna baru dapat ditemukan di class ColorScheme.

Tipografi

Serupa dengan M2.5, M3 sangat bergantung pada konstanta ukuran font yang telah ditentukan sebelumnya—sebaiknya jangan menentukan ukuran font secara langsung. Konstanta ini terletak di class Typography dan menawarkan rentang opsi yang lebih ekspresif yang sedikit diperluas.

Untuk mengetahui detail selengkapnya, lihat Dokumentasi tipografi.

Bentuk

Sebagian besar komponen M3 dapat bervariasi di sepanjang dimensi bentuk serta warna.

textButton (di mainSlot) dengan bentuk full:

Kartu dengan bentuk &#39;penuh&#39; (sudut lebih membulat)
Gambar 2.: Kartu dengan bentuk 'penuh'

textButton yang sama dengan bentuk small:

Kartu dengan bentuk &#39;kecil&#39; (sudut kurang membulat)
Gambar 3.: Kartu dengan bentuk 'kecil'

Komponen

Komponen M3 secara signifikan lebih fleksibel dan dapat dikonfigurasi daripada komponen M2.5. Jika M2.5 sering kali memerlukan komponen yang berbeda untuk berbagai perlakuan visual, M3 sering kali menggunakan komponen "dasar" yang umum tetapi sangat dapat dikonfigurasi dengan default yang baik.

Prinsip ini berlaku untuk tata letak "root". Di M2.5, ini adalah PrimaryLayout atau EdgeContentLayout. Di M3, setelah satu MaterialScope tingkat teratas dibuat, fungsi primaryLayout() akan dipanggil. Tindakan ini akan menampilkan tata letak root secara langsung (tidak memerlukan builder) dan menerima LayoutElements untuk beberapa "slot", seperti titleSlot, mainSlot, dan bottomSlot. Slot ini dapat diisi dengan komponen UI konkret—seperti yang ditampilkan oleh text(), button(), atau card()—atau struktur tata letak, seperti Row atau Column dari LayoutElementBuilders.

Tema mewakili peningkatan M3 utama lainnya. Secara default, elemen UI otomatis mematuhi spesifikasi gaya visual M3 dan mendukung tema dinamis.

M2.5 M3
Elemen Interaktif
Button atau Chip
Teks
Text text()
Indikator Progres
CircularProgressIndicator circularProgressIndicator() atau segmentedCircularProgressIndicator()
Tata letak
PrimaryLayout atau EdgeContentLayout primaryLayout()
buttonGroup()
Gambar
icon(), avatarImage(), atau backgroundImage()

Pengubah

Di M3, Modifiers, yang Anda gunakan untuk mendekorasi atau menambah komponen, lebih mirip dengan Compose. Perubahan ini dapat mengurangi boilerplate dengan secara otomatis membuat jenis internal yang sesuai. (Perubahan ini ortogonal dengan penggunaan komponen UI M3; jika perlu, Anda dapat menggunakan pengubah gaya builder dari ProtoLayout 1.2 dengan komponen UI M3, dan sebaliknya.)

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)

Anda dapat membuat pengubah menggunakan gaya API, dan Anda juga dapat menggunakan fungsi ekstensi toProtoLayoutModifiers() untuk mengonversi LayoutModifier menjadi ModifiersBuilders.Modifier.

Fungsi Bantuan

Meskipun ProtoLayout 1.3 memungkinkan banyak komponen UI diekspresikan menggunakan API yang terinspirasi Compose, elemen tata letak dasar seperti baris dan kolom dari LayoutElementBuilders terus menggunakan pola builder. Untuk menjembatani kesenjangan gaya ini dan mendorong konsistensi dengan API komponen M3 baru, pertimbangkan untuk menggunakan fungsi bantuan.

Tanpa Helper

primaryLayout(
    mainSlot = {
        LayoutElementBuilders.Column.Builder()
            .setWidth(expand())
            .setHeight(expand())
            .addContent(text("A".layoutString))
            .addContent(text("B".layoutString))
            .addContent(text("C".layoutString))
            .build()
    }
)

Dengan Helper

// 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))
        }
    }
)

Bermigrasi ke Tiles 1.2 / ProtoLayout 1.0

Mulai versi 1.2, sebagian besar API tata letak Kartu berada di namespace androidx.wear.protolayout. Untuk menggunakan API terbaru, selesaikan langkah-langkah migrasi berikut dalam kode Anda.

Memperbarui dependensi

Dalam file build modul aplikasi Anda, buat perubahan berikut:

Groovy

  // Remove
  implementation '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

  // Remove
  implementation("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")

Memperbarui namespace

Di file kode berbasis Kotlin dan Java aplikasi Anda, lakukan pembaruan berikut. Bisa juga dengan mengeksekusi skrip penggantian nama namespace ini.

  1. Ganti semua impor androidx.wear.tiles.material.* dengan androidx.wear.protolayout.material.*. Selesaikan juga langkah ini untuk library androidx.wear.tiles.material.layouts.
  2. Ganti sebagian besar impor androidx.wear.tiles.* lainnya dengan androidx.wear.protolayout.*.

    Impor untuk androidx.wear.tiles.EventBuilders, androidx.wear.tiles.RequestBuilders, androidx.wear.tiles.TileBuilders, dan androidx.wear.tiles.TileService harus tetap sama.

  3. Ganti nama beberapa metode yang tidak digunakan lagi dari class TileService dan TileBuilder:

    1. TileBuilders: getTimeline() ke getTileTimeline(), dan setTimeline() ke setTileTimeline()
    2. TileService: onResourcesRequest() ke onTileResourcesRequest()
    3. RequestBuilders.TileRequest: getDeviceParameters() ke getDeviceConfiguration(), setDeviceParameters() ke setDeviceConfiguration(), getState() ke getCurrentState(), dan setState() ke setCurrentState()