Skip to content

Instantly share code, notes, and snippets.

@hardiksachan
Last active December 28, 2023 06:52
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save hardiksachan/0b63ab1e18a52d1e5a374a0df0bccb96 to your computer and use it in GitHub Desktop.
Save hardiksachan/0b63ab1e18a52d1e5a374a0df0bccb96 to your computer and use it in GitHub Desktop.
Jetpack Compose Expandable Search Bar (Top Bar)
@Composable
fun ExpandableSearchView(
searchDisplay: String,
onSearchDisplayChanged: (String) -> Unit,
onSearchDisplayClosed: () -> Unit,
modifier: Modifier = Modifier,
expandedInitially: Boolean = false,
tint: Color = MaterialTheme.colors.onPrimary
) {
val (expanded, onExpandedChanged) = remember {
mutableStateOf(expandedInitially)
}
Crossfade(targetState = expanded) { isSearchFieldVisible ->
when (isSearchFieldVisible) {
true -> ExpandedSearchView(
searchDisplay = searchDisplay,
onSearchDisplayChanged = onSearchDisplayChanged,
onSearchDisplayClosed = onSearchDisplayClosed,
onExpandedChanged = onExpandedChanged,
modifier = modifier,
tint = tint
)
false -> CollapsedSearchView(
onExpandedChanged = onExpandedChanged,
modifier = modifier,
tint = tint
)
}
}
}
@Composable
fun SearchIcon(iconTint: Color) {
Icon(
painter = painterResource(id = R.drawable.ic_search),
contentDescription = "search icon",
tint = iconTint
)
}
@Composable
fun CollapsedSearchView(
onExpandedChanged: (Boolean) -> Unit,
modifier: Modifier = Modifier,
tint: Color = MaterialTheme.colors.onPrimary,
) {
Row(
modifier = modifier
.fillMaxWidth()
.padding(vertical = 2.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "Tasks",
style = MaterialTheme.typography.h6,
modifier = Modifier
.padding(start = 16.dp)
)
IconButton(onClick = { onExpandedChanged(true) }) {
SearchIcon(iconTint = tint)
}
}
}
@Composable
fun ExpandedSearchView(
searchDisplay: String,
onSearchDisplayChanged: (String) -> Unit,
onSearchDisplayClosed: () -> Unit,
onExpandedChanged: (Boolean) -> Unit,
modifier: Modifier = Modifier,
tint: Color = MaterialTheme.colors.onPrimary,
) {
val focusManager = LocalFocusManager.current
val textFieldFocusRequester = remember { FocusRequester() }
SideEffect {
textFieldFocusRequester.requestFocus()
}
var textFieldValue by remember {
mutableStateOf(TextFieldValue(searchDisplay, TextRange(searchDisplay.length)))
}
Row(
modifier = modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically
) {
IconButton(onClick = {
onExpandedChanged(false)
onSearchDisplayClosed()
}) {
Icon(
painter = painterResource(id = R.drawable.ic_back),
contentDescription = "back icon",
tint = tint
)
}
TextField(
value = textFieldValue,
onValueChange = {
textFieldValue = it
onSearchDisplayChanged(it.text)
},
trailingIcon = {
SearchIcon(iconTint = tint)
},
modifier = Modifier
.fillMaxWidth()
.focusRequester(textFieldFocusRequester),
label = {
Text(text = "Search", color = tint)
},
keyboardOptions = KeyboardOptions(
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(
onDone = {
focusManager.clearFocus()
}
)
)
}
}
@Preview
@Composable
fun CollapsedSearchViewPreview() {
AppTheme {
Surface(
color = MaterialTheme.colors.primary
) {
ExpandableSearchView(
searchDisplay = "",
onSearchDisplayChanged = {},
onSearchDisplayClosed = {}
)
}
}
}
@Preview
@Composable
fun ExpandedSearchViewPreview() {
AppTheme {
Surface(
color = MaterialTheme.colors.primary
) {
ExpandableSearchView(
searchDisplay = "",
onSearchDisplayChanged = {},
expandedInitially = true,
onSearchDisplayClosed = {}
)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment