Modelli di sezioni

Questo documento fornisce dettagli su come utilizzare i generatori di modelli in Android Jetpack per creare Slices.

Definisci il modello della sezione

Le sezioni vengono create utilizzando ListBuilder ListBuilder consente di aggiungere diversi tipi di righe da visualizzare in un elenco. Questo che descrive ognuno di questi tipi di riga e il modo in cui sono stati creati.

Azione sezione

L'elemento fondamentale di un modello di sezione è SliceAction SliceAction contiene un'etichetta insieme a PendingIntent ed è uno dei seguenti:

  • Pulsante icona
  • Pulsante di attivazione/disattivazione predefinito
  • Pulsante di attivazione/disattivazione personalizzato (un elemento disegnabile con stato On/Off)

SliceAction viene utilizzato dai generatori di modelli descritti in questa parte . Per un SliceAction può essere definita una modalità immagine che determina il modo in cui viene presentata l'immagine per l'azione:

  • ICON_IMAGE: dimensioni minime e incompatibile
  • SMALL_IMAGE: dimensioni ridotte e non colorabili
  • LARGE_IMAGE: dimensione massima e non colorabile

HeaderBuilder

Nella maggior parte dei casi, devi impostare un'intestazione per il modello utilizzando un HeaderBuilder Un'intestazione può supportare quanto segue:

  • Titolo
  • Sottotitolo
  • Sottotitolo riepilogo
  • Azione principale

Di seguito sono riportate alcune configurazioni di intestazione di esempio. Le caselle grigie mostrano potenziali posizioni di icona e spaziatura interna:

Rendering dell'intestazione su piattaforme diverse

Quando è necessaria una sezione, la superficie di visualizzazione determina come eseguire il rendering Sezione. Tieni presente che il rendering potrebbe differire leggermente tra le piattaforme di hosting.

Nei formati più piccoli, di solito viene visualizzata solo l'intestazione, se esistente. Se hai specificato un riepilogo per l'intestazione, al posto della viene mostrato il testo di riepilogo il testo dei sottotitoli.

Se non hai specificato un'intestazione nel modello, la prima riga aggiunta al tuo In genere, invece, viene visualizzato ListBuilder.

Esempio di HeaderBuilder - Sezione con elenco semplice con intestazione

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

SliceAzioni nelle intestazioni

Le intestazioni delle sezioni possono anche visualizzare Slice Actions:

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

Puoi creare una riga di contenuti utilizzando una RowBuilder Riga A può supportare quanto segue:

  • Titolo
  • Sottotitolo
  • Elemento iniziale: SliceAction, Icona o timestamp
  • Elementi finali: SliceAction, Icona o un timestamp
  • Azione principale

Puoi combinare i contenuti delle righe in diversi modi, rispettando quanto segue: restrizioni:

  • Gli elementi iniziali non verranno visualizzati nella prima riga di una sezione
  • Gli elementi finali non possono essere una combinazione di oggetti SliceAction e Icon oggetti
  • Una riga può contenere un solo timestamp

Nelle seguenti immagini vengono mostrate righe di contenuti di esempio. Tieni presente che le caselle grigie mostra potenziali posizioni di icona e spaziatura interna:

Esempio di RowBuilder: pulsante di attivazione/disattivazione del Wi-Fi

L'esempio seguente mostra una riga con un'azione principale e un pulsante di attivazione/disattivazione predefinito.

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

Strumento di creazione griglia

Puoi creare una griglia di contenuti utilizzando un GridBuilder Una griglia può supportano i seguenti tipi di immagini:

  • ICON_IMAGE: dimensioni minime e incompatibile
  • SMALL_IMAGE: dimensioni ridotte e non colorabili
  • LARGE_IMAGE: dimensione massima e non colorabile

Una cella della griglia viene creata utilizzando CellBuilder R può supportare fino a due righe di testo e un'immagine. Una cella non può essere vuota.

Gli esempi di griglia sono mostrati nelle seguenti immagini:

Esempio di GridRowBuilder - Ristoranti nelle vicinanze

L'esempio seguente mostra una riga di griglia che contiene immagini e testo.

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

Generatore di intervalli

Con un RangeBuilder, puoi creare una riga contenente una barra di avanzamento o un intervallo di input, come cursore.

Gli esempi di avanzamento e scorrimento sono mostrati nelle seguenti immagini:

Esempio di RangeBuilder - Dispositivo di scorrimento

L'esempio seguente mostra come creare una sezione contenente un volume usando un InputRangeBuilder. Per creare una riga di avanzamento, utilizza 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();
}

Contenuti in ritardo

Dovresti restituire una sezione il più rapidamente possibile da SliceProvider.onBindSlice() Le chiamate dispendiose in termini di tempo possono determinare problemi di visualizzazione, ad esempio sfarfallio e improvvisi del ridimensionamento.

Se alcuni contenuti della sezione non possono essere caricati rapidamente, puoi creare Suddividi con contenuti segnaposto tenendo presente nel builder che Caricamento dei contenuti in corso. Quando i contenuti sono pronti per essere visualizzati, richiama getContentResolver().notifyChange(sliceUri, null) utilizzando l'URI della sezione. Viene così creata un'altra chiamata SliceProvider.onBindSlice(), dove puoi creare di nuovo la sezione con nuovi contenuti.

Esempio di contenuti in ritardo: Vai al lavoro

Nella riga Andare al lavoro in basso, la distanza dal lavoro è determinata in modo dinamico e potrebbe non essere disponibile immediatamente. Il codice di esempio mostra l'utilizzo di un sottotitolo nullo come segnaposto durante il caricamento dei contenuti:

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

Gestire lo scorrimento disattivato all'interno della Sezione

La superficie in cui viene presentato il modello della sezione potrebbe non supportare lo scorrimento all'interno della sezione modello. In questo caso, alcuni dei tuoi contenuti potrebbero non essere visualizzati.

Ad esempio, consideriamo una sezione in cui viene mostrato un elenco di reti Wi-Fi:

Se l'elenco Wi-Fi è lungo e se lo scorrimento è disattivato, puoi aggiungere Mostra altro per consentire agli utenti di visualizzare tutti gli elementi nel dall'elenco di lettura. Puoi aggiungere questo pulsante utilizzando addSeeMoreAction(), come mostrato nell'esempio seguente:

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

Questo viene visualizzato come mostrato nell'immagine seguente:

Se tocchi Altro, viene inviato seeAllNetworksPendingIntent.

In alternativa, se vuoi fornire un messaggio o una riga personalizzata, valuta la possibilità di aggiungere un 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();
}

La riga o l'azione aggiunta tramite questo metodo viene visualizzata solo quando una delle seguenti condizioni soddisfa i requisiti:

  • Il presentatore della sezione ha disattivato lo scorrimento nella visualizzazione
  • Non tutte le righe possono essere visualizzate nello spazio disponibile

Combinare i modelli

Puoi creare una sezione ricca e dinamica combinando più tipi di righe. Per Ad esempio, una sezione può contenere una riga di intestazione, una griglia con una singola immagine una griglia con due celle di testo.

Ecco una sezione con una riga di intestazione e una griglia che contiene tre celle.