mirror of
https://github.com/Myzel394/NumberHub.git
synced 2025-06-19 08:45:27 +02:00
Refactor chips
This commit is contained in:
parent
533c94db6b
commit
58359a2a2d
@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* Unitto is a unit converter for Android
|
||||||
|
* Copyright (c) 2023 Elshan Agaev
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sadellie.unitto.core.ui.common
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.border
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Check
|
||||||
|
import androidx.compose.material.icons.filled.Settings
|
||||||
|
import androidx.compose.material3.AssistChipDefaults
|
||||||
|
import androidx.compose.material3.FilterChipDefaults
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun FilterChip(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
selected: Boolean,
|
||||||
|
onClick: () -> Unit,
|
||||||
|
label: String,
|
||||||
|
imageVector: ImageVector,
|
||||||
|
contentDescription: String,
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = modifier
|
||||||
|
.background(
|
||||||
|
color = if (selected) MaterialTheme.colorScheme.primaryContainer else MaterialTheme.colorScheme.surface,
|
||||||
|
shape = FilterChipDefaults.shape
|
||||||
|
)
|
||||||
|
.border(
|
||||||
|
width = 1.dp,
|
||||||
|
color = if (selected) Color.Transparent else MaterialTheme.colorScheme.outline,
|
||||||
|
shape = FilterChipDefaults.shape
|
||||||
|
)
|
||||||
|
.height(FilterChipDefaults.Height)
|
||||||
|
.clickable { onClick() }
|
||||||
|
.padding(start = 8.dp, end = 16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
AnimatedVisibility(visible = selected) {
|
||||||
|
Icon(
|
||||||
|
modifier = Modifier.height(FilterChipDefaults.IconSize),
|
||||||
|
imageVector = imageVector,
|
||||||
|
contentDescription = contentDescription,
|
||||||
|
tint = MaterialTheme.colorScheme.onPrimaryContainer
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.padding(start = 8.dp),
|
||||||
|
text = label,
|
||||||
|
style = MaterialTheme.typography.labelLarge,
|
||||||
|
color = if (selected) MaterialTheme.colorScheme.onPrimaryContainer else MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AssistChip(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
onClick: () -> Unit,
|
||||||
|
imageVector: ImageVector,
|
||||||
|
contentDescription: String,
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = modifier
|
||||||
|
.background(
|
||||||
|
color = MaterialTheme.colorScheme.surface,
|
||||||
|
shape = AssistChipDefaults.shape
|
||||||
|
)
|
||||||
|
.border(
|
||||||
|
width = 1.dp,
|
||||||
|
color = MaterialTheme.colorScheme.outline,
|
||||||
|
shape = AssistChipDefaults.shape
|
||||||
|
)
|
||||||
|
.height(32.dp)
|
||||||
|
.clickable { onClick() }
|
||||||
|
.padding(horizontal = 8.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
modifier = Modifier.height(AssistChipDefaults.IconSize),
|
||||||
|
imageVector = imageVector,
|
||||||
|
contentDescription = contentDescription,
|
||||||
|
tint = MaterialTheme.colorScheme.onPrimaryContainer
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
fun PreviewAssistChip() {
|
||||||
|
AssistChip(
|
||||||
|
onClick = {},
|
||||||
|
imageVector = Icons.Default.Settings,
|
||||||
|
contentDescription = ""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
fun PreviewFilterChip() {
|
||||||
|
var isSelected by remember { mutableStateOf(true) }
|
||||||
|
|
||||||
|
FilterChip(
|
||||||
|
selected = isSelected,
|
||||||
|
onClick = { isSelected = !isSelected },
|
||||||
|
label = "Label",
|
||||||
|
imageVector = Icons.Default.Check,
|
||||||
|
contentDescription = ""
|
||||||
|
)
|
||||||
|
}
|
@ -18,23 +18,17 @@
|
|||||||
|
|
||||||
package com.sadellie.unitto.feature.converter.components
|
package com.sadellie.unitto.feature.converter.components
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
|
||||||
import androidx.compose.animation.core.animateDp
|
import androidx.compose.animation.core.animateDp
|
||||||
import androidx.compose.animation.core.animateFloat
|
import androidx.compose.animation.core.animateFloat
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.animation.core.updateTransition
|
import androidx.compose.animation.core.updateTransition
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.border
|
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||||
import androidx.compose.foundation.layout.FlowRow
|
import androidx.compose.foundation.layout.FlowRow
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.RowScope
|
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.heightIn
|
import androidx.compose.foundation.layout.heightIn
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
@ -43,7 +37,6 @@ import androidx.compose.foundation.lazy.LazyRow
|
|||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Check
|
import androidx.compose.material.icons.filled.Check
|
||||||
@ -51,23 +44,20 @@ import androidx.compose.material.icons.filled.ExpandMore
|
|||||||
import androidx.compose.material.icons.filled.Settings
|
import androidx.compose.material.icons.filled.Settings
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
|
||||||
import androidx.compose.ui.draw.clipToBounds
|
import androidx.compose.ui.draw.clipToBounds
|
||||||
import androidx.compose.ui.draw.rotate
|
import androidx.compose.ui.draw.rotate
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
|
import com.sadellie.unitto.core.ui.common.AssistChip
|
||||||
|
import com.sadellie.unitto.core.ui.common.FilterChip
|
||||||
import com.sadellie.unitto.data.model.ALL_UNIT_GROUPS
|
import com.sadellie.unitto.data.model.ALL_UNIT_GROUPS
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.UnitGroup
|
||||||
|
|
||||||
@ -97,27 +87,15 @@ internal fun ChipsRow(
|
|||||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
items(items, key = { it.name }) { item ->
|
items(items, key = { it.name }) { item ->
|
||||||
val isSelected: Boolean = item == chosenUnitGroup
|
val selected: Boolean = item == chosenUnitGroup
|
||||||
UnittoFilterChip(
|
FilterChip(
|
||||||
isSelected = isSelected,
|
selected = selected,
|
||||||
selectAction = { selectAction(if (item == chosenUnitGroup) null else item) }
|
onClick = { selectAction(if (selected) null else item) },
|
||||||
) {
|
label = stringResource(item.res),
|
||||||
AnimatedVisibility(visible = isSelected) {
|
|
||||||
Icon(
|
|
||||||
modifier = Modifier.height(18.dp),
|
|
||||||
imageVector = Icons.Default.Check,
|
imageVector = Icons.Default.Check,
|
||||||
contentDescription = stringResource(R.string.checked_filter_description),
|
contentDescription = stringResource(R.string.checked_filter_description)
|
||||||
tint = MaterialTheme.colorScheme.onPrimaryContainer
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text(
|
|
||||||
modifier = Modifier.padding(start = 8.dp),
|
|
||||||
text = stringResource(item.res),
|
|
||||||
style = MaterialTheme.typography.labelLarge,
|
|
||||||
color = if (isSelected) MaterialTheme.colorScheme.onPrimaryContainer else MaterialTheme.colorScheme.onSurfaceVariant
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Usually this chip is placed at the start, but since we scroll to currently selected
|
* Usually this chip is placed at the start, but since we scroll to currently selected
|
||||||
@ -125,19 +103,13 @@ internal fun ChipsRow(
|
|||||||
* scrolling right (to the last one).
|
* scrolling right (to the last one).
|
||||||
*/
|
*/
|
||||||
item("settings") {
|
item("settings") {
|
||||||
UnittoFilterChip(
|
AssistChip(
|
||||||
isSelected = false,
|
onClick = navigateToSettingsAction,
|
||||||
selectAction = navigateToSettingsAction,
|
|
||||||
paddingValues = PaddingValues(horizontal = 8.dp)
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
modifier = Modifier.height(18.dp),
|
|
||||||
imageVector = Icons.Default.Settings,
|
imageVector = Icons.Default.Settings,
|
||||||
contentDescription = stringResource(R.string.open_settings_description)
|
contentDescription = stringResource(R.string.open_settings_description)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalLayoutApi::class)
|
@OptIn(ExperimentalLayoutApi::class)
|
||||||
@ -175,39 +147,21 @@ fun ChipsFlexRow(
|
|||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
items.forEach { item ->
|
items.forEach { item ->
|
||||||
val isSelected: Boolean = item == chosenUnitGroup
|
val selected: Boolean = item == chosenUnitGroup
|
||||||
UnittoFilterChip(
|
FilterChip(
|
||||||
isSelected = isSelected,
|
selected = selected,
|
||||||
selectAction = { selectAction(if (item == chosenUnitGroup) null else item) }
|
onClick = { selectAction(if (selected) null else item) },
|
||||||
) {
|
label = stringResource(item.res),
|
||||||
AnimatedVisibility(visible = isSelected) {
|
|
||||||
Icon(
|
|
||||||
modifier = Modifier.height(18.dp),
|
|
||||||
imageVector = Icons.Default.Check,
|
imageVector = Icons.Default.Check,
|
||||||
contentDescription = stringResource(R.string.checked_filter_description),
|
contentDescription = stringResource(R.string.checked_filter_description)
|
||||||
tint = MaterialTheme.colorScheme.onPrimaryContainer
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text(
|
AssistChip(
|
||||||
modifier = Modifier.padding(start = 8.dp),
|
onClick = navigateToSettingsAction,
|
||||||
text = stringResource(item.res),
|
|
||||||
style = MaterialTheme.typography.labelLarge,
|
|
||||||
color = if (isSelected) MaterialTheme.colorScheme.onPrimaryContainer else MaterialTheme.colorScheme.onSurfaceVariant
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UnittoFilterChip(
|
|
||||||
isSelected = false,
|
|
||||||
selectAction = navigateToSettingsAction,
|
|
||||||
paddingValues = PaddingValues(horizontal = 8.dp)
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
modifier = Modifier.height(18.dp),
|
|
||||||
imageVector = Icons.Default.Settings,
|
imageVector = Icons.Default.Settings,
|
||||||
contentDescription = stringResource(R.string.open_settings_description)
|
contentDescription = stringResource(R.string.open_settings_description)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = { expanded = !expanded },
|
onClick = { expanded = !expanded },
|
||||||
@ -224,43 +178,6 @@ fun ChipsFlexRow(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Basic chip implementation
|
|
||||||
*
|
|
||||||
* @param isSelected Chip state.
|
|
||||||
* @param selectAction Action to perform when clicking chip.
|
|
||||||
* @param paddingValues Padding values applied to Row.
|
|
||||||
* @param content Content of the list. Icon and/or label.
|
|
||||||
*/
|
|
||||||
@Composable
|
|
||||||
private fun UnittoFilterChip(
|
|
||||||
isSelected: Boolean,
|
|
||||||
selectAction: () -> Unit,
|
|
||||||
paddingValues: PaddingValues = PaddingValues(start = 8.dp, end = 16.dp),
|
|
||||||
content: @Composable RowScope.() -> Unit
|
|
||||||
) {
|
|
||||||
val chipShape = RoundedCornerShape(8.dp)
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.height(32.dp)
|
|
||||||
.clip(chipShape)
|
|
||||||
.background(
|
|
||||||
if (isSelected) MaterialTheme.colorScheme.primaryContainer else Color.Transparent
|
|
||||||
)
|
|
||||||
// Remove border when selected
|
|
||||||
.border(
|
|
||||||
1.dp,
|
|
||||||
if (isSelected) Color.Transparent else MaterialTheme.colorScheme.outline,
|
|
||||||
chipShape
|
|
||||||
)
|
|
||||||
.clickable { selectAction() }
|
|
||||||
.padding(paddingValues),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
content()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun PreviewUnittoChips() {
|
fun PreviewUnittoChips() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user