I'm trying to implement something that I feel should be easy but I'm having a hard time.
I have a screen with a scaffold, topbar, and lazycolumn as content:
I'm using a M3 TopAppBar with a enterAlwaysScrollBehavior so it disappears/appears when the content is scrolled.
What I want to do is implement the search button. How can I make that once the search icon is tapped, the "Cards" title turns into a textfield to input a search query?
I've done this easily using a Row and Crossfade instead of TopAppBar, but then I lose the scrollBehavior feature.
Any ideas?
Thanks, and happy new year!
Did the following:
@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun SearchAppBar() {
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
var isSearch by remember { mutableStateOf(false) }
var value by remember { mutableStateOf("") }
Crossfade(
modifier = Modifier.animateContentSize(),
targetState = isSearch,
label = "Search"
) { target ->
if (!target) {
TopAppBar(
title = { Text("Cards") },
actions = { IconButton(Icons.Filled.Search) { isSearch = !isSearch } },
scrollBehavior = scrollBehavior,
)
} else {
TextField(
modifier = Modifier
.fillMaxWidth()
.windowInsetsPadding(TopAppBarDefaults.windowInsets)
.layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
val height = placeable.height * (1 - scrollBehavior.state.collapsedFraction)
layout(placeable.width, height.roundToInt()) {
placeable.place(0, 0)
}
},
value = value,
placeholder = { Text("Enter card name") },
onValueChange = { value = it },
leadingIcon = {
IconButton(Icons.AutoMirrored.Filled.ArrowBack) {
isSearch = !isSearch
}
},
trailingIcon = if (value.isNotBlank()) {
{ IconButton(Icons.Filled.Close) { value = "" } }
} else {
null
}
)
}
}
},
) { paddingValues ->
LazyColumn(
Modifier
.fillMaxSize()
.padding(paddingValues)
) {
items(200) { index ->
Text(modifier = Modifier.fillMaxWidth(), text = "Title $index")
}
}
}
}
@Composable
fun IconButton(imageVector: ImageVector, onClick: () -> Unit) {
IconButton(onClick = onClick) {
Icon(
imageVector = imageVector,
contentDescription = null
)
}
}