I want to make a background color change when user select a item on Surface
. I am using Column
in my parent, so I can't make LazyColumn
. So I am using Foreach
to make a list of view. By default no view will be selected, when user click on item then I want change the color. Note: Only one item will select at a time.
ScanDeviceList
@Composable
fun ColumnScope.ScanDeviceList(
scanDeviceList: List<ScanResult>,
modifier: Modifier = Modifier,
pairSelectedDevice: () -> Unit
) {
Spacer()
AnimatedVisibility() {
Column {
Text()
Spacer()
scanDeviceList.forEachIndexed { index, scanResult ->
ClickableItemContainer(
rippleColor = AquaLightOpacity10,
content = {
ScanDeviceItem(index, scanResult, scanDeviceList)
}
){}
}
AvailableWarningText()
PairSelectedDevice(pairSelectedDevice)
}
}
}
ScanDeviceItem
@Composable
fun ScanDeviceItem(
index: Int,
scanResult: ScanResult,
scanDeviceList: List<ScanResult>
) {
Column {
if (index == 0) {
Divider(color = Cloudy, thickness = 1.dp)
}
Text(
text = scanResult.device.name,
modifier = Modifier.padding(vertical = 10.dp)
)
if (index <= scanDeviceList.lastIndex) {
Divider(color = Cloudy, thickness = 1.dp)
}
}
}
ClickableItemContainer
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun ClickableItemContainer(
rippleColor: Color = TealLight,
content: @Composable (MutableInteractionSource) -> Unit,
clickAction: () -> Unit
) {
val interactionSource = remember { MutableInteractionSource() }
CompositionLocalProvider(
LocalRippleTheme provides AbcRippleTheme(rippleColor),
content = {
Surface(
onClick = { clickAction() },
interactionSource = interactionSource,
color = White
) {
content(interactionSource)
}
}
)
}
I want to something like this
Now above solution is only working on ripple effect, Now I want to extend my function to select a single item at a time. Many Thanks
CodePudding user response:
You can store the selected index and use the clickAction
to update its value when the user clicks on each item.
Something like:
@Composable
fun MyList(
var selectedIndex by remember { mutableStateOf(-1) }
Column() {
itemsList.forEachIndexed() { index, item ->
MyItem(
selected = selectedIndex == index,
clickAction = { selectedIndex = index }
)
}
}
@Composable
fun MyItem(
selected : Boolean = false,
clickAction: () -> Unit
){
Surface(
onClick = { clickAction() },
color = if (selected) Color.Red else Color.Yellow
) {
Text("Item...")
}
}
CodePudding user response:
To have only item selected at a time, you can follow a behavior that is similar. You save your item selected in a mutableState variable, like:
var itemSelected by remember { mutableState(ScanDeviceResult()) }
After that, when you click the item, you update the itemSelected, something like:
ClickableItemContainer(
rippleColor = AquaLightOpacity10,
content = {
ScanDeviceItem(index, scanResult, scanDeviceList)
}
){ newItemSelected ->
itemSelected = newItemSelected
}
Now, each ClickableItemContainer needs to have an associated ScanResult.
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun ClickableItemContainer(
itemSelected: ScanResult,
scanResult: ScanResult,
rippleColor: Color = TealLight,
content: @Composable (MutableInteractionSource) -> Unit,
clickAction: (ScanResult) -> Unit
) {
val interactionSource = remember { MutableInteractionSource() }
CompositionLocalProvider(
LocalRippleTheme provides AbcRippleTheme(rippleColor),
content = {
Surface(
onClick = { clickAction.invoke(scanResult) },
interactionSource = interactionSource,
color = if (itemSelected == scanResult) YOUR_BACKGROUND-SELECTED_COLOR else White
) {
content(interactionSource)
}
}
)
}
Now, on your ScanDeviceList method:
@Composable
fun ColumnScope.ScanDeviceList(
itemSelected: MutableState<ScanResult>,
scanDeviceList: List<ScanResult>,
modifier: Modifier = Modifier,
pairSelectedDevice: () -> Unit
) {
Spacer()
AnimatedVisibility() {
Column {
Text()
Spacer()
scanDeviceList.forEachIndexed { index, scanResult ->
ClickableItemContainer(
itemSelected = itemSelected,
scanResult = scanResult,
rippleColor = AquaLightOpacity10,
content = {
ScanDeviceItem(index, scanResult, scanDeviceList)
}
){ scanResultToSelect ->
itemSelected = scanResultToSelect
}
}
AvailableWarningText()
PairSelectedDevice(pairSelectedDevice)
}
}
}