Android Jetpack Compose - ModalNavigationDrawer、NavigationRail、PullToRefreshBox

一、ModalNavigationDrawer(抽屉式导航栏)

  1. 使用 drawerContent,提供 ModalDrawerSheet(提供抽屉式导航栏的内容)。可以通过从侧边滑动或点击按钮来打开抽屉式导航栏
kotlin 复制代码
var selectedItemIndex by remember { mutableStateOf(0) }

ModalNavigationDrawer(
    drawerContent = {
        ModalDrawerSheet {
            Text("抽屉式导航栏", modifier = Modifier.padding(16.dp))
            HorizontalDivider()
            NavigationDrawerItem(
                icon = { Icon(Icons.Filled.Home, contentDescription = null) },
                label = { Text("Home") },
                selected = selectedItemIndex == 0,
                onClick = { selectedItemIndex = 0 }
            )
            NavigationDrawerItem(
                icon = { Icon(Icons.Filled.Call, contentDescription = null) },
                label = { Text("Call") },
                selected = selectedItemIndex == 1,
                onClick = { selectedItemIndex = 1 }
            )
            NavigationDrawerItem(
                icon = { Icon(Icons.Filled.Email, contentDescription = null) },
                label = { Text("Email") },
                selected = selectedItemIndex == 2,
                onClick = { selectedItemIndex = 2 }
            )
            NavigationDrawerItem(
                icon = { Icon(Icons.Filled.Person, contentDescription = null) },
                label = { Text("Person") },
                selected = selectedItemIndex == 3,
                onClick = { selectedItemIndex = 3 }
            )
        }
    }
) {}
  1. 控制抽屉式导航栏的打开和关闭,使用 DrawerState,它提供了 open 与 close 方法
kotlin 复制代码
var selectedItemIndex by remember { mutableStateOf(0) }

val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
val scope = rememberCoroutineScope()

ModalNavigationDrawer(
    drawerState = drawerState,
    drawerContent = {
        ModalDrawerSheet {
            Text("抽屉式导航栏", modifier = Modifier.padding(16.dp))
            HorizontalDivider()
            NavigationDrawerItem(
                icon = { Icon(Icons.Filled.Home, contentDescription = null) },
                label = { Text("Home") },
                selected = selectedItemIndex == 0,
                onClick = {
                    selectedItemIndex = 0
                    scope.launch {
                        drawerState.close()
                    }
                }
            )
            NavigationDrawerItem(
                icon = { Icon(Icons.Filled.Call, contentDescription = null) },
                label = { Text("Call") },
                selected = selectedItemIndex == 1,
                onClick = {
                    selectedItemIndex = 1
                    scope.launch {
                        drawerState.close()
                    }
                }
            )
            NavigationDrawerItem(
                icon = { Icon(Icons.Filled.Email, contentDescription = null) },
                label = { Text("Email") },
                selected = selectedItemIndex == 2,
                onClick = {
                    selectedItemIndex = 2
                    scope.launch {
                        drawerState.close()
                    }
                }
            )
            NavigationDrawerItem(
                icon = { Icon(Icons.Filled.Person, contentDescription = null) },
                label = { Text("Person") },
                selected = selectedItemIndex == 3,
                onClick = {
                    selectedItemIndex = 3
                    scope.launch {
                        drawerState.close()
                    }
                }
            )
        }
    }
) {
    Box(
        modifier = Modifier.fillMaxSize(),
        contentAlignment = Alignment.Center,
    ) {
        Button(
            onClick = {
                scope.launch {
                    drawerState.open()
                }
            }
        ) {
            Text("打开抽屉式导航栏")
        }
    }
}
kotlin 复制代码
var selectedItemIndex by remember { mutableStateOf(0) }

val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
val scope = rememberCoroutineScope()

ModalNavigationDrawer(
    drawerState = drawerState,
    gesturesEnabled = false,
    drawerContent = {
        ModalDrawerSheet {
            Text("抽屉式导航栏", modifier = Modifier.padding(16.dp))
            HorizontalDivider()
            NavigationDrawerItem(
                icon = { Icon(Icons.Filled.Home, contentDescription = null) },
                label = { Text("Home") },
                selected = selectedItemIndex == 0,
                onClick = {
                    selectedItemIndex = 0
                    scope.launch {
                        drawerState.close()
                    }
                }
            )
            NavigationDrawerItem(
                icon = { Icon(Icons.Filled.Call, contentDescription = null) },
                label = { Text("Call") },
                selected = selectedItemIndex == 1,
                onClick = {
                    selectedItemIndex = 1
                    scope.launch {
                        drawerState.close()
                    }
                }
            )
            NavigationDrawerItem(
                icon = { Icon(Icons.Filled.Email, contentDescription = null) },
                label = { Text("Email") },
                selected = selectedItemIndex == 2,
                onClick = {
                    selectedItemIndex = 2
                    scope.launch {
                        drawerState.close()
                    }
                }
            )
            NavigationDrawerItem(
                icon = { Icon(Icons.Filled.Person, contentDescription = null) },
                label = { Text("Person") },
                selected = selectedItemIndex == 3,
                onClick = {
                    selectedItemIndex = 3
                    scope.launch {
                        drawerState.close()
                    }
                }
            )
        }
    }
) {
    Scaffold(
        topBar = {
            TopAppBar(
                colors = topAppBarColors(
                    containerColor = MaterialTheme.colorScheme.primaryContainer,
                    titleContentColor = MaterialTheme.colorScheme.primary,
                ),
                title = {
                    IconButton(
                        onClick = {
                            scope.launch {
                                drawerState.open()
                            }
                        }
                    ) {
                        Icon(Icons.Default.MoreVert, contentDescription = "MoreVert")
                    }
                }
            )
        },
    ) { innerPadding ->
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(innerPadding),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center,
        ) {
            Text("内容区域")
        }
    }
}

二、NavigationRail(侧边导航栏)

kotlin 复制代码
var selectedItemIndex by remember { mutableStateOf(0) }

NavigationRail {
    NavigationRailItem(
        icon = { Icon(Icons.Filled.Home, contentDescription = null) },
        label = { Text("Home") },
        selected = selectedItemIndex == 0,
        onClick = { selectedItemIndex = 0 }
    )
    NavigationRailItem(
        icon = { Icon(Icons.Filled.Call, contentDescription = null) },
        label = { Text("Call") },
        selected = selectedItemIndex == 1,
        onClick = { selectedItemIndex = 1 }
    )
    NavigationRailItem(
        icon = { Icon(Icons.Filled.Email, contentDescription = null) },
        label = { Text("Email") },
        selected = selectedItemIndex == 2,
        onClick = { selectedItemIndex = 2 }
    )
    NavigationRailItem(
        icon = { Icon(Icons.Filled.Person, contentDescription = null) },
        label = { Text("Person") },
        selected = selectedItemIndex == 3,
        onClick = { selectedItemIndex = 3 }
    )
}
kotlin 复制代码
var selectedItemIndex by remember { mutableStateOf(0) }

Row(
    modifier = Modifier.fillMaxSize()
) {
    NavigationRail {
        NavigationRailItem(
            icon = { Icon(Icons.Filled.Home, contentDescription = null) },
            label = { Text("Home") },
            selected = selectedItemIndex == 0,
            onClick = { selectedItemIndex = 0 }
        )
        NavigationRailItem(
            icon = { Icon(Icons.Filled.Call, contentDescription = null) },
            label = { Text("Call") },
            selected = selectedItemIndex == 1,
            onClick = { selectedItemIndex = 1 }
        )
        NavigationRailItem(
            icon = { Icon(Icons.Filled.Email, contentDescription = null) },
            label = { Text("Email") },
            selected = selectedItemIndex == 2,
            onClick = { selectedItemIndex = 2 }
        )
        NavigationRailItem(
            icon = { Icon(Icons.Filled.Person, contentDescription = null) },
            label = { Text("Person") },
            selected = selectedItemIndex == 3,
            onClick = { selectedItemIndex = 3 }
        )
    }

    Column(
        modifier = Modifier
            .fillMaxHeight()
            .weight(1f),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Text("内容区域")
    }
}
kotlin 复制代码
data class NavItem(
    val title: String,
    val icon: ImageVector,
)

val navItems = listOf(
    NavItem("Home", Icons.Filled.Home),
    NavItem("Call", Icons.Filled.Call),
    NavItem("Email", Icons.Filled.Email),
    NavItem("Person", Icons.Filled.Person)
)

var selectedItemIndex by remember { mutableStateOf(0) }

Row(
    modifier = Modifier.fillMaxSize()
) {
    NavigationRail {
        navItems.forEachIndexed { index, item ->
            NavigationRailItem(
                icon = { Icon(item.icon, contentDescription = item.title) },
                label = { Text(item.title) },
                selected = selectedItemIndex == index,
                onClick = { selectedItemIndex = index },
            )
        }
    }

    Column(
        modifier = Modifier
            .fillMaxHeight()
            .weight(1f),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        when (selectedItemIndex) {
            0 -> Text("Home")
            1 -> Text("Call")
            2 -> Text("Email")
            3 -> Text("Person")
        }
    }
}

三、PullToRefreshBox(下拉刷新)

1、基本介绍
  • PullToRefreshBox 组件用于实现下拉刷新,该组件可以包裹可滚动内容,关键参数如下
  1. isRefreshing:指示刷新操作是否正在进行

  2. onRefresh:当发起刷新时执行的函数

2、演示
kotlin 复制代码
var items by remember { mutableStateOf(List(5) { "第 ${it + 1} 项" }) }
val scope = rememberCoroutineScope()

var isRefreshing by remember { mutableStateOf(false) }

PullToRefreshBox(
    modifier = Modifier.fillMaxSize(),
    isRefreshing = isRefreshing,
    onRefresh = {
        isRefreshing = true
        scope.launch {
            delay(1500)
            items = List((1..10).random()) { "新数据 ${it + 1}" }
            isRefreshing = false
        }
    }
) {
    LazyColumn(
        modifier = Modifier.fillMaxSize(),
        contentPadding = PaddingValues(16.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        items(items) { item ->
            Card(
                modifier = Modifier.fillMaxWidth(),
                colors = CardDefaults.cardColors(
                    containerColor = MaterialTheme.colorScheme.surfaceVariant
                )
            ) {
                Text(
                    text = item,
                    modifier = Modifier.padding(16.dp),
                    style = MaterialTheme.typography.bodyLarge
                )
            }
        }
    }
}
相关推荐
圆山猫14 分钟前
[Virtualization](四):Linux KVM/RISC-V 的 vCPU 运行路径
java·linux·risc-v
城管不管1 小时前
ReAct、Plan-and-Execute、Reflection 三大智能 Agent 范式核心区别
java·人工智能·算法·spring·ai·动态规划
IT小白杨1 小时前
从环境制备到自动化工作流:多账号运营的工程化架构拆解
java·经验分享·自动化·安全架构·指纹浏览器
summerkissyou19871 小时前
Android - 摄像头 - hal - 开发教程,例子,常见问题,分析方法,解决方案
android
豆瓣鸡1 小时前
算法日记 - Day3
java·开发语言·算法
萧瑟余晖2 小时前
Java深入解析篇九之NIO详解
java·网络·nio
summerkissyou19872 小时前
Android 16 架构图
android
The Chosen One9852 小时前
高进度算法模板速记(待完善)
java·前端·算法
神龙天舞20012 小时前
MySQL 备库为什么会延迟好几个小时
android·数据库·mysql
海天鹰3 小时前
Android Studio Quail3 | 2026.1.3 升级后 Gradle 报错
android studio