Hey there. I'm trying to implement a sidebar item ...
# compose
r
Hey there. I'm trying to implement a sidebar item menu like this one, I'm trying implementing a shape for the row but I realized that might not be possible because shape will only affect current sidebar row and looks like needs to affect also the other one. Does anyone have an example of it?
Using css is possible with :before and :after but I don't think that is possible in compose.
j
I see two approaches you could use to achieve this: 1. The amateurish approach I would attempt would be to achieve this by adding a custom shape to the navigation drawer/sidebar. a. Using a path, you could define a rectangle that defines the overall navigation drawer/sidebar. b. For the selected item you’d modify the right edge of the path to inset the “popsicle” shape in the path… This part is a little tricky to get the look just right. c. You will need to know the size, y offset of the first item, as well as the item spacing to make sure you draw the indicator at the correct location. d. Doing it this way you can easily animate the “selection” shape to the correct item. 2. The more desired approach would be to create the “popsicle” shape and apply it directly to the selected item. a. You want to make sure you don’t have a “clip”
modifier
after the shape
modifier
otherwise you’ll loose the “fan out” bits towards the top and bottom left edges of the shape. b. Animating this would be trickier. You won’t be able to easily animate the “selection” shape animating behind the intermediate items… You could possibly do a funky shrinking/growing animating though.
c
It’s even simpler. Give the item before (here the “User Central”) the selected item a bottomEnd border radius and the item after (here the “Admin”) a topEnd border radius shape. You can then even have a nice animation with animating the radii.
Copy code
@Composable
@Preview
fun BoxScreen() {
    Box(
        Modifier
            .fillMaxSize()
            .background(Color.White),
    ) {
        Box(
            Modifier
                .width(200.dp)
                .fillMaxHeight()
                .background(Color.White),
        ) {
            Column {
                Box(
                    Modifier
                        .fillMaxWidth()
                        .height(20.dp)
                        .clip(
                            RoundedCornerShape(bottomEnd = 20.dp),
                        )
                        .background(Color.Green),
                )
                Box(
                    Modifier
                        .fillMaxWidth()
                        .height(20.dp)
                        .background(Color.White),
                )
                Box(
                    Modifier
                        .fillMaxWidth()
                        .height(20.dp)
                        .clip(
                            RoundedCornerShape(topEnd = 20.dp),
                        )
                        .background(Color.Green),
                    )
            }
        }
    }
}
with animation
Copy code
@Composable
@Preview
fun BoxScreen() {

    var enabled by remember { mutableStateOf(false) }

    val radius by animateDpAsState(if (enabled) 20.dp else 0.dp)

    Box(
        Modifier
            .fillMaxSize()
            .background(Color.White),
    ) {
        Box(
            Modifier
                .width(200.dp)
                .fillMaxHeight()
                .background(Color.White),
        ) {
            Column {
                Box(
                    Modifier
                        .fillMaxWidth()
                        .height(20.dp)
                        .clip(
                            RoundedCornerShape(bottomEnd = radius),
                        )
                        .background(Color.Green),
                )
                Box(
                    Modifier
                        .fillMaxWidth()
                        .height(20.dp)
                        .background(if (enabled) Color.White else Color.Green)
                        .clickable {
                            enabled = !enabled
                        },
                )
                Box(
                    Modifier
                        .fillMaxWidth()
                        .height(20.dp)
                        .clip(
                            RoundedCornerShape(topEnd = radius),
                        )
                        .background(Color.Green),
                )
            }
        }
    }
}
j
I guess it depends on the “highlight” animation they want. Using custom corner radius approach on the nearby items would make it impossible to have a vertical sliding animation.
c
yeah, but no one was talking about vertical sliding animation 😉
also none of yours would be able to to that as you apply the modifier to an item 🤷🏻
j
True but I’m just tying to come up with a robust solution and I wanted to be mindful of a solution that would allow the simple animation…. My first solution would allow for for a vertical sliding animation you would just need to pass the selected index in. I used a similar trick to make a wavy navigation bar in production app.
👍🏻 1
Here is a prototype I build using the first approach for a NavBar.
so beautiful 3
r
Thanks for the anwsers folks!! Will show the final result
s
You can try write a custom shape like this