androidkotlinandroid-jetpack-composesearchbar

How to use compose SearchBar?


How can I update SearchBar results with every key pressed on the keyboard? there is no value and valuechanged variables on it. Here is the documentation.

This is the sample:

@Composable
fun DockedSearchBarScaffold() {
    val textFieldState = rememberTextFieldState()
    val searchBarState = rememberSearchBarState()
    val scope = rememberCoroutineScope()
    val scrollBehavior = SearchBarDefaults.enterAlwaysSearchBarScrollBehavior()

    val inputField =
    @Composable {
        SearchBarDefaults.InputField(
            modifier = Modifier,
            searchBarState = searchBarState,
            textFieldState = textFieldState,
            onSearch = {
                scope.launch {
                    searchBarState.animateToCollapsed()
                }
            },
            placeholder = { Text("Search...") },
            leadingIcon = {
                if (searchBarState.currentValue == SearchBarValue.Expanded) {
                    IconButton(
                        onClick = { scope.launch { searchBarState.animateToCollapsed() } }
                    ) {
                        Icon(Icons.AutoMirrored.Default.ArrowBack, contentDescription = "Back")
                    }
                } else {
                    Icon(Icons.Default.Search, contentDescription = null)
                }
            }
        )
    }

    TopSearchBar(
        scrollBehavior = scrollBehavior,
        state = searchBarState,
        inputField = inputField,
    )
    ExpandedDockedSearchBar(
        state = searchBarState,
        inputField = inputField,
    ) {
        SearchResults(
            busStops = emptyList(),
            onResultClick = { result ->
                textFieldState.setTextAndPlaceCursorAtEnd(result)
                scope.launch { searchBarState.animateToCollapsed() }
            }
        )
    }
}

Solution

  • You don't need to do anything in order to update the SearchResults Composable on each key press. The only thing missing in your code is actual data and a filter operation using the textFieldState.text.

    When you enter a character into the SearchBarDefaults.InputField, it will be recomposed. As you are passing the inputField to the ExpandedDockedSearchBar, it will automatically recompose too and the filter expression will be re-evaluated.

    Please have a look at the following code:

    @OptIn(ExperimentalMaterial3Api::class)
    @Composable
    fun SearchBarDemo() {
    
        val animalList = listOf("Dog", "Cat", "Deer", "Cheetah", "Dolphin", "Cougar", "Donkey")
    
        val textFieldState = rememberTextFieldState()
        val searchBarState = rememberSearchBarState()
        val scope = rememberCoroutineScope()
        val scrollBehavior = SearchBarDefaults.enterAlwaysSearchBarScrollBehavior()
    
        val inputField =
            @Composable {
                SearchBarDefaults.InputField(
                    modifier = Modifier,
                    searchBarState = searchBarState,
                    textFieldState = textFieldState,
                    onSearch = { scope.launch { searchBarState.animateToCollapsed() } },
                    placeholder = { Text("Search...") },
                    leadingIcon = {
                        if (searchBarState.currentValue == SearchBarValue.Expanded) {
                            IconButton(
                                onClick = { scope.launch { searchBarState.animateToCollapsed() } }
                            ) {
                                Icon(Icons.AutoMirrored.Default.ArrowBack, contentDescription = "Back")
                            }
                        } else {
                            Icon(Icons.Default.Search, contentDescription = null)
                        }
                    },
                    trailingIcon = { Icon(Icons.Default.MoreVert, contentDescription = null) },
                )
            }
    
        Scaffold(
            modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
            topBar = {
                TopSearchBar(
                    scrollBehavior = scrollBehavior,
                    state = searchBarState,
                    inputField = inputField,
                )
                ExpandedDockedSearchBar(
                    state = searchBarState,
                    inputField = inputField,
                ) {
                    LazyColumn {
                        items(animalList.filter { it.startsWith(textFieldState.text.toString(), ignoreCase = true) }) {
                            Text(modifier = Modifier.padding(vertical = 8.dp, horizontal = 16.dp), text = it)
                        }
                    }
                }
            }
        ) { padding ->
            // LazyColumn to show search results
        }
    }
    

    Output:

    Screen Recording