Szablony wycinków

Ten dokument zawiera szczegółowy opis używania kreatorów szablonów Android Jetpack do tworzenia wycinków.

Definiowanie szablonu wycinka

Wycinki są tworzone za pomocą funkcji ListBuilder Kreator list umożliwia dodawanie różnych typów wierszy wyświetlanych na liście. Ten opisuje każdy z tych typów wierszy i sposób ich budowy.

Działanie na wycinku

Najbardziej podstawowym elementem szablonu wycinka jest SliceAction SliceAction zawiera etykietę razem z PendingIntent i jest jednym z :

  • Przycisk ikony
  • Domyślny przełącznik
  • Niestandardowy przełącznik (element rysowalny, który można włączyć/wyłączyć)

Narzędzie SliceAction jest używane przez kreatory szablonów opisane w dalszej części tego artykułu . W elemencie SliceAction można zdefiniować tryb obrazu, który określa sposób obraz przedstawiający działanie:

  • ICON_IMAGE: malutki rozmiar i możliwość przyciemniania
  • SMALL_IMAGE: mały rozmiar i nie można zabarwić
  • LARGE_IMAGE: największy rozmiar i niemożliwy do przyciemniania

Narzędzie HeaderBuilder

W większości przypadków do ustawienia nagłówka szablonu służy tag HeaderBuilder Nagłówek może obsługiwać:

  • Tytuł
  • Podtytuł
  • Podtytuł podsumowania
  • Główne działanie

Poniżej znajdziesz kilka przykładowych konfiguracji nagłówków. Szare pola pokazują, potencjalne lokalizacje ikon i dopełnienia:

Renderowanie nagłówków na różnych platformach

Jeśli potrzebny jest wycinek, powierzchnia wyświetlania określa sposób renderowania Wycinek. Pamiętaj, że renderowanie może się nieco różnić w zależności od platformy hostingu.

W mniejszych formatach zazwyczaj wyświetlany jest tylko nagłówek (jeśli taki istnieje). Jeśli określisz podsumowanie nagłówka, zamiast tego wyświetli się tekst podsumowania tekst podtytułu.

Jeśli w szablonie nie określisz nagłówka, pierwszy wiersz zostanie dodany do szablonu Zazwyczaj wyświetlana jest wartość ListBuilder.

Przykład narzędzia HeaderBuilder – prosty wycinek listy z nagłówkiem

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

Działania na wycinku w nagłówkach

Nagłówki wycinka mogą też wyświetlać działania wycinka:

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

Wiersz treści możesz utworzyć za pomocą RowBuilder wiersz A obsługuje dowolne z tych formatów:

  • Tytuł
  • Podtytuł
  • Element początkowy: SliceAction, Ikona lub sygnatura czasowa
  • Elementy końcowe: SliceAction, Ikona lub sygnatura czasowa
  • Główne działanie

Zawartość wierszy możesz łączyć na wiele sposobów z zastrzeżeniem następujących ograniczenia:

  • Elementy początkowe nie będą wyświetlane w pierwszym wierszu wycinka
  • Elementy końcowe nie mogą być mieszanką obiektów SliceAction i Icon
  • Wiersz może zawierać tylko 1 sygnaturę czasową

Przykładowe wiersze treści widać na tych obrazach. Pamiętaj, że szare pola pokaż potencjalne lokalizacje ikon i dopełnienia:

Przykład narzędzia RowBuilder – przełącznik Wi-Fi

Przykład poniżej przedstawia wiersz z działaniem głównym i domyślnym przełącznikiem.

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

Kreator siatki

Siatka treści możesz utworzyć za pomocą GridBuilder Siatka może obsługują te typy obrazów:

  • ICON_IMAGE: malutki rozmiar i możliwość przyciemniania
  • SMALL_IMAGE: mały rozmiar i nie można zabarwić
  • LARGE_IMAGE: największy rozmiar i niemożliwy do przyciemniania

Komórkę siatki tworzy się przy użyciu CellBuilder O komórka może zawierać maksymalnie dwa wiersze tekstu i jeden obraz. Komórka nie może być pusta.

Przykłady siatki są widoczne na tych obrazach:

Przykład GridRowBuilder – restauracje w pobliżu

Poniższy przykład pokazuje wiersz siatki zawierający obrazy i tekst.

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

Twórca zakresu

Dzięki RangeBuilder, możesz utworzyć wiersz zawierający pasek postępu lub zakres do wprowadzania danych, za pomocą suwaka.

Przykłady postępu i suwaka znajdują się na tych obrazach:

Przykład narzędzia RangeBuilder – suwak

Przykład poniżej pokazuje, jak utworzyć wycinek zawierający wolumin za pomocą suwaka InputRangeBuilder. Aby utworzyć wiersz postępu, użyj funkcji 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();
}

Opóźniona treść

Wycinek powinien zostać zwrócony jak najszybciej z SliceProvider.onBindSlice() Czasochłonne połączenia mogą powodować problemy z wyświetlaniem, np. migotanie lub gwałtowne dźwięki zmiany rozmiaru.

Jeśli masz treści do wycinka, których nie da się szybko wczytać, możesz Wyciąć fragment za pomocą zmiennej i zaznaczyć w kreatorze, że trwa wczytywanie treści. Gdy zawartość będzie gotowa do wyświetlenia, wywołaj getContentResolver().notifyChange(sliceUri, null) za pomocą identyfikatora URI wycinka. Powoduje to kolejne wywołanie do SliceProvider.onBindSlice(), gdzie można ponownie utworzyć wycinek z nowym treści.

Przykład treści opóźnionych – jazda do pracy

W wierszu „Dojazd do pracy” poniżej odległość do pracy jest określana dynamicznie i mogą nie być dostępne od razu. Przykładowy kod pokazuje użycie pusty napis jako symbol zastępczy podczas wczytywania treści:

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

Uchwyt wyłączony przewijania w wycinku

Platforma wyświetlająca szablon wycinka może nie obsługiwać przewijania w obrębie szablon. W takim przypadku niektóre treści mogą się nie wyświetlać.

Spójrzmy na przykładowy wycinek z listą sieci Wi-Fi:

Jeśli lista sieci Wi-Fi jest długa i wyłączone przewijanie, możesz dodać Pokaż więcej, aby użytkownicy mogli zobaczyć wszystkie elementy w z listy. Aby dodać ten przycisk, użyj polecenia addSeeMoreAction(), jak w tym przykładzie:

Kotlin

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

Java

public Slice seeMoreActionSlice(Uri sliceUri) {
    if (getContext() == null) {
        return null;
    }
    ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY);
    // [START_EXCLUDE]
    listBuilder.addRow(new RowBuilder()
            .setTitle("Hello")
            .setPrimaryAction(createActivityAction())
    );
    // [END_EXCLUDE]
    listBuilder.setSeeMoreAction(seeAllNetworksPendingIntent);
    // [START_EXCLUDE]
    // [END_EXCLUDE]
    return listBuilder.build();
}

Oto obraz:

Kliknięcie Zobacz więcej powoduje wysłanie seeAllNetworksPendingIntent.

Jeśli chcesz podać niestandardowy komunikat lub wiersz, możesz też dodać atrybut RowBuilder:

Kotlin

fun seeMoreRowSlice(sliceUri: Uri) =
    list(context, sliceUri, ListBuilder.INFINITY) {
        // [START_EXCLUDE]
        // [END_EXCLUDE]
        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)
            // [START_EXCLUDE]
            .addRow(new RowBuilder()
                    .setTitle("Hello")
                    .setPrimaryAction(createActivityAction())
            )
            // [END_EXCLUDE]
            .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"))
            );
    // [START_EXCLUDE]
    // [END_EXCLUDE]
    return listBuilder.build();
}

Wiersz lub działanie dodane za pomocą tej metody są wyświetlane tylko wtedy, gdy jeden z poniższych warunków jest spełniony:

  • Osoba wyświetlająca wycinek wyłączył przewijanie widoku
  • Nie wszystkie wiersze mogą być wyświetlone w dostępnym miejscu

Łączenie szablonów

Możesz utworzyć bogaty, dynamiczny wycinek, łącząc wiele typów wierszy. Dla: wycinek może np. zawierać wiersz nagłówka, siatkę z jednym obrazem oraz siatkę z dwiema komórkami z tekstem.

Oto wycinek z wierszem nagłówka i siatką zawierającą 3 komórki.