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
                )
            }
        }
    }
}
相关推荐
Byron__2 小时前
HashSet/LinkedHashSet/TreeSet 原理解析
java
侠客工坊2 小时前
大模型落地移动端:解析侠客工坊端侧 Agent 的零拷贝(Zero-Copy)屏幕感知与空间映射
android·人工智能
苏瞳儿2 小时前
创建后端项目-连接MySql并运行成功
java
北漂Zachary2 小时前
Laravel7.x核心特性全解析
android
菜鸟小九2 小时前
JUC(共享模型之管程、synchronized、wait、park、活跃性、renetrantlock、条件变量)
java·开发语言·juc
kongba0072 小时前
学习COZE编程 / LangGraph 通用工作流项目 提示词模板
java·网络·学习
程序员阿明2 小时前
spring boot3识别PDF图纸
java·spring boot·后端·pdf
blxr_3 小时前
Spring AI自定义Advisor
java·spring