Template Slice

Dokumen ini memberikan detail tentang cara menggunakan builder template di Android Jetpack untuk membuat Slice.

Menentukan template Slice Anda

Slice dibuat menggunakan ListBuilder. ListBuilder memungkinkan Anda menambahkan berbagai jenis baris yang ditampilkan dalam daftar. Bagian ini menjelaskan masing-masing jenis baris tersebut dan cara pembuatannya.

SliceAction

Elemen yang paling dasar dari template Slice adalah SliceAction. Suatu SliceAction berisi label bersama dengan PendingIntent dan merupakan salah satu dari tombol berikut:

  • Tombol ikon
  • Tombol default
  • Tombol kustom (drawable dengan status on/off)

SliceAction digunakan oleh builder template yang dijelaskan sepanjang bagian ini. Suatu SliceAction dapat memiliki mode gambar yang ditetapkan, yang menentukan cara gambar ditampilkan untuk tindakan tersebut:

  • ICON_IMAGE: berukuran sangat kecil dan dapat diberi warna
  • SMALL_IMAGE: berukuran kecil dan tidak dapat diberi warna
  • LARGE_IMAGE: ukuran terbesar dan tidak dapat diberi warna

HeaderBuilder

Pada umumnya, Anda harus menetapkan header untuk template menggunakan HeaderBuilder. Header dapat mendukung hal berikut:

  • Judul
  • Subtitel
  • Subtitel ringkasan
  • Tindakan utama

Beberapa contoh konfigurasi header ditunjukkan di bawah ini. Perhatikan bahwa kotak abu-abu menunjukkan ikon potensial dan lokasi padding:

Rendering header pada permukaan yang berbeda

Jika Slice diperlukan, permukaan tampilan menentukan cara merender Slice. Perhatikan bahwa rendering mungkin agak berbeda antara permukaan hosting.

Dalam format yang lebih kecil, biasanya hanya header yang akan ditampilkan, jika ada. Jika Anda telah menentukan ringkasan untuk header, teks ringkasan tersebut akan ditampilkan, bukan subtitel.

Jika Anda belum menentukan header dalam template, baris pertama yang ditambahkan ke ListBuilder biasanya akan ditampilkan sebagai gantinya.

Contoh HeaderBuilder - Slice daftar sederhana dengan header

Kotlin

    fun createSliceWithHeader(sliceUri: Uri) =
        list(context, sliceUri, ListBuilder.INFINITY) {
            setAccentColor(0xff0F9D) // Specify color for tinting icons
            header {
                title = "Get a ride"
                subtitle = "Ride in 4 min"
                summary = "Work in 1 hour 45 min | Home in 12 min"
            }
            row {
                title = "Home"
                subtitle = "12 miles | 12 min | $9.00"
                addEndItem(
                    IconCompat.createWithResource(context, R.drawable.ic_home),
                    ListBuilder.ICON_IMAGE
                )
            }
        }
    

Java

    public Slice createSliceWithHeader(Uri sliceUri) {
        if (getContext() == null) {
            return null;
        }

        // Construct the parent.
        ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
                .setAccentColor(0xff0F9D58) // Specify color for tinting icons.
                .setHeader( // Create the header and add to slice.
                        new HeaderBuilder()
                                .setTitle("Get a ride")
                                .setSubtitle("Ride in 4 min.")
                                .setSummary("Work in 1 hour 45 min | Home in 12 min.")
                ).addRow(new RowBuilder() // Add a row.
                        .setPrimaryAction(
                                createActivityAction()) // A slice always needs a SliceAction.
                        .setTitle("Home")
                        .setSubtitle("12 miles | 12 min | $9.00")
                        .addEndItem(IconCompat.createWithResource(getContext(), R.drawable.ic_home),
                                SliceHints.ICON_IMAGE)
                ); // Add more rows if needed...
        return listBuilder.build();
    }
    

SliceActions pada header

Header slice juga dapat menampilkan SliceActions:

Kotlin

    fun createSliceWithActionInHeader(sliceUri: Uri): Slice {
        // Construct our slice actions.
        val noteAction = SliceAction.create(
            takeNoteIntent,
            IconCompat.createWithResource(context, R.drawable.ic_pencil),
            ICON_IMAGE,
            "Take note"
        )

        val voiceNoteAction = SliceAction.create(
            voiceNoteIntent,
            IconCompat.createWithResource(context, R.drawable.ic_mic),
            ICON_IMAGE,
            "Take voice note"
        )

        val cameraNoteAction = SliceAction.create(
            cameraNoteIntent,
            IconCompat.createWithResource(context, R.drawable.ic_camera),
            ICON_IMAGE,
            "Create photo note"
        )

        // Construct the list.
        return list(context, sliceUri, ListBuilder.INFINITY) {
            setAccentColor(0xfff4b4) // Specify color for tinting icons
            header {
                title = "Create new note"
                subtitle = "Easily done with this note taking app"
            }
            addAction(noteAction)
            addAction(voiceNoteAction)
            addAction(cameraNoteAction)
        }
    }
    

Java

    public Slice createSliceWithActionInHeader(Uri sliceUri) {
        if (getContext() == null) {
            return null;
        }
        // Construct our slice actions.
        SliceAction noteAction = SliceAction.create(takeNoteIntent,
                IconCompat.createWithResource(getContext(), R.drawable.ic_pencil),
                ListBuilder.ICON_IMAGE, "Take note");

        SliceAction voiceNoteAction = SliceAction.create(voiceNoteIntent,
                IconCompat.createWithResource(getContext(), R.drawable.ic_mic),
                ListBuilder.ICON_IMAGE,
                "Take voice note");

        SliceAction cameraNoteAction = SliceAction.create(cameraNoteIntent,
                IconCompat.createWithResource(getContext(), R.drawable.ic_camera),
                ListBuilder.ICON_IMAGE,
                "Create photo note");

        // Construct the list.
        ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
                .setAccentColor(0xfff4b400) // Specify color for tinting icons
                .setHeader(new HeaderBuilder() // Construct the header.
                        .setTitle("Create new note")
                        .setSubtitle("Easily done with this note taking app")
                )
                .addRow(new RowBuilder()
                        .setTitle("Enter app")
                        .setPrimaryAction(createActivityAction())
                )
                // Add the actions to the ListBuilder.
                .addAction(noteAction)
                .addAction(voiceNoteAction)
                .addAction(cameraNoteAction);
        return listBuilder.build();
    }
    

RowBuilder

Anda dapat membuat baris konten dengan menggunakan RowBuilder. Satu baris dapat mendukung salah satu dari item berikut:

  • Judul
  • Subtitel
  • Item awal: SliceAction, Ikon, atau stempel waktu
  • Item akhir: SliceAction, Ikon, atau stempel waktu
  • Tindakan utama

Anda dapat menggabungkan konten baris dalam beberapa cara, sesuai dengan batasan berikut:

  • Item awal tidak akan ditampilkan di baris pertama Slice
  • Item akhir tidak boleh berupa campuran objek SliceAction dan objek Icon
  • Satu baris hanya dapat berisi satu stempel waktu

Contoh baris konten ditampilkan dalam gambar berikut. Perhatikan bahwa kotak abu-abu menampilkan ikon potensial dan lokasi padding:

Contoh RowBuilder - Tombol Wi-Fi

Contoh di bawah ini menunjukkan baris dengan tindakan utama dan tombol default.

Kotlin

    fun createActionWithActionInRow(sliceUri: Uri): Slice {
        // Primary action - open wifi settings.
        val wifiAction = SliceAction.create(
            wifiSettingsPendingIntent,
            IconCompat.createWithResource(context, R.drawable.ic_wifi),
            ICON_IMAGE,
            "Wi-Fi Settings"
        )

        // Toggle action - toggle wifi.
        val toggleAction = SliceAction.createToggle(
            wifiTogglePendingIntent,
            "Toggle Wi-Fi",
            isConnected /* isChecked */
        )

        // Create the parent builder.
        return list(context, wifiUri, ListBuilder.INFINITY) {
            setAccentColor(0xff4285) // Specify color for tinting icons / controls.
            row {
                title = "Wi-Fi"
                primaryAction = wifiAction
                addEndItem(toggleAction)
            }
        }
    }
    

Java

    public Slice createActionWithActionInRow(Uri sliceUri) {
        if (getContext() == null) {
            return null;
        }
        // Primary action - open wifi settings.
        SliceAction primaryAction = SliceAction.create(wifiSettingsPendingIntent,
                IconCompat.createWithResource(getContext(), R.drawable.ic_wifi),
                ListBuilder.ICON_IMAGE,
                "Wi-Fi Settings"
        );

        // Toggle action - toggle wifi.
        SliceAction toggleAction = SliceAction.createToggle(wifiTogglePendingIntent,
                "Toggle Wi-Fi", isConnected /* isChecked */);

        // Create the parent builder.
        ListBuilder listBuilder = new ListBuilder(getContext(), wifiUri, ListBuilder.INFINITY)
                // Specify color for tinting icons / controls.
                .setAccentColor(0xff4285f4)
                // Create and add a row.
                .addRow(new RowBuilder()
                        .setTitle("Wi-Fi")
                        .setPrimaryAction(primaryAction)
                        .addEndItem(toggleAction));
        // Build the slice.
        return listBuilder.build();
    }
    

GridBuilder

Anda dapat membuat grid konten menggunakan GridBuilder. Suatu grid dapat mendukung jenis gambar berikut:

  • ICON_IMAGE: berukuran sangat kecil dan dapat diberi warna
  • SMALL_IMAGE: berukuran kecil dan tidak dapat diberi warna
  • LARGE_IMAGE: ukuran terbesar dan tidak dapat diberi warna

Sel grid dibuat menggunakan CellBuilder. Suatu sel dapat mendukung hingga dua baris teks dan satu gambar. Sel tidak boleh kosong.

Contoh grid ditampilkan dalam gambar berikut:

Contoh GridRowBuilder - Restoran di sekitar

Contoh di bawah ini menunjukkan baris grid yang berisi gambar dan teks.

Kotlin

    fun createSliceWithGridRow(sliceUri: Uri): Slice {
        // Create the parent builder.
        return list(context, sliceUri, ListBuilder.INFINITY) {
            header {
                title = "Famous restaurants"
                primaryAction = SliceAction.create(
                    pendingIntent, icon, ListBuilder.ICON_IMAGE, "Famous restaurants"
                )
            }
            gridRow {
                cell {
                    addImage(image1, LARGE_IMAGE)
                    addTitleText("Top Restaurant")
                    addText("0.3 mil")
                    contentIntent = intent1
                }
                cell {
                    addImage(image2, LARGE_IMAGE)
                    addTitleText("Fast and Casual")
                    addText("0.5 mil")
                    contentIntent = intent2
                }
                cell {
                    addImage(image3, LARGE_IMAGE)
                    addTitleText("Casual Diner")
                    addText("0.9 mi")
                    contentIntent = intent3
                }
                cell {
                    addImage(image4, LARGE_IMAGE)
                    addTitleText("Ramen Spot")
                    addText("1.2 mi")
                    contentIntent = intent4
                }
            }
        }
    }
    

Java

    public Slice createSliceWithGridRow(Uri sliceUri) {
        if (getContext() == null) {
            return null;
        }
        // Create the parent builder.
        ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
                .setHeader(
                        // Create the header.
                        new HeaderBuilder()
                                .setTitle("Famous restaurants")
                                .setPrimaryAction(SliceAction
                                        .create(pendingIntent, icon, ListBuilder.ICON_IMAGE,
                                                "Famous restaurants"))
                )
                // Add a grid row to the list.
                .addGridRow(new GridRowBuilder()
                        // Add cells to the grid row.
                        .addCell(new CellBuilder()
                                .addImage(image1, ListBuilder.LARGE_IMAGE)
                                .addTitleText("Top Restaurant")
                                .addText("0.3 mil")
                                .setContentIntent(intent1)
                        ).addCell(new CellBuilder()
                                .addImage(image2, ListBuilder.LARGE_IMAGE)
                                .addTitleText("Fast and Casual")
                                .addText("0.5 mil")
                                .setContentIntent(intent2)
                        )
                        .addCell(new CellBuilder()
                                .addImage(image3, ListBuilder.LARGE_IMAGE)
                                .addTitleText("Casual Diner")
                                .addText("0.9 mi")
                                .setContentIntent(intent3))
                        .addCell(new CellBuilder()
                                .addImage(image4, ListBuilder.LARGE_IMAGE)
                                .addTitleText("Ramen Spot")
                                .addText("1.2 mi")
                                .setContentIntent(intent4))
                        // Every slice needs a primary action.
                        .setPrimaryAction(createActivityAction())
                );
        return listBuilder.build();
    }
    

RangeBuilder

Dengan RangeBuilder, Anda dapat membuat baris yang berisi status progres atau rentang masukan, seperti penggeser.

Contoh progress dan penggeser ditampilkan dalam gambar berikut:

Contoh RangeBuilder - Penggeser

Contoh di bawah ini menunjukkan cara mem-build Slice yang berisi penggeser volume menggunakan InputRangeBuilder. Untuk membuat baris progres, gunakan addRange().

Kotlin

    fun createSliceWithRange(sliceUri: Uri): Slice {
        return list(context, sliceUri, ListBuilder.INFINITY) {
            inputRange {
                title = "Ring Volume"
                inputAction = volumeChangedPendingIntent
                max = 100
                value = 30
            }
        }
    }
    

Java

    public Slice createSliceWithRange(Uri sliceUri) {
        if (getContext() == null) {
            return null;
        }
        // Construct the parent.
        ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
                .addRow(new RowBuilder() // Every slice needs a row.
                        .setTitle("Enter app")
                         // Every slice needs a primary action.
                        .setPrimaryAction(createActivityAction())
                )
                .addInputRange(new InputRangeBuilder() // Create the input row.
                        .setTitle("Ring Volume")
                        .setInputAction(volumeChangedPendingIntent)
                        .setMax(100)
                        .setValue(30)
                );
        return listBuilder.build();
    }
    

Konten yang tertunda

Anda harus mengembalikan Slice secepatnya dari SliceProvider#onBindSlice. Panggilan yang memakan waktu dapat menyebabkan masalah tampilan, seperti kedipan dan perubahan ukuran yang mendadak.

Jika memiliki konten Slice yang tidak dapat dimuat dengan cepat, Anda dapat membuat Slice dengan null atau konten placeholder sembari memberi catatan di builder bahwa konten sedang dimuat. Setelah konten siap ditampilkan, panggil getContentResolver().notifyChange(sliceUri, null) menggunakan URI Slice Anda. Hal ini mengakibatkan panggilan lain ke SliceProvider#onBindSlice, tempat Anda dapat membuat Slice lagi dengan konten baru.

Contoh konten yang tertunda - Berkendara ke kantor

Di baris Berkendara ke kantor di bawah ini, jarak ke tempat kerja ditentukan secara dinamis dan mungkin tidak langsung tersedia. Kode contoh menunjukkan penggunaan subtitel null sebagai placeholder saat konten dimuat:

Kotlin

    fun createSliceShowingLoading(sliceUri: Uri): Slice {
        // We’re waiting to load the time to work so indicate that on the slice by
        // setting the subtitle with the overloaded method and indicate true.
        return list(context, sliceUri, ListBuilder.INFINITY) {
            row {
                title = "Ride to work"
                setSubtitle(null, true)
                addEndItem(IconCompat.createWithResource(context, R.drawable.ic_work), ICON_IMAGE)
            }
        }
    }
    

Java

    public Slice createSliceShowingLoading(Uri sliceUri) {
        if (getContext() == null) {
            return null;
        }
        // Construct the parent.
        ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
                // Construct the row.
                .addRow(new RowBuilder()
                        .setPrimaryAction(createActivityAction())
                        .setTitle("Ride to work")
                        // We’re waiting to load the time to work so indicate that on the slice by
                        // setting the subtitle with the overloaded method and indicate true.
                        .setSubtitle(null, true)
                        .addEndItem(IconCompat.createWithResource(getContext(), R.drawable.ic_work),
                                ListBuilder.ICON_IMAGE)
                );
        return listBuilder.build();
    }

    private SliceAction createActivityAction() {
        return SliceAction.create(
                PendingIntent.getActivity(
                        getContext(),
                        0,
                        new Intent(getContext(), MainActivity.class),
                        0
                ),
                IconCompat.createWithResource(getContext(), R.drawable.ic_home),
                ListBuilder.ICON_IMAGE,
                "Enter app"
        );
    }
    

Menangani scroll nonaktif dalam Slice Anda

Permukaan yang menampilkan template Slice Anda mungkin tidak mendukung scrolling di dalam template. Dalam hal ini, beberapa konten Anda mungkin tidak ditampilkan.

Sebagai contoh, anggap sebuah Slice menampilkan daftar jaringan Wi-Fi:

Jika daftar Wi-Fi panjang, dan jika scrolling dinonaktifkan, Anda dapat menambahkan tombol Lihat lainnya untuk memastikan bahwa pengguna memiliki cara untuk melihat semua item dalam daftar. Anda dapat menambahkan tombol ini dengan menggunakan addSeeMoreAction(), seperti yang ditunjukkan pada contoh berikut:

Kotlin

    fun seeMoreActionSlice(sliceUri: Uri) =
        list(context, sliceUri, ListBuilder.INFINITY) {
            // ...
            setSeeMoreAction(seeAllNetworksPendingIntent)
            // ...
        }
    

Java

    public Slice seeMoreActionSlice(Uri sliceUri) {
        if (getContext() == null) {
            return null;
        }
        ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY);
        // ...
        listBuilder.setSeeMoreAction(seeAllNetworksPendingIntent);
        // ...
        return listBuilder.build();
    }
    

Ini akan ditampilkan seperti yang ditunjukkan pada gambar berikut:

Mengetuk Lihat lainnya akan mengirim seeAllNetworksPendingIntent.

Selain itu, jika Anda ingin menyediakan baris atau pesan kustom, pertimbangkan untuk menambahkan RowBuilder:

Kotlin

    fun seeMoreRowSlice(sliceUri: Uri) =
        list(context, sliceUri, ListBuilder.INFINITY) {
            // ...
            seeMoreRow {
                title = "See all available networks"
                addEndItem(
                    IconCompat.createWithResource(context, R.drawable.ic_right_caret), ICON_IMAGE
                )
                primaryAction = SliceAction.create(
                    seeAllNetworksPendingIntent,
                    IconCompat.createWithResource(context, R.drawable.ic_wifi),
                    ListBuilder.ICON_IMAGE,
                    "Wi-Fi Networks"
                )
            }
        }
    

Java

    public Slice seeMoreRowSlice(Uri sliceUri) {
        if (getContext() == null) {
            return null;
        }
        ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
                // ...
                .setSeeMoreRow(new RowBuilder()
                        .setTitle("See all available networks")
                        .addEndItem(IconCompat
                                        .createWithResource(getContext(), R.drawable
                                                .ic_right_caret),
                                ListBuilder.ICON_IMAGE)
                        .setPrimaryAction(SliceAction.create(seeAllNetworksPendingIntent,
                                IconCompat.createWithResource(getContext(), R.drawable.ic_wifi),
                                ListBuilder.ICON_IMAGE,
                                "Wi-Fi Networks"))
                );
        // ...
        return listBuilder.build();
    }
    

Baris atau tindakan yang ditambahkan melalui metode ini hanya ditampilkan jika salah satu kondisi berikut terpenuhi:

  • Presenter Slice Anda telah menonaktifkan scrolling pada tampilan
  • Tidak semua baris dapat ditampilkan di ruang yang tersedia

Menggabungkan template

Anda dapat membuat Slice dinamis yang kaya dengan menggabungkan beberapa jenis baris. Sebagai contoh, sebuah Slice dapat berisi baris header, grid dengan satu gambar, dan grid dengan dua sel teks.

Berikut adalah sebuah Slice dengan baris header bersama dengan grid yang berisi tiga sel.