1

I've a pager composed of cards and I want to control each card's border with a boolean variable: green if that variable's true, darkgrey else.

        var isPedestrianSelected by remember { mutableStateOf(false) }
        var isCyclistSelected by remember { mutableStateOf(false) }
        var isCarSelected by remember { mutableStateOf(false) }

        Card(
            shape = RoundedCornerShape(70.dp),
            border = BorderStroke(
                1.2.dp,
                when (page) {
                    0 -> { if (isPedestrianSelected) Color.Green else Color.DarkGray }
                    1 -> { if (isCarSelected) Color.Green else Color.DarkGray }
                    2 -> { if (isCyclistSelected) Color.Green else Color.DarkGray }
                    else -> { Color.DarkGray }
                }
            ),
            elevation = CardDefaults.cardElevation(
                defaultElevation = 12.dp
            ),
            onClick = {
                val stationType = when (page) {
                   0 -> StationType.PEDESTRIAN
                   1 -> StationType.PASSENGER_CAR
                   2 -> StationType.CYCLIST
                   else -> { StationType.PEDESTRIAN }
                }
                when (stationType) {
                    StationType.PEDESTRIAN -> {
                        isPedestrianSelected = true
                        isCarSelected = false
                        isCyclistSelected = false
                    }
                    StationType.PASSENGER_CAR -> {
                        isPedestrianSelected = false
                        isCarSelected = true
                        isCyclistSelected = false
                    }
                    StationType.CYCLIST -> {
                        isPedestrianSelected = false
                        isCarSelected = false
                        isCyclistSelected = true
                    }
                    else -> {}
                }
                ...
            },

Issue: when the boolean variable (e.g. isCarSelected) is set to true, the borders are colored correctly (green), but when it returns to false, the borders won't change (although I'd expect they would change back to the darkgrey color).

Thanks for help

EDIT: Maybe I can explain better. My purpose is that at most one card of the pager has a green border, so what my code should do is, if I select one page, then put a green border around the card of that page and remove all green borders around cards of other pages. Example: isCarSelected = true, so the card on page 1 is set to a green border. After scrolling the pager, I click on another page, say page 0, and this sets isPedestrianSelected=true and other booleans to false, such as isCarSelected = false, and this should turn page 1 color from green to darkgray (along with turning page 0 color from darkgray to green). But this doesn't happen for some reason.

1
  • Welcome to stackoverflow! If an answer resolved your issue, please mark it as accepted answer by clicking the checkmark at the left side of the answer. Commented Apr 18, 2024 at 11:54

2 Answers 2

0

The problem with your current code is that you declare your isPedestrianSelected / isCarSelected / isCyclistSelected variables within the content of the HorizontalPager. So each page will have its own three local variables.

Move your declaration on top of the HorizontalPager, then your code should work:

var isPedestrianSelected by remember { mutableStateOf(false) }
var isCyclistSelected by remember { mutableStateOf(false) }
var isCarSelected by remember { mutableStateOf(false) }

HorizontalPager(
    // ...
) { page ->

    Card(
        //...
    )
}

Note that you could simplify the logic of your implementation by instead using only one variable to store the index of the page where the card currently has a green border:

var selectedCardIndex by rememberSaveable { mutableStateOf(-1) }

HorizontalPager(
    //...
) { page ->
    
    Card(
        shape = RoundedCornerShape(70.dp),
        border = BorderStroke(
            1.2.dp,
            if (page == selectedCardIndex) Color.Green else Color.DarkGray
        ),
        elevation = CardDefaults.cardElevation(
            defaultElevation = 12.dp
        ),
        onClick = {
            selectedCardIndex = page
        },
        //...
    )
}
Sign up to request clarification or add additional context in comments.

1 Comment

Hello, thank you for the answer but unfortunately it doesn't address my issue.. I've added an edit to my question in order for it to be clearer. Basically I need to set the variable to false and the color to grey not when the same page is clicked twice, but when another page is clicked (the logic is that at most 1 page is selected and green at the same time). I elaborate more in the EDIT paragraph of my question.
0

The reason is in your onClick function, you only ever set the target value to true and never to false.

This should work:

when (stationType) {
    StationType.PEDESTRIAN -> {
        isPedestrianSelected = if(isPedestrianSelected) false else true
        isCarSelected = false
        isCyclistSelected = false
    }
    StationType.PASSENGER_CAR -> {
        isPedestrianSelected = false
        isCarSelected = if(isCarSelected) false else true
        isCyclistSelected = false
    }
    StationType.CYCLIST -> {
        isPedestrianSelected = false
        isCarSelected = false
        isCyclistSelected = if(isCyclistSelected) false else true
    }
    else -> {}
}

However, I believe you could improve the code overall by maintaining one nullable mutable state which is updated on click where null represents none selected.

var selectedStationType: StationType? by remember { mutableStateOf(null) }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.