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
                )
            }
        }
    }
}
相关推荐
FlightYe4 分钟前
linux系统编程(十七):内存管理基础
android·linux·ffmpeg·音视频·android runtime
众链网络12 分钟前
年卡跨淡旺季的有效期模型:不可用日期、次数与顺延规则
java·前端·数据库
文丑颜不良啊14 分钟前
LeetCode926~950题目解析
java·leetcode
今天的砖头有点烫手啊20 分钟前
Java 对象内存布局:压缩指针、对齐填充与 JOL 实测
java·jvm
devilnumber27 分钟前
Lambda 表达式(Java)优缺点清晰分析
java·开发语言·python
时空节拍AI数字人30 分钟前
博物馆数字人讲解系统设计:知识库 schema、展项联动协议与时序控制
java·服务器·前端·人工智能·ai·语音识别
蒲公英内测分发31 分钟前
智能家居厂商有多个产品线,包装上的 App 下载入口该共用还是分开?
android·人工智能·数码相机·机器人·智能家居·智能硬件
GG.WinGel40 分钟前
三元组中心问题
java·数据结构·算法·青少年编程·蓝桥杯
vailee1 小时前
42 万字符的工具输出压进 6,945 token:Agent 长会话的上下文治理实践
java·大数据·人工智能·prompt工程·rag·上下文管理
weixin_448771721 小时前
Spring框架之ConfigurableApplicationContext源码学习
java·spring