Let SearchBar/SearchField use TextFieldState
This commit is contained in:
parent
87619e50e8
commit
fa1b32f0ba
48 changed files with 197 additions and 298 deletions
|
|
@ -17,6 +17,9 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.text.input.TextFieldState
|
||||
import androidx.compose.foundation.text.input.clearText
|
||||
import androidx.compose.foundation.text.input.rememberTextFieldState
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.SearchBar
|
||||
import androidx.compose.material3.SearchBarColors
|
||||
|
|
@ -25,9 +28,7 @@ import androidx.compose.material3.TextFieldDefaults
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
|
|
@ -51,8 +52,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
|||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun <T> SearchBar(
|
||||
query: String,
|
||||
onQueryChange: (String) -> Unit,
|
||||
queryState: TextFieldState,
|
||||
active: Boolean,
|
||||
onActiveChange: (Boolean) -> Unit,
|
||||
placeHolderTitle: String,
|
||||
|
|
@ -72,10 +72,9 @@ fun <T> SearchBar(
|
|||
) {
|
||||
val focusManager = LocalFocusManager.current
|
||||
val colors = if (active) activeBarColors else inactiveBarColors
|
||||
val updatedOnQueryChange by rememberUpdatedState(onQueryChange)
|
||||
LaunchedEffect(active) {
|
||||
if (!active) {
|
||||
updatedOnQueryChange("")
|
||||
queryState.clearText()
|
||||
focusManager.clearFocus()
|
||||
}
|
||||
}
|
||||
|
|
@ -83,8 +82,7 @@ fun <T> SearchBar(
|
|||
SearchBar(
|
||||
inputField = {
|
||||
SearchBarDefaults.InputField(
|
||||
query = query,
|
||||
onQueryChange = updatedOnQueryChange,
|
||||
state = queryState,
|
||||
onSearch = { focusManager.clearFocus() },
|
||||
expanded = active,
|
||||
onExpandedChange = onActiveChange,
|
||||
|
|
@ -98,9 +96,9 @@ fun <T> SearchBar(
|
|||
null
|
||||
},
|
||||
trailingIcon = when {
|
||||
active && query.isNotEmpty() -> {
|
||||
active && queryState.text.isNotEmpty() -> {
|
||||
{
|
||||
IconButton(onClick = { onQueryChange("") }) {
|
||||
IconButton(onClick = { queryState.clearText() }) {
|
||||
Icon(
|
||||
imageVector = CompoundIcons.Close(),
|
||||
contentDescription = stringResource(CommonStrings.action_clear),
|
||||
|
|
@ -221,7 +219,7 @@ internal fun SearchBarInactivePreview() = ElementThemedPreview { ContentToPrevie
|
|||
@Composable
|
||||
internal fun SearchBarActiveNoneQueryPreview() = ElementThemedPreview {
|
||||
ContentToPreview(
|
||||
query = "",
|
||||
initialQuery = "",
|
||||
active = true,
|
||||
)
|
||||
}
|
||||
|
|
@ -230,7 +228,7 @@ internal fun SearchBarActiveNoneQueryPreview() = ElementThemedPreview {
|
|||
@Composable
|
||||
internal fun SearchBarActiveWithQueryPreview() = ElementThemedPreview {
|
||||
ContentToPreview(
|
||||
query = "search term",
|
||||
initialQuery = "search term",
|
||||
active = true,
|
||||
)
|
||||
}
|
||||
|
|
@ -239,7 +237,7 @@ internal fun SearchBarActiveWithQueryPreview() = ElementThemedPreview {
|
|||
@Composable
|
||||
internal fun SearchBarActiveWithQueryNoBackButtonPreview() = ElementThemedPreview {
|
||||
ContentToPreview(
|
||||
query = "search term",
|
||||
initialQuery = "search term",
|
||||
active = true,
|
||||
showBackButton = false,
|
||||
)
|
||||
|
|
@ -249,7 +247,7 @@ internal fun SearchBarActiveWithQueryNoBackButtonPreview() = ElementThemedPrevie
|
|||
@Composable
|
||||
internal fun SearchBarActiveWithNoResultsPreview() = ElementThemedPreview {
|
||||
ContentToPreview(
|
||||
query = "search term",
|
||||
initialQuery = "search term",
|
||||
active = true,
|
||||
resultState = SearchBarResultState.NoResultsFound<String>(),
|
||||
)
|
||||
|
|
@ -259,7 +257,7 @@ internal fun SearchBarActiveWithNoResultsPreview() = ElementThemedPreview {
|
|||
@Composable
|
||||
internal fun SearchBarActiveWithContentPreview() = ElementThemedPreview {
|
||||
ContentToPreview(
|
||||
query = "search term",
|
||||
initialQuery = "search term",
|
||||
active = true,
|
||||
resultState = SearchBarResultState.Results("result!"),
|
||||
contentPrefix = {
|
||||
|
|
@ -292,7 +290,7 @@ internal fun SearchBarActiveWithContentPreview() = ElementThemedPreview {
|
|||
@Composable
|
||||
@ExcludeFromCoverage
|
||||
private fun ContentToPreview(
|
||||
query: String = "",
|
||||
initialQuery: String = "",
|
||||
active: Boolean = false,
|
||||
showBackButton: Boolean = true,
|
||||
resultState: SearchBarResultState<String> = SearchBarResultState.Initial(),
|
||||
|
|
@ -300,13 +298,13 @@ private fun ContentToPreview(
|
|||
contentSuffix: @Composable ColumnScope.() -> Unit = {},
|
||||
resultHandler: @Composable ColumnScope.(String) -> Unit = {},
|
||||
) {
|
||||
val queryState = rememberTextFieldState(initialText = initialQuery)
|
||||
SearchBar(
|
||||
modifier = Modifier.heightIn(max = 200.dp),
|
||||
query = query,
|
||||
queryState = queryState,
|
||||
active = active,
|
||||
resultState = resultState,
|
||||
showBackButton = showBackButton,
|
||||
onQueryChange = {},
|
||||
onActiveChange = {},
|
||||
placeHolderTitle = "Search for things",
|
||||
contentPrefix = contentPrefix,
|
||||
|
|
|
|||
|
|
@ -22,8 +22,10 @@ import androidx.compose.foundation.layout.width
|
|||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.text.input.TextFieldLineLimits
|
||||
import androidx.compose.foundation.text.input.TextFieldState
|
||||
import androidx.compose.foundation.text.input.clearText
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
|
|
@ -34,7 +36,6 @@ import androidx.compose.ui.platform.LocalFocusManager
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
|
|
@ -50,8 +51,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
|||
*/
|
||||
@Composable
|
||||
fun SearchField(
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
state: TextFieldState,
|
||||
modifier: Modifier = Modifier,
|
||||
placeholder: String? = null,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
|
|
@ -59,67 +59,28 @@ fun SearchField(
|
|||
val focusManager = LocalFocusManager.current
|
||||
val isFocused by interactionSource.collectIsFocusedAsState()
|
||||
BasicTextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
state = state,
|
||||
modifier = modifier,
|
||||
textStyle = textFieldStyle(),
|
||||
singleLine = true,
|
||||
lineLimits = TextFieldLineLimits.SingleLine,
|
||||
interactionSource = interactionSource,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
imeAction = ImeAction.Search,
|
||||
),
|
||||
keyboardActions = KeyboardActions(
|
||||
onSearch = {
|
||||
focusManager.clearFocus()
|
||||
}
|
||||
),
|
||||
onKeyboardAction = {
|
||||
focusManager.clearFocus()
|
||||
},
|
||||
cursorBrush = SolidColor(ElementTheme.colors.textActionAccent),
|
||||
) { innerTextField ->
|
||||
DecorationBox(
|
||||
isFocused = isFocused,
|
||||
placeholder = placeholder,
|
||||
isTextEmpty = value.isEmpty(),
|
||||
innerTextField = innerTextField,
|
||||
onClear = { onValueChange("") },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SearchField(
|
||||
value: TextFieldValue,
|
||||
onValueChange: (TextFieldValue) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
placeholder: String? = null,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
) {
|
||||
val focusManager = LocalFocusManager.current
|
||||
val isFocused by interactionSource.collectIsFocusedAsState()
|
||||
BasicTextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
textStyle = textFieldStyle(),
|
||||
singleLine = true,
|
||||
interactionSource = interactionSource,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
imeAction = ImeAction.Search,
|
||||
),
|
||||
keyboardActions = KeyboardActions(
|
||||
onSearch = {
|
||||
focusManager.clearFocus()
|
||||
}
|
||||
),
|
||||
cursorBrush = SolidColor(ElementTheme.colors.textActionAccent),
|
||||
) { innerTextField ->
|
||||
DecorationBox(
|
||||
isFocused = isFocused,
|
||||
placeholder = placeholder,
|
||||
isTextEmpty = value.text.isEmpty(),
|
||||
innerTextField = innerTextField,
|
||||
onClear = { TextFieldValue() }
|
||||
)
|
||||
}
|
||||
decorator = { innerTextField ->
|
||||
DecorationBox(
|
||||
isFocused = isFocused,
|
||||
placeholder = placeholder,
|
||||
isTextEmpty = state.text.isEmpty(),
|
||||
innerTextField = innerTextField,
|
||||
onClear = { state.clearText() },
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -211,14 +172,12 @@ private fun ContentToPreview() {
|
|||
verticalArrangement = spacedBy(8.dp)
|
||||
) {
|
||||
SearchField(
|
||||
onValueChange = {},
|
||||
placeholder = "Search",
|
||||
value = "",
|
||||
state = TextFieldState(""),
|
||||
)
|
||||
SearchField(
|
||||
onValueChange = {},
|
||||
placeholder = "Search",
|
||||
value = "Search term",
|
||||
state = TextFieldState("Search term"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue