NullPointerException
NullPointerException

Reputation: 37721

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

Upvotes: -1

Views: 66

Answers (1)

BenjyTec
BenjyTec

Reputation: 10887

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

Upvotes: 2

Related Questions