Mulai menggunakan kartu

Untuk mulai menyediakan kartu dari aplikasi, sertakan dependensi berikut dalam file build.gradle aplikasi.

Groovy

dependencies {
    // Use to implement support for wear tiles
    implementation "androidx.wear.tiles:tiles:1.5.0-alpha04"

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

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

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

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

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

Kotlin

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

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

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

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

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

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

Konsep utama

Kartu tidak dibuat dengan cara yang sama seperti aplikasi Android, dan menggunakan konsep yang berbeda:

  • Template tata letak: Menentukan keseluruhan pengaturan elemen visual di layar. Kartu menggunakan template tata letak EdgeContentLayout, yang menyertakan indikator progres di sekitar tepi layar, atau PrimaryLayout, yang tidak menampilkan indikator ini.
  • Elemen tata letak: Merepresentasikan setiap elemen grafis, seperti Button atau Chip, atau beberapa elemen tersebut yang dikelompokkan bersama menggunakan Column, MultiButtonLayout, MultiSlotLayout atau yang serupa. Elemen ini disematkan dalam template tata letak.
  • Resource: Objek ResourceBuilders.Resources terdiri dari peta key-value pair resource Android (gambar) yang diperlukan untuk merender tata letak, dan versi.
  • Linimasa: Objek TimelineBuilders.Timeline adalah daftar dari satu atau beberapa instance objek tata letak. Anda dapat menyediakan berbagai mekanisme dan ekspresi untuk menunjukkan kapan perender harus beralih dari satu objek tata letak ke objek lainnya, seperti untuk berhenti menampilkan tata letak pada waktu tertentu.
  • Status: Struktur data jenis StateBuilders.State yang diteruskan antara kartu dan aplikasi, untuk memungkinkan kedua komponen berkomunikasi satu sama lain. Misalnya, jika tombol diketuk pada kartu, status akan menyimpan ID tombol. Anda juga dapat menukar jenis data menggunakan peta.
  • Kartu: Objek TileBuilders.Tile yang mewakili kartu, yang terdiri dari linimasa, ID versi resource, interval keaktualan, dan status.
  • Protolayout: Istilah ini muncul dalam nama berbagai class terkait kartu dan mengacu pada library Protolayout Wear OS, library grafik yang digunakan di berbagai platform Wear OS.

Membuat kartu

Untuk menyediakan kartu dari aplikasi, terapkan layanan jenis TileService dan daftarkan dalam manifes Anda. Dari sini, sistem meminta kartu yang diperlukan selama panggilan ke onTileRequest() dan resource selama panggilan ke onTileResourcesRequest().

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_BODY1)
                            .setColor(argb(0xFFFFFFFF.toInt()))
                            .build()
                    )
                )
                .build()
        )

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

Selanjutnya, tambahkan layanan di dalam tag <application> file AndroidManifest.xml Anda.

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

Filter intent dan izin akan mendaftarkan layanan ini sebagai penyedia kartu.

Ikon, label, deskripsi, dan resource pratinjau ditampilkan kepada pengguna saat mereka mengonfigurasi kartu di ponsel atau smartwatch.

Deploy aplikasi Anda, dan tambahkan Kartu ke Carousel Kartu (ada juga cara yang lebih mudah bagi developer untuk melihat pratinjau Kartu, tetapi untuk saat ini, lakukan saja secara manual).

Gambar 1. Kartu "Hello World".

Untuk contoh lengkap, lihat contoh kode di GitHub atau codelab.

Membuat UI untuk kartu

Tata letak kartu ditulis menggunakan pola builder. Tata letak kartu dibuat seperti hierarki yang terdiri dari penampung tata letak dan elemen tata letak dasar. Setiap elemen tata letak memiliki properti, yang dapat Anda setel melalui berbagai metode penyetel.

Elemen tata letak dasar

Elemen visual berikut dari library protolayout didukung, beserta komponen Material:

  • Text: merender string teks, digabungkan secara opsional.
  • Image: merender gambar.
  • Spacer: menyediakan padding di antara elemen atau dapat berfungsi sebagai pemisah saat Anda menetapkan warna latar belakangnya.

Komponen Material

Selain elemen dasar, library protolayout-material juga menyediakan komponen yang memastikan desain kartu sesuai dengan rekomendasi antarmuka pengguna Desain Material.

  • Button: komponen melingkar yang dapat diklik dan dirancang untuk memuat ikon.
  • Chip: komponen berbentuk stadion yang dapat diklik dan dirancang untuk memuat hingga dua baris teks dan ikon opsional.

  • CompactChip: komponen berbentuk stadion yang dapat diklik dan dirancang untuk memuat baris teks.

  • TitleChip: komponen berbentuk elips yang dapat diklik dan mirip dengan Chip, tetapi lebih tinggi untuk menampung teks judul.

  • CircularProgressIndicator: indikator progres melingkar yang dapat ditempatkan di dalam EdgeContentLayout untuk menampilkan progres di sekitar tepi layar.

Penampung tata letak

Penampung berikut didukung, beserta tata letak Material:

  • Row: menata letak elemen turunan secara horizontal, satu per satu.
  • Column: menata letak elemen turunan secara vertikal, satu per satu.
  • Box: menempatkan elemen turunan satu per satu.
  • Arc: menata letak elemen turunan dalam lingkaran.
  • Spannable: menerapkan FontStyles tertentu pada bagian teks bersama dengan teks dan gambar yang disisipkan. Untuk informasi selengkapnya, lihat Spannable.

Setiap penampung dapat berisi satu atau beberapa turunan yang juga dapat berupa penampung. Misalnya, Column dapat berisi beberapa elemen Row sebagai turunan sehingga menghasilkan tata letak seperti petak.

Sebagai contoh, kartu dengan tata letak penampung dan dua elemen tata letak turunan dapat terlihat seperti ini:

Kotlin

private fun myLayout(): LayoutElement =
    Row.Builder()
        .setWidth(wrap())
        .setHeight(expand())
        .setVerticalAlignment(VERTICAL_ALIGN_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();
}

Tata letak Material

Selain tata letak dasar, library protolayout-material juga menyediakan beberapa tata letak tetap yang dibuat untuk menampung elemen di "slot" tertentu.

  • PrimaryLayout: memosisikan satu tindakan utama CompactChip di bagian bawah dengan konten yang dipusatkan di atasnya.

  • MultiSlotLayout: memosisikan label utama dan sekunder dengan konten opsional di antara keduanya dan CompactChip opsional di bagian bawah.

  • MultiButtonLayout: mengatur posisi kumpulan tombol yang disusun sesuai dengan pedoman Material.

  • EdgeContentLayout: memosisikan konten di sekitar tepi layar, seperti CircularProgressIndicator. Saat menggunakan tata letak ini, konten di dalamnya memiliki margin dan padding yang sesuai yang diterapkan secara otomatis.

Arc

Turunan penampung Arc berikut didukung:

  • ArcLine: merender garis melengkung di sekitar Arc.
  • ArcText: merender teks melengkung di Arc.
  • ArcAdapter: merender elemen tata letak dasar di arc, yang digambar bersinggungan dengan arc.

Untuk informasi selengkapnya, lihat dokumentasi referensi untuk setiap jenis elemen.

Pengubah

Setiap elemen tata letak yang tersedia secara opsional dapat memiliki pengubah yang diterapkan padanya. Gunakan pengubah ini untuk tujuan berikut:

  • Mengubah tampilan visual tata letak. Misalnya, tambahkan latar belakang, batas, atau padding ke elemen tata letak.
  • Menambahkan metadata tentang tata letak. Misalnya, menambahkan pengubah semantik ke elemen tata letak untuk digunakan dengan pembaca layar.
  • Menambahkan fungsi. Misalnya, menambahkan pengubah yang dapat diklik ke elemen tata letak agar kartu Anda interaktif. Untuk mengetahui informasi selengkapnya, lihat Berinteraksi dengan kartu.

Misalnya, kita dapat menyesuaikan tampilan default dan metadata Image, seperti yang ditunjukkan dalam contoh kode berikut:

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

Spannable

Spannable adalah jenis penampung khusus yang mengatur tata letak elemen yang mirip dengan teks. Jenis penampung ini berguna jika Anda ingin menerapkan gaya yang berbeda ke hanya satu substring dalam blok teks yang lebih besar, dan tidak mungkin dilakukan dengan elemen Text.

Penampung Spannable diisi dengan turunan Span. Turunan lain, atau instance Spannable bertingkat, tidak diizinkan.

Ada dua jenis turunan Span:

  • SpanText: merender teks dengan gaya tertentu.
  • SpanImage: merender gambar yang inline dengan teks.

Misalnya, Anda dapat mencetak miring kata "dunia" dalam kartu "Halo dunia" dan menyisipkan gambar di antara kata, seperti yang ditunjukkan dalam contoh kode berikut:

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

Menggunakan resource

Kartu tidak memiliki akses ke resource mana pun di aplikasi Anda. Ini berarti Anda tidak boleh meneruskan ID gambar Android ke elemen tata letak Image dan mengharapkannya untuk diselesaikan. Sebagai gantinya, ganti metode onTileResourcesRequest() dan sediakan resource apa pun secara manual.

Terdapat dua cara untuk menyediakan gambar dalam metode onTileResourcesRequest():

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