compose: search: fix searchbar & IME issue
This commit is contained in:
@@ -7,6 +7,8 @@ package com.aurora.store.compose.ui.search
|
|||||||
|
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.foundation.focusable
|
import androidx.compose.foundation.focusable
|
||||||
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
|
import androidx.compose.foundation.interaction.PressInteraction
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
@@ -46,6 +48,8 @@ import androidx.compose.runtime.snapshotFlow
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
import androidx.compose.ui.focus.focusRequester
|
import androidx.compose.ui.focus.focusRequester
|
||||||
|
import androidx.compose.ui.platform.LocalFocusManager
|
||||||
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||||
import androidx.compose.ui.res.dimensionResource
|
import androidx.compose.ui.res.dimensionResource
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringArrayResource
|
import androidx.compose.ui.res.stringArrayResource
|
||||||
@@ -73,23 +77,27 @@ import com.aurora.store.compose.preview.PreviewTemplate
|
|||||||
import com.aurora.store.compose.ui.details.AppDetailsScreen
|
import com.aurora.store.compose.ui.details.AppDetailsScreen
|
||||||
import com.aurora.store.data.model.SearchFilter
|
import com.aurora.store.data.model.SearchFilter
|
||||||
import com.aurora.store.viewmodel.search.SearchViewModel
|
import com.aurora.store.viewmodel.search.SearchViewModel
|
||||||
import kotlin.random.Random
|
|
||||||
import kotlinx.coroutines.android.awaitFrame
|
import kotlinx.coroutines.android.awaitFrame
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SearchScreen(onNavigateUp: () -> Unit, viewModel: SearchViewModel = hiltViewModel()) {
|
fun SearchScreen(onNavigateUp: () -> Unit, viewModel: SearchViewModel = hiltViewModel()) {
|
||||||
val suggestions by viewModel.suggestions.collectAsStateWithLifecycle()
|
val suggestions by viewModel.suggestions.collectAsStateWithLifecycle()
|
||||||
val results = viewModel.apps.collectAsLazyPagingItems()
|
val results = viewModel.apps.collectAsLazyPagingItems()
|
||||||
|
|
||||||
|
val onSearchCallback = remember<(String) -> Unit> { { query -> viewModel.search(query) } }
|
||||||
|
val onFetchSuggestionsCallback =
|
||||||
|
remember<(String) -> Unit> { { query -> viewModel.fetchSuggestions(query) } }
|
||||||
|
|
||||||
ScreenContent(
|
ScreenContent(
|
||||||
suggestions = suggestions,
|
suggestions = suggestions,
|
||||||
results = results,
|
results = results,
|
||||||
onNavigateUp = onNavigateUp,
|
onNavigateUp = onNavigateUp,
|
||||||
onSearch = { query -> viewModel.search(query) },
|
onSearch = onSearchCallback,
|
||||||
onFetchSuggestions = { query -> viewModel.fetchSuggestions(query) },
|
onFetchSuggestions = onFetchSuggestionsCallback,
|
||||||
onFilter = { filter -> viewModel.filterResults(filter) },
|
onFilter = { filter -> viewModel.filterResults(filter) },
|
||||||
isAnonymous = viewModel.authProvider.isAnonymous
|
isAnonymous = viewModel.authProvider.isAnonymous
|
||||||
)
|
)
|
||||||
@@ -113,6 +121,9 @@ private fun ScreenContent(
|
|||||||
val scaffoldNavigator = rememberListDetailPaneScaffoldNavigator<String>()
|
val scaffoldNavigator = rememberListDetailPaneScaffoldNavigator<String>()
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
val focusManager = LocalFocusManager.current
|
||||||
|
val keyboardController = LocalSoftwareKeyboardController.current
|
||||||
|
|
||||||
LaunchedEffect(key1 = focusRequester) {
|
LaunchedEffect(key1 = focusRequester) {
|
||||||
awaitFrame()
|
awaitFrame()
|
||||||
focusRequester.requestFocus()
|
focusRequester.requestFocus()
|
||||||
@@ -131,18 +142,34 @@ private fun ScreenContent(
|
|||||||
|
|
||||||
fun onRequestSearch(query: String) {
|
fun onRequestSearch(query: String) {
|
||||||
textFieldState.setTextAndPlaceCursorAtEnd(query.trim())
|
textFieldState.setTextAndPlaceCursorAtEnd(query.trim())
|
||||||
coroutineScope.launch { searchBarState.animateToCollapsed() }
|
coroutineScope.launch {
|
||||||
|
focusManager.clearFocus()
|
||||||
|
keyboardController?.hide()
|
||||||
|
searchBarState.animateToCollapsed()
|
||||||
|
}
|
||||||
onSearch(textFieldState.text.toString())
|
onSearch(textFieldState.text.toString())
|
||||||
isSearching = true
|
isSearching = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SearchBar() {
|
fun SearchBar() {
|
||||||
|
val interactionSource = remember { MutableInteractionSource() }
|
||||||
|
|
||||||
|
LaunchedEffect(interactionSource) {
|
||||||
|
interactionSource.interactions.collectLatest { interaction ->
|
||||||
|
if (interaction is PressInteraction.Press) {
|
||||||
|
awaitFrame()
|
||||||
|
focusRequester.requestFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val inputField = @Composable {
|
val inputField = @Composable {
|
||||||
SearchBarDefaults.InputField(
|
SearchBarDefaults.InputField(
|
||||||
modifier = Modifier.focusRequester(focusRequester),
|
modifier = Modifier.focusRequester(focusRequester),
|
||||||
searchBarState = searchBarState,
|
searchBarState = searchBarState,
|
||||||
textFieldState = textFieldState,
|
textFieldState = textFieldState,
|
||||||
|
interactionSource = interactionSource,
|
||||||
onSearch = { query -> onRequestSearch(query) },
|
onSearch = { query -> onRequestSearch(query) },
|
||||||
placeholder = {
|
placeholder = {
|
||||||
Text(
|
Text(
|
||||||
|
|||||||
Reference in New Issue
Block a user