mirror of
https://github.com/Myzel394/NumberHub.git
synced 2025-06-19 08:45:27 +02:00
Collapsable top bar for SecondScreen.kt
This commit is contained in:
parent
90780d66ef
commit
a37babb63d
@ -1,15 +1,17 @@
|
|||||||
package com.sadellie.unitto.screens.second
|
package com.sadellie.unitto.screens.second
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalFocusManager
|
import androidx.compose.ui.platform.LocalFocusManager
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import com.sadellie.unitto.R
|
import com.sadellie.unitto.R
|
||||||
import com.sadellie.unitto.data.units.ALL_UNIT_GROUPS
|
import com.sadellie.unitto.data.units.ALL_UNIT_GROUPS
|
||||||
@ -38,12 +40,15 @@ fun SecondScreen(
|
|||||||
val chipsRowLazyListState = rememberLazyListState()
|
val chipsRowLazyListState = rememberLazyListState()
|
||||||
val currentUnit = if (leftSide) viewModel.unitFrom else viewModel.unitTo
|
val currentUnit = if (leftSide) viewModel.unitFrom else viewModel.unitTo
|
||||||
var chosenUnitGroup: UnitGroup? by rememberSaveable { mutableStateOf(currentUnit.group) }
|
var chosenUnitGroup: UnitGroup? by rememberSaveable { mutableStateOf(currentUnit.group) }
|
||||||
|
val scrollBehavior: TopAppBarScrollBehavior = remember {
|
||||||
|
TopAppBarDefaults.enterAlwaysScrollBehavior()
|
||||||
|
}
|
||||||
|
|
||||||
Column {
|
Scaffold(
|
||||||
SearchBar(
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
.padding(8.dp),
|
topBar = {
|
||||||
|
SearchBar(
|
||||||
title = stringResource(id = if (leftSide) R.string.units_screen_from else R.string.units_screen_to),
|
title = stringResource(id = if (leftSide) R.string.units_screen_from else R.string.units_screen_to),
|
||||||
value = searchQuery,
|
value = searchQuery,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
@ -56,9 +61,12 @@ fun SecondScreen(
|
|||||||
viewModel.loadUnitsToShow(searchQuery, chosenUnitGroup, leftSide)
|
viewModel.loadUnitsToShow(searchQuery, chosenUnitGroup, leftSide)
|
||||||
},
|
},
|
||||||
navigateUpAction = navigateUp,
|
navigateUpAction = navigateUp,
|
||||||
focusManager = focusManager
|
focusManager = focusManager,
|
||||||
|
scrollBehavior = scrollBehavior
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
) { paddingValues ->
|
||||||
|
Column(modifier = Modifier.padding(paddingValues)) {
|
||||||
if (leftSide) {
|
if (leftSide) {
|
||||||
ChipsRow(
|
ChipsRow(
|
||||||
lazyListState = chipsRowLazyListState,
|
lazyListState = chipsRowLazyListState,
|
||||||
@ -86,6 +94,7 @@ fun SecondScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This block is called only once on initial composition
|
// This block is called only once on initial composition
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
|
@ -8,15 +8,12 @@ import androidx.compose.foundation.text.BasicTextField
|
|||||||
import androidx.compose.foundation.text.KeyboardActions
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
|
||||||
import androidx.compose.material.icons.filled.Favorite
|
import androidx.compose.material.icons.filled.Favorite
|
||||||
import androidx.compose.material.icons.filled.FavoriteBorder
|
import androidx.compose.material.icons.filled.FavoriteBorder
|
||||||
import androidx.compose.material.icons.filled.Search
|
import androidx.compose.material.icons.filled.Search
|
||||||
|
import androidx.compose.material.icons.outlined.ArrowBack
|
||||||
import androidx.compose.material.icons.outlined.Clear
|
import androidx.compose.material.icons.outlined.Clear
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
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.Alignment
|
||||||
@ -33,7 +30,6 @@ import com.sadellie.unitto.R
|
|||||||
/**
|
/**
|
||||||
* Search bar on the Second screen. Controls what will be shown in the list above this component
|
* Search bar on the Second screen. Controls what will be shown in the list above this component
|
||||||
*
|
*
|
||||||
* @param modifier Modifier to be applied to the Row that contains search bar elements
|
|
||||||
* @param title Search bar title
|
* @param title Search bar title
|
||||||
* @param value Current query
|
* @param value Current query
|
||||||
* @param onValueChange Action to perform when search query changes
|
* @param onValueChange Action to perform when search query changes
|
||||||
@ -41,35 +37,43 @@ import com.sadellie.unitto.R
|
|||||||
* @param favoriteAction Function to toggle favorite filter
|
* @param favoriteAction Function to toggle favorite filter
|
||||||
* @param navigateUpAction Function to navigate to previous screen
|
* @param navigateUpAction Function to navigate to previous screen
|
||||||
* @param focusManager Used to hide keyboard when leaving unit selection screen
|
* @param focusManager Used to hide keyboard when leaving unit selection screen
|
||||||
|
* @param scrollBehavior [TopAppBarScrollBehavior] that is used for collapsing and container color
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun SearchBar(
|
fun SearchBar(
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
title: String = String(),
|
title: String = String(),
|
||||||
value: String = String(),
|
value: String = String(),
|
||||||
onValueChange: (String) -> Unit = {},
|
onValueChange: (String) -> Unit = {},
|
||||||
favoritesOnly: Boolean,
|
favoritesOnly: Boolean,
|
||||||
favoriteAction: () -> Unit,
|
favoriteAction: () -> Unit,
|
||||||
navigateUpAction: () -> Unit = {},
|
navigateUpAction: () -> Unit = {},
|
||||||
focusManager: FocusManager
|
focusManager: FocusManager,
|
||||||
|
scrollBehavior: TopAppBarScrollBehavior
|
||||||
) {
|
) {
|
||||||
var showSearch by rememberSaveable { mutableStateOf(false) }
|
var showSearch by rememberSaveable { mutableStateOf(false) }
|
||||||
val focusRequester = remember { FocusRequester() }
|
val focusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
|
fun stagedNavigateUp() {
|
||||||
|
if (showSearch) {
|
||||||
|
// Search text field is open, need to close it and clear search query
|
||||||
|
onValueChange("")
|
||||||
|
focusManager.clearFocus()
|
||||||
|
showSearch = false
|
||||||
|
} else {
|
||||||
|
// No search text field is shown, can go back as usual
|
||||||
|
navigateUpAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallTopAppBar(
|
||||||
|
title = {
|
||||||
Crossfade(targetState = showSearch) { textFieldShown ->
|
Crossfade(targetState = showSearch) { textFieldShown ->
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier,
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
when (textFieldShown) {
|
when (textFieldShown) {
|
||||||
// No search text field
|
// No search text field
|
||||||
false -> {
|
false -> {
|
||||||
IconButton(onClick = navigateUpAction) {
|
|
||||||
Icon(
|
|
||||||
Icons.Default.ArrowBack,
|
|
||||||
contentDescription = stringResource(id = R.string.navigate_up_description)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@ -77,43 +81,9 @@ fun SearchBar(
|
|||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.titleLarge
|
style = MaterialTheme.typography.titleLarge
|
||||||
)
|
)
|
||||||
// Search button
|
|
||||||
IconButton(onClick = { onValueChange(""); showSearch = true }) {
|
|
||||||
Icon(
|
|
||||||
Icons.Default.Search,
|
|
||||||
contentDescription = stringResource(id = R.string.search_button_description)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
// Favorites button
|
|
||||||
IconButton(onClick = favoriteAction) {
|
|
||||||
AnimatedContent(
|
|
||||||
targetState = favoritesOnly,
|
|
||||||
transitionSpec = {
|
|
||||||
(scaleIn() with scaleOut()).using(SizeTransform(clip = false))
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
if (favoritesOnly) Icons.Filled.Favorite else Icons.Filled.FavoriteBorder,
|
|
||||||
contentDescription = stringResource(id = R.string.favorite_button_description)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// With text field
|
// With text field
|
||||||
true -> {
|
true -> {
|
||||||
IconButton(
|
|
||||||
onClick = {
|
|
||||||
// Resetting query
|
|
||||||
onValueChange("")
|
|
||||||
focusManager.clearFocus()
|
|
||||||
showSearch = false
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
Icons.Default.ArrowBack,
|
|
||||||
contentDescription = stringResource(id = R.string.navigate_up_description)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
BasicTextField(
|
BasicTextField(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@ -149,31 +119,67 @@ fun SearchBar(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
// Clear button
|
|
||||||
IconButton(
|
|
||||||
modifier = Modifier.alpha(if (value != String()) 1f else 0f),
|
|
||||||
onClick = { onValueChange("") }
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
Icons.Outlined.Clear,
|
|
||||||
contentDescription = stringResource(id = R.string.clear_input_description)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
focusRequester.requestFocus()
|
focusRequester.requestFocus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BackHandler {
|
}
|
||||||
if (textFieldShown) {
|
},
|
||||||
// Search text field is open, need to close it and clear search query
|
actions = {
|
||||||
onValueChange("")
|
Crossfade(targetState = showSearch) {
|
||||||
showSearch = false
|
Row(
|
||||||
} else {
|
verticalAlignment = Alignment.CenterVertically
|
||||||
// No MyTextField shown, can go back as usual
|
) {
|
||||||
navigateUpAction()
|
when (it) {
|
||||||
|
false -> {
|
||||||
|
// Search button
|
||||||
|
IconButton(onClick = { onValueChange(""); showSearch = true }) {
|
||||||
|
Icon(
|
||||||
|
Icons.Default.Search,
|
||||||
|
contentDescription = stringResource(id = R.string.search_button_description)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// Favorites button
|
||||||
|
IconButton(onClick = favoriteAction) {
|
||||||
|
AnimatedContent(
|
||||||
|
targetState = favoritesOnly,
|
||||||
|
transitionSpec = {
|
||||||
|
(scaleIn() with scaleOut()).using(SizeTransform(clip = false))
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
if (favoritesOnly) Icons.Filled.Favorite else Icons.Filled.FavoriteBorder,
|
||||||
|
contentDescription = stringResource(id = R.string.favorite_button_description)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true -> {
|
||||||
|
// Clear button
|
||||||
|
IconButton(onClick = { onValueChange("") }) {
|
||||||
|
Icon(
|
||||||
|
modifier = Modifier.alpha(if (value.isBlank()) 0f else 1f),
|
||||||
|
imageVector = Icons.Outlined.Clear,
|
||||||
|
contentDescription = stringResource(id = R.string.clear_input_description)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
navigationIcon = {
|
||||||
|
IconButton(onClick = { stagedNavigateUp() }) {
|
||||||
|
Icon(
|
||||||
|
Icons.Outlined.ArrowBack,
|
||||||
|
contentDescription = stringResource(id = R.string.navigate_up_description)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scrollBehavior = scrollBehavior
|
||||||
|
)
|
||||||
|
|
||||||
|
BackHandler { stagedNavigateUp() }
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user