Este documento traz detalhes sobre como usar os builders de modelo no Android Jetpack para criar Slices.
Definir seu modelo Slice
Os Slices são criados com um
ListBuilder. O ListBuilder
permite adicionar diferentes tipos de linhas que são exibidas em uma lista. Esta
seção descreve cada um desses tipos de linha e como eles são criados.
SliceAction
O elemento mais básico de um modelo Slice é uma
SliceAction. Uma SliceAction
contém uma etiqueta junto com um
PendingIntent e pode ser um dos
itens a seguir:
- Botão de ícone
- Alternância padrão
- Alternância personalizada (drawable com um estado ativado/desativado)
A SliceAction é usada pelos builders de modelo descritos no restante desta
seção. Uma SliceAction pode ter um modo de imagem definido que determina como a
imagem será apresentada para a ação:
ICON_IMAGE: tamanho muito pequeno e coloridaSMALL_IMAGE: tamanho pequeno e não coloridaLARGE_IMAGE: tamanho máximo e não colorida
HeaderBuilder
Na maioria dos casos, é preciso definir um cabeçalho para o modelo usando um
HeaderBuilder.
Um cabeçalho pode ser compatível com:
- Título
- Subtítulo
- Subtítulo de resumo
- Ação principal
Veja abaixo alguns exemplos de configurações de cabeçalho. As caixas cinza mostram possíveis locais de ícones e padding:




Renderização de cabeçalho em diferentes superfícies
Quando um Slice é necessário, a superfície em exibição determina como renderizá-lo. A renderização pode apresentar algumas diferenças entre as superfícies de hospedagem.
Em formatos menores, apenas o cabeçalho, se existir, costuma ser exibido. Se você especificou um resumo para o cabeçalho, o texto do resumo será exibido em vez do texto do subtítulo.
Se você não especificou um cabeçalho no modelo, a primeira linha adicionada ao
ListBuilder é geralmente exibida.


Exemplo de HeaderBuilder: Slice de lista simples com cabeçalho
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 nos cabeçalhos
Os cabeçalhos de Slices também podem exibir 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
Você pode criar uma linha de conteúdo por meio de um
RowBuilder. Uma linha
pode ser compatível com qualquer destes itens:
- Título
- Subtítulo
- Item de início: SliceAction, ícone ou carimbo de data/hora
- Itens de término: SliceAction, ícone ou carimbo de data/hora
- Ação principal
É possível combinar conteúdos de linha de várias formas, de acordo com as seguintes restrições:
- Os itens de início não são exibidos na primeira linha de um Slice.
- Os itens de término não podem ser uma mistura de objetos
SliceActioneIcon. - Uma linha pode conter apenas um carimbo de data/hora.
Veja exemplos de linha de conteúdo nas imagens a seguir. As caixas cinza mostram possíveis locais de ícones e padding:



Exemplo de RowBuilder: alternância de Wi-Fi
O exemplo abaixo demonstra uma linha com uma ação principal e uma alternância padrão.

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
Você pode criar uma grade de conteúdo por meio de um
GridBuilder. Uma grade pode
ser compatível com os seguintes tipos de imagem:
ICON_IMAGE: tamanho muito pequeno e coloridaSMALL_IMAGE: tamanho pequeno e não coloridaLARGE_IMAGE: tamanho máximo e não colorida
Uma célula de grade é criada com um
CellBuilder. Uma
célula pode ser compatível com até duas linhas de texto e uma imagem. Uma célula não pode ficar vazia.
Veja exemplos de grade nas imagens a seguir:



Exemplo de GridRowBuilder: restaurantes por perto
O exemplo abaixo demonstra uma linha de grade que contém imagens e texto.

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
Com um
RangeBuilder,
você pode criar uma linha que contenha uma barra de progresso ou um intervalo de entrada, como
um controle deslizante.
Veja exemplos de barra de progresso e controle deslizante nas seguintes imagens:


Exemplo de RangeBuilder: controle deslizante
O exemplo abaixo demonstra como criar um Slice que contém um controle
deslizante de volume por meio de um InputRangeBuilder. Para criar uma linha de progresso, use
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(); }
Conteúdo atrasado
Retorne um Slice o mais rápido possível a partir de
SliceProvider.onBindSlice().
Chamadas demoradas podem causar problemas de exibição, como oscilações e redimensionamento
abrupto.
Se você tiver conteúdo de Slice que não pode ser carregado rapidamente, crie o
Slice com conteúdo de marcador e observe no builder que o
conteúdo está carregando. Quando o conteúdo estiver pronto para exibição, chame
getContentResolver().notifyChange(sliceUri, null)
por meio do URI do Slice. Isso resultará em outra chamada para
SliceProvider.onBindSlice(), em que você pode criar o Slice novamente com conteúdo
novo.
Exemplo de conteúdo atrasado: deslocamento para o trabalho
Na linha "Ride to work" abaixo, a distância até o trabalho é determinada dinamicamente e pode não estar disponível de imediato. O exemplo de código demonstra o uso de um subtítulo nulo como marcador enquanto o conteúdo é carregado:

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" ); }
Processar rolagem desativada no Slice
A superfície que apresenta seu modelo Slice pode não ser compatível com a rolagem no modelo. Nesse caso, parte do conteúdo pode não ser exibida.
Por exemplo, considere um Slice que exibe uma lista de redes Wi-Fi:

Se a lista de Wi-Fi for longa e a rolagem estiver desativada, você poderá adicionar um
botão Ver mais para que os usuários possam ver todos os itens
da lista. Para adicionar esse botão, use
addSeeMoreAction(),
conforme mostrado no exemplo a seguir:
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(); }
O resultado pode ser visto nesta imagem:

O toque em Ver mais envia seeAllNetworksPendingIntent.
Como alternativa, se você quiser mostrar uma mensagem ou linha personalizada, adicione um 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(); }
A linha ou ação adicionada por esse método é exibida apenas quando uma das seguintes condições é atendida:
- O apresentador do Slice desativou a rolagem na visualização.
- Nem todas as linhas podem ser exibidas no espaço disponível.
Combinar modelos
É possível criar um Slice avançado e dinâmico combinando vários tipos de linha. Por exemplo, um Slice pode conter uma linha de cabeçalho, uma grade com uma única imagem e uma grade com duas células de texto.

Veja um Slice com uma linha de cabeçalho e uma grade com três células.
