feat(app): replace top app bar with search bar

This commit is contained in:
Anthony 2024-06-11 14:20:38 +02:00
parent 9f7e1c1a61
commit ab932f5293
2 changed files with 57 additions and 99 deletions

View File

@ -1,51 +0,0 @@
package component
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.ui.text.style.TextOverflow
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TopBar(
scrollBehavior: TopAppBarScrollBehavior,
searchActive: MutableState<Boolean>
) {
CenterAlignedTopAppBar(
title = {
Text(
text = "Vegan E Numbers",
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
},
navigationIcon = {
IconButton(
onClick = {/* TODO Implement Navigation Drawer */}
) {
Icon(
imageVector = Icons.Filled.Menu,
contentDescription = "Navigation Menu",
)
}
},
actions = {
IconButton(
onClick = {
println("Clicked on Search")
searchActive.value = true
}
) {
Icon(
imageVector = Icons.Filled.Search,
contentDescription = "Search for E Number",
)
}
},
scrollBehavior = scrollBehavior,
)
}

View File

@ -1,9 +1,7 @@
package tab.list package tab.list
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
@ -12,9 +10,11 @@ import androidx.compose.material.icons.filled.*
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.semantics.isTraversalGroup
import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.traversalIndex import androidx.compose.ui.semantics.traversalIndex
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -23,7 +23,6 @@ import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
import cafe.adriel.voyager.navigator.tab.Tab import cafe.adriel.voyager.navigator.tab.Tab
import cafe.adriel.voyager.navigator.tab.TabOptions import cafe.adriel.voyager.navigator.tab.TabOptions
import component.TopBar
import tab.LoadingScreen import tab.LoadingScreen
object ListMain : Tab { object ListMain : Tab {
@ -47,19 +46,11 @@ object ListMain : Tab {
val screenModel = navigator.rememberNavigatorScreenModel { ListScreenModel() } val screenModel = navigator.rememberNavigatorScreenModel { ListScreenModel() }
val state by screenModel.state.collectAsState() val state by screenModel.state.collectAsState()
val searchActive = rememberSaveable { mutableStateOf(false) }
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
Scaffold( Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = { topBar = { Search() }
if (!searchActive.value) {
TopBar(scrollBehavior = scrollBehavior, searchActive = searchActive)
} else {
Search(searchActive = searchActive)
}
}
) { innerPadding -> ) { innerPadding ->
Column( Column(
modifier = Modifier.padding(innerPadding) modifier = Modifier.padding(innerPadding)
@ -78,44 +69,62 @@ object ListMain : Tab {
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun Search(searchActive: MutableState<Boolean>) { private fun Search() {
var text by rememberSaveable { mutableStateOf("") } var text by rememberSaveable { mutableStateOf("") }
var expanded by rememberSaveable { mutableStateOf(false) }
SearchBar( Column (
modifier = Modifier Modifier
.semantics { traversalIndex = 0f }, .fillMaxWidth()
query = text, .padding(if (!expanded) 8.dp else 0.dp)
onQueryChange = { text = it }, .semantics { isTraversalGroup = true }
onSearch = { searchActive.value = false },
onActiveChange = { searchActive.value = it },
active = searchActive.value,
leadingIcon = {
IconButton(onClick = { searchActive.value = false }) {
Icon(Icons.AutoMirrored.Filled.ArrowBack, "Exit Search")
}
},
trailingIcon = {
IconButton(onClick = { text = "" }) {
Icon(imageVector = Icons.Filled.Clear, contentDescription = "Clear Search")
}
}
) { ) {
Column(Modifier.verticalScroll(rememberScrollState())) { SearchBar(
repeat(4) { idx -> modifier = Modifier
val resultText = "Suggestion $idx" .align(Alignment.CenterHorizontally)
ListItem( .semantics { traversalIndex = 0f },
headlineContent = { Text(resultText) }, query = text,
supportingContent = { Text("Additional info") }, onQueryChange = { text = it },
leadingContent = { Icon(Icons.Filled.Star, contentDescription = null) }, onSearch = { expanded = false },
colors = ListItemDefaults.colors(containerColor = Color.Transparent), onActiveChange = { expanded = it },
modifier = Modifier active = expanded,
.clickable { placeholder = {Text("Search E Numbers")},
text = resultText leadingIcon = {
searchActive.value = false if (expanded) {
} IconButton(onClick = { expanded = false }) {
.fillMaxWidth() Icon(Icons.AutoMirrored.Filled.ArrowBack, "Exit Search")
.padding(horizontal = 16.dp, vertical = 4.dp) }
) } else {
IconButton(onClick = { /* TODO Add menu */ }) {
Icon(Icons.Filled.Menu, "Navigation Menu")
}
}
},
trailingIcon = {
if (text.isNotBlank()) {
IconButton(onClick = { text = "" }) {
Icon(imageVector = Icons.Filled.Clear, contentDescription = "Clear Search")
}
}
}
) {
Column(Modifier.verticalScroll(rememberScrollState())) {
repeat(4) { idx ->
val resultText = "Suggestion $idx"
ListItem(
headlineContent = { Text(resultText) },
supportingContent = { Text("Additional info") },
leadingContent = { Icon(Icons.Filled.Star, contentDescription = null) },
colors = ListItemDefaults.colors(containerColor = Color.Transparent),
modifier = Modifier
.clickable {
text = resultText
expanded = false
}
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 4.dp)
)
}
} }
} }
} }