I am using jetpack compose / Kotlin to create my first android app.
I am using a navigation drawer like so
ModalNavigationDrawer(
drawerContent = {
ModalDrawerSheet {
Text(text = stringResource(id = R.string.app_name), modifier = Modifier.padding(16.dp))
Divider()
NavigationDrawerItem(
label = { Text(text = stringResource(id = R.string.settings_title)) },
icon = {Icon(
Icons.Filled.Settings,
contentDescription = stringResource(id = R.string.settings_title)
)},
selected = false,
onClick = { /*TODO*/ }
)
NavigationDrawerItem(
label = { Text(text = stringResource(id = R.string.collections)) },
icon = {Icon(
painterResource(id = R.drawable.baseline_collections_bookmark_24),
contentDescription = stringResource(id = R.string.collections)
)},
selected = false,
onClick = { /*TODO*/ }
)
// ...other drawer items
}
},
gesturesEnabled = true,
content = content
)
which gives this
I want to make the second item expandable like in this question, however all resources I find use the view system which as I understand is outdated and which anyway I know nothing about.
How can I implement this using Compose ?
There is a lot of option you can play around showing option.
I'm showing you one of the simple option to show/hide the list below the option in ModalNavigationDrawer
I have made this sample using Material3
. Checkout the complete code.
MainActivity.kt
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.rememberDrawerState
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.md.bottomsheetjetpackcompose.ui.theme.BottomSheetJetpackComposeTheme
import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
BottomSheetJetpackComposeTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
val scope = rememberCoroutineScope()
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
Sidebar(drawerState = drawerState) {
Box(
modifier = Modifier
.fillMaxWidth()
.background(color = MaterialTheme.colorScheme.primary)
.padding(12.dp)
.clickable {
scope.launch {
drawerState.open()
}
},
contentAlignment = Alignment.Center
) {
Text(text = "Click To Open Drawer")
}
}
}
}
}
}
}
ModalNavigation.kt
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.List
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.Divider
import androidx.compose.material3.DrawerState
import androidx.compose.material3.Icon
import androidx.compose.material3.ModalDrawerSheet
import androidx.compose.material3.ModalNavigationDrawer
import androidx.compose.material3.NavigationDrawerItem
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
@Composable
fun Sidebar(drawerState: DrawerState, content: @Composable () -> Unit) {
val showSubMenu = remember {
mutableStateOf(false)
}
ModalNavigationDrawer(
drawerState = drawerState,
drawerContent = {
ModalDrawerSheet {
Text(
text = stringResource(id = R.string.app_name),
modifier = Modifier.padding(16.dp)
)
Divider()
NavigationDrawerItem(
label = { Text(text = stringResource(id = R.string.settings_title)) },
icon = {
Icon(
Icons.Filled.Settings,
contentDescription = stringResource(id = R.string.settings_title)
)
},
selected = false,
onClick = { /*TODO*/ }
)
NavigationDrawerItem(
label = { Text(text = stringResource(id = R.string.collections)) },
icon = {
Icon(
Icons.Filled.List,
contentDescription = stringResource(id = R.string.collections)
)
},
selected = false,
onClick = { showSubMenu.value = !showSubMenu.value }
)
AnimatedVisibility(visible = showSubMenu.value) {
SubMenu()
}
// ...other drawer items
}
},
gesturesEnabled = true,
content = content
)
}
@Composable
fun SubMenu() {
Column ( Modifier.padding(start = 16.dp, end = 24.dp, top = 15.dp)){
Text(text = "Option 1")
Text(text = "Option 2")
Text(text = "Option 2")
}
}
Explanation about the code.
AnimatedVisibility
composable to show/hide content with default Animation.Preview Result