Reputation: 6795
I have a string list of texts, when I click one of them I should color it in one color, currently my implementation colors all of the texts, what I'm doing wrong ?
var isPressed by remember { mutableStateOf(false) }
val buttonColor: Color by animateColorAsState(
targetValue = when (isPressed) {
true -> FreshGreen
false -> PastelPeach
},
animationSpec = tween()
)
LazyRow(
modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(25.dp)
) {
items(filterList) { filterName ->
Text(
text = filterName,
modifier = Modifier
.background(shape = RoundedCornerShape(24.dp), color = buttonColor)
.padding(horizontal = 16.dp, vertical = 8.dp)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null
) {
isPressed = !isPressed
onFilterClick(filterName)
}
)
}
}
Upvotes: 4
Views: 471
Reputation: 6795
For those who wants only to keep selected only one item at the time, here is the way I went for
@Composable
fun BrandCategoryFilterSection(
modifier: Modifier,
uiState: BrandFilterUiState,
onBrandCategoryClick: (String) -> Unit
) {
var selectedIndex by remember { mutableStateOf(-1) }
LazyRow(
modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(25.dp)
) {
itemsIndexed(uiState.categoryList) { index, categoryName ->
CategoryText(
categoryName = categoryName,
isSelected = index == selectedIndex,
onBrandCategoryClick = {
selectedIndex = index
onBrandCategoryClick(it)
}
)
}
}
}
@Composable
private fun CategoryText(categoryName: String, onBrandCategoryClick: (String) -> Unit, isSelected: Boolean) {
val buttonColor: Color by animateColorAsState(
targetValue = when (isSelected) {
true -> FreshGreen
false -> PastelPeach
},
animationSpec = tween()
)
Text(
text = categoryName,
modifier = Modifier
.background(shape = RoundedCornerShape(24.dp), color = buttonColor)
.padding(horizontal = 16.dp, vertical = 8.dp)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null
) {
onBrandCategoryClick(categoryName)
}
)
}
Upvotes: 2
Reputation: 363845
You are using the same state (isPressed
) for all the items.
As alternative to z.y's answer you can just move the isPressed
declaration inside the items
block:
LazyRow(
horizontalArrangement = Arrangement.spacedBy(25.dp)
) {
items(itemsList) { filterName->
var isPressed by remember { mutableStateOf(false) }
val buttonColor: Color by animateColorAsState(
targetValue = when (isPressed) {
true -> Color.Green
false -> Color.Red
},
animationSpec = tween()
)
Text(
//your code
)
}
}
Upvotes: 2
Reputation: 6207
I modified your code, where I lowered down the animation and the pressed state so the parent composable won't suffer from its own re-composition
@Composable
fun MyScreen(
modifier: Modifier = Modifier,
filterList: SnapshotStateList<String>
) {
LazyRow(
modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(25.dp)
) {
items(filterList) { filterName ->
FilterText(
filterName
)
}
}
}
@Composable
fun FilterText(
filter: String
) {
var isPressed by remember { mutableStateOf(false) }
val buttonColor: Color by animateColorAsState(
targetValue = when (isPressed) {
true -> Color.Blue
false -> Color.Green
},
animationSpec = tween()
)
Text(
text = filter,
modifier = Modifier
.background(shape = RoundedCornerShape(24.dp), color = buttonColor)
.padding(horizontal = 16.dp, vertical = 8.dp)
.clickable {
isPressed = !isPressed
}
)
}
Upvotes: 1