Suchleiste

Verwenden Sie eine Suchleiste, um die Suchfunktion zu implementieren. Eine Suchleiste ist ein dauerhaftes Suchfeld, in das Nutzer ein Keyword oder eine Wortgruppe eingeben können, um relevante Ergebnisse in Ihrer App zu sehen. Sie wird empfohlen, wenn die Suche der Hauptfokus Ihrer App ist.

Es werden zwei Suchleisten angezeigt. Die linke hat nur ein Textfeld.
  Die Suchleiste auf der linken Seite enthält ein Textfeld und einen Suchvorschlag darunter.
Abbildung 1 Eine einfache Suchleiste (1) und eine Suchleiste mit Vorschlag (2).

API-Oberfläche

Verwenden Sie das SearchBar-Element, um Suchleisten zu implementieren. Zu den wichtigsten Parametern für diese Composeable-Funktion gehören:

  • inputField: Definiert das Eingabefeld der Suchleiste. In der Regel wird SearchBarDefaults.InputField verwendet, was die Anpassung folgender Elemente ermöglicht:
    • query: Der Suchbegriff, der im Eingabefeld angezeigt werden soll.
    • onQueryChange: Lambda zum Verarbeiten von Änderungen am Abfragestring.
  • expanded: Ein boolescher Wert, der angibt, ob die Suchleiste maximiert ist, um Vorschläge oder gefilterte Ergebnisse anzuzeigen.
  • onExpandedChange: Lambda zum Verwalten von Änderungen am maximierten Zustand des Drop-down-Menüs.

  • content: Der Inhalt dieser Suchleiste, um Suchergebnisse unter dem inputField anzuzeigen.

Dieses Snippet zeigt eine grundlegende Implementierung von SearchBar mit Vorschlägen:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SimpleSearchBar(
    textFieldState: TextFieldState,
    onSearch: (String) -> Unit,
    searchResults: List<String>,
    modifier: Modifier = Modifier
) {
    // Controls expansion state of the search bar
    var expanded by rememberSaveable { mutableStateOf(false) }

    Box(
        modifier
            .fillMaxSize()
            .semantics { isTraversalGroup = true }
    ) {
        SearchBar(
            modifier = Modifier
                .align(Alignment.TopCenter)
                .semantics { traversalIndex = 0f },
            inputField = {
                SearchBarDefaults.InputField(
                    query = textFieldState.text.toString(),
                    onQueryChange = { textFieldState.edit { replace(0, length, it) } },
                    onSearch = {
                        onSearch(textFieldState.text.toString())
                        expanded = false
                    },
                    expanded = expanded,
                    onExpandedChange = { expanded = it },
                    placeholder = { Text("Search") }
                )
            },
            expanded = expanded,
            onExpandedChange = { expanded = it },
        ) {
            // Display search results in a scrollable column
            Column(Modifier.verticalScroll(rememberScrollState())) {
                searchResults.forEach { result ->
                    ListItem(
                        headlineContent = { Text(result) },
                        modifier = Modifier
                            .clickable {
                                textFieldState.edit { replace(0, length, result) }
                                expanded = false
                            }
                            .fillMaxWidth()
                    )
                }
            }
        }
    }
}

Wichtige Punkte zum Code

  • Mit rememberSaveable wird sichergestellt, dass die Suchleiste bei Konfigurationsänderungen maximiert oder minimiert bleibt. Der gespeicherte Wert wird in das savedInstanceState-Bundle der hostenden Aktivität geschrieben, bevor die Aktivität bei einer Konfigurationsänderung gelöscht wird.
  • Mit der Modifikatortaste semantics wird die TalkBack-Durchlaufreihenfolge gesteuert.
    • isTraversalGroup ist für Box festgelegt, um alle untergeordneten Composeables zu gruppieren.
    • Mit traversalIndex wird die Reihenfolge festgelegt, in der TalkBack Informationen zur Barrierefreiheit von den einzelnen Mitgliedern der Gruppe liest. TalkBack liest Informationen zur Barrierefreiheit von einem Peer mit einem negativen Wert, z. B. -1, vor einem Peer mit einem positiven Wert, z. B. 1. Da es sich bei dem Wert um einen Gleitkommawert handelt, können Sie eine benutzerdefinierte Reihenfolge vieler Peers angeben, indem Sie für jeden Peer Werte zwischen -1.0 und 1.0 festlegen.
  • Die SearchBar enthält ein inputField für die Nutzereingabe und ein Column, um Suchvorschläge anzuzeigen.
    • SearchBarDefaults.InputField erstellt das Eingabefeld und verarbeitet Änderungen an der Nutzerabfrage.
    • onQueryChange verarbeitet die Texteingabe und aktualisiert den Status, sobald sich der Text im Eingabefeld ändert.
    • Mit dem Status The expanded wird die Sichtbarkeit der Vorschlagsliste gesteuert.
  • searchResults.forEach { result -> … } iteriert durch die Liste searchResults und erstellt für jedes Ergebnis eine ListItem.
    • Wenn auf ein ListItem geklickt wird, wird das textFieldState aktualisiert, die Suchleiste minimiert und das textField mit dem ausgewählten Suchergebnis gefüllt.

Ergebnis

Eine Suchleiste mit dem Buchstaben „a“ wird angezeigt. Unterhalb der Suchleiste wird eine Liste mit sechs Suchvorschlägen angezeigt.
Abbildung 2. Eine Suchleiste mit Vorschlägen.

Suchleiste mit gefilterter Liste

In diesem Beispiel wird eine SearchBar gezeigt, mit der eine Liste anhand der Suchanfrage des Nutzers gefiltert wird:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CustomizableSearchBar(
    query: String,
    onQueryChange: (String) -> Unit,
    onSearch: (String) -> Unit,
    searchResults: List<String>,
    onResultClick: (String) -> Unit,
    // Customization options
    placeholder: @Composable () -> Unit = { Text("Search") },
    leadingIcon: @Composable (() -> Unit)? = { Icon(Icons.Default.Search, contentDescription = "Search") },
    trailingIcon: @Composable (() -> Unit)? = null,
    supportingContent: (@Composable (String) -> Unit)? = null,
    leadingContent: (@Composable () -> Unit)? = null,
    modifier: Modifier = Modifier
) {
    // Track expanded state of search bar
    var expanded by rememberSaveable { mutableStateOf(false) }

    Box(
        modifier
            .fillMaxSize()
            .semantics { isTraversalGroup = true }
    ) {
        SearchBar(
            modifier = Modifier
                .align(Alignment.TopCenter)
                .semantics { traversalIndex = 0f },
            inputField = {
                // Customizable input field implementation
                SearchBarDefaults.InputField(
                    query = query,
                    onQueryChange = onQueryChange,
                    onSearch = {
                        onSearch(query)
                        expanded = false
                    },
                    expanded = expanded,
                    onExpandedChange = { expanded = it },
                    placeholder = placeholder,
                    leadingIcon = leadingIcon,
                    trailingIcon = trailingIcon
                )
            },
            expanded = expanded,
            onExpandedChange = { expanded = it },
        ) {
            // Show search results in a lazy column for better performance
            LazyColumn {
                items(count = searchResults.size) { index ->
                    val resultText = searchResults[index]
                    ListItem(
                        headlineContent = { Text(resultText) },
                        supportingContent = supportingContent?.let { { it(resultText) } },
                        leadingContent = leadingContent,
                        colors = ListItemDefaults.colors(containerColor = Color.Transparent),
                        modifier = Modifier
                            .clickable {
                                onResultClick(resultText)
                                expanded = false
                            }
                            .fillMaxWidth()
                            .padding(horizontal = 16.dp, vertical = 4.dp)
                    )
                }
            }
        }
    }
}

Wichtige Punkte zum Code

  • Die Lambda-Funktion onQueryChange wird aufgerufen, wenn der Nutzer Text in die Suchleiste eingibt oder löscht.
  • SearchBarDefaults.InputField enthält ein leadingIcon, das am Anfang des Eingabefelds ein Suchsymbol hinzufügt, und ein trailingIcon, das am Ende des Eingabefelds ein Symbol für weitere Optionen hinzufügt. Hier können Sie den Nutzern Sortier- und Filteroptionen zur Verfügung stellen.
  • onSearch = { … } ruft das Lambda onSearch auf und minimiert die Suchleiste, wenn die Suche gesendet wurde.
  • Ein LazyColumn verarbeitet eine potenziell große Anzahl von Suchergebnissen effizient. Dabei wird die Liste der searchResults durchlaufen und jedes Ergebnis als ListItem angezeigt.
  • Jedes ListItem-Element enthält den Artikeltext, Text mit zusätzlichen Informationen und ein Sternsymbol als leadingContent des Artikels. In diesem Beispiel wird eine Option zum Hinzufügen des Artikels zu den Favoriten angezeigt.
  • Die Filterlogik finden Sie unter CustomizableSearchBarExample im vollständigen Quellcode auf GitHub.

Ergebnis

Eine Suchleiste mit den Worten „Textsuche mit Vorschlägen“ wird angezeigt. Unterhalb der Suchleiste wird eine Liste mit Suchvorschlägen angezeigt. Neben jedem Vorschlag befindet sich ein Sternsymbol.
Abbildung 3 Eine Suchleiste mit relevanten Vorschlägen.

Weitere Informationen