前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >安卓软件开发:使用Jetpack Compose实现DrawerMenuApp

安卓软件开发:使用Jetpack Compose实现DrawerMenuApp

原创
作者头像
Nimyears
修改于 2024-10-15 00:57:37
修改于 2024-10-15 00:57:37
8810
举报
文章被收录于专栏:JetpackCompose M3JetpackCompose M3

2024年已经过半了,我作为聋人独立开发者,我经常会时不时反思:自己这半年到底进步了多少?在这篇文章里,我分享一个用 Jetpack Compose、Material3和 Kotlin语言开发NimDrawaerMenuApp的案例。无论你有没有开发经验,相信这篇文章对你会非常有所帮助。

一、项目背景

在现代应用中,导航是关键元素,特别是使用侧边栏(Drawer Menu)切换不同页面的场景。通过 Jetpack Compose,安卓开发已经从传统的 XML 布局转向了声明式 UI 方式,简化了很多工作。这个Demo演示利用 Jetpack Compose 和 Material 3 实现一个带有 Drawer 菜单的应用,帮助用户理解工作机制,通过此应用进行页面切换。

二、项目开发

2.1 配置项目依赖

代码语言:java
AI代码解释
复制
plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
}

android {
    namespace = "eu.tutorials.drawermenuappdemo"
    compileSdk = 34

    defaultConfig {
        applicationId = "eu.tutorials.drawermenuappdemo"
        minSdk = 24
        targetSdk = 34
        versionCode = 1
        versionName = "1.0"
    }

    buildTypes {
        release {
            isMinifyEnabled = false
        }
    }

    buildFeatures {
        compose = true
    }

    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.1"
    }

    kotlinOptions {
        jvmTarget = "1.8"
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
}

dependencies {
    val compose_version = "1.6.0-alpha08"
    val nav_version = "2.7.5"

    implementation("androidx.compose.ui:ui:$compose_version")
    implementation("androidx.compose.material3:material3:$compose_version")
    implementation("androidx.navigation:navigation-compose:$nav_version")
    implementation("androidx.activity:activity-compose:1.8.0")
}

2.2 介绍DrawerUI组件

Drawer 是侧边栏菜单,提供一种易于访问的页面切换方式,用于多功能的应用App,允许用户在不同页面之间快速切换。在 Jetpack Compose 中,使用 ModalNavigationDrawer 组件构建 Drawer 菜单,根据用户操作动态显示或隐藏菜单。

2.3 创建菜单项类

在项目中,每个 Drawer 菜单项对应一个独立页面,使用 sealed class 定义菜单项:

代码语言:java
AI代码解释
复制

sealed class DrawerScreen(val title: String, val icon: ImageVector) {
    object Account : DrawerScreen("账户", Icons.Filled.AccountCircle)
    object Subscription : DrawerScreen("订阅", Icons.Filled.Subscriptions)
    object AddAccount : DrawerScreen("添加账户", Icons.Filled.PersonAdd)
}

val drawerItems = listOf(
    DrawerScreen.Account,
    DrawerScreen.Subscription,
    DrawerScreen.AddAccount
)

2.3.1 解释代码

定义了DrawerScreen类为每个菜单项设置了标题和图标。通过drawerItems列表,drawerItems 是菜单项的集合,用于构建完整的 Drawer 菜单。

2.4 开发DrawerMenu UI

DrawerMenuApp 是应用的核心,它通过 ModalNavigationDrawer 和 Scaffold 组件构建侧边菜单布局和顶部应用栏:

代码语言:java
AI代码解释
复制

@Composable
fun DrawerMenuApp() {
    var selectedItem by remember { mutableStateOf<DrawerScreen>(DrawerScreen.Account) }
    val drawerState = rememberDrawerState(DrawerValue.Closed)
    val scope = rememberCoroutineScope()

    ModalNavigationDrawer(
        drawerContent = {
            DrawerContent(
                selectedItem = selectedItem,
                onItemSelected = { selectedItem = it; scope.launch { drawerState.close() } }
            )
        },
        drawerState = drawerState
    ) {
        Scaffold(
            topBar = {
                TopAppBar(
                    title = { Text(selectedItem.title) },
                    navigationIcon = {
                        IconButton(onClick = { scope.launch { drawerState.open() } }) {
                            Icon(Icons.Default.Menu, contentDescription = "Menu")
                        }
                    }
                )
            }
        ) { paddingValues ->
            Box(modifier = Modifier.padding(paddingValues)) {
                // 显示对应的页面内容
                when (selectedItem) {
                    DrawerScreen.Account -> AccountScreen()
                    DrawerScreen.Subscription -> SubscriptionScreen()
                    DrawerScreen.AddAccount -> AddAccountScreen()
                }
            }
        }
    }
}

2.4.1 解释代码

DrawerMenuApp 通过 Scaffold 设置顶部栏,通过 ModalNavigationDrawer 进行页面切换。在点击菜单项时,会关闭抽屉并切换到对应的页面内容。

2.5 定义Drawer菜单项内容

DrawerContent 负责展示菜单项内容。每个项都是一个 NavigationDrawerItem,当用户点击项时,调用 onItemSelected 切换页面。

代码语言:java
AI代码解释
复制
@Composable
fun DrawerContent(
    selectedItem: DrawerScreen,
    onItemSelected: (DrawerScreen) -> Unit
) {
    ModalDrawerSheet {

        Box(
            modifier = Modifier
                .fillMaxWidth()
                .padding(top = 20.dp),
            contentAlignment = Alignment.Center
        ) {
            Text("NimDrawer", modifier = Modifier.padding(10.dp))
        }

        drawerItems.forEach { item ->
            NavigationDrawerItem(
                label = { Text(item.title) },
                icon = { Icon(item.icon, contentDescription = null) },
                selected = item == selectedItem,
                onClick = { onItemSelected(item) },
                modifier = Modifier.padding(8.dp)
            )
        }
    }
}

2.5.1 解释代码

代码语言:java
AI代码解释
复制
selectedItem: DrawerScreen, onItemSelected: (DrawerScreen) -> Unit

selectedItem:当前选中的菜单项,类型是 DrawerScreen,指示当前高亮显示的菜单项。

onItemSelected:一个回调函数,用于处理用户点击菜单项时的逻辑。它接收一个 DrawerScreen 对象,表示用户选中的菜单项。点击某个菜单项时会调用这个函数,然后选中的菜单项作为参数传递。

代码语言:txt
AI代码解释
复制
ModalDrawerSheet {
  • ModalDrawerSheet 是 Material 3 中提供的一个组件,用于显示抽屉的内容。

2.5.2 介绍三种Drawer源码

一. ModalDrawerSheet

(1) 场景:ModalDrawerSheet 是最常见的 Drawer 类型,用于显示在应用的内容之上,当 Drawer 打开时,主界面会被覆盖,需要用户手动关闭或点击其他地方来收起抽屉。

(2) 解释

• ModalDrawerSheet 是用于模态抽屉的组件,它会覆盖住当前内容,用户必须关闭它才能回到主界面。

• 在代码中,我们通过 ModalDrawerSheet 包裹所有的菜单项,点击其中的任意一项可以触发不同的操作。

(3) 适用场景

• 比如一个购物应用中的导航栏,当用户点击左上角的菜单按钮时,抽屉滑出,显示购物车、收藏夹、账户信息等。

二. DismissibleDrawerSheet

(1) 场景:DismissibleDrawerSheet 是用户可以通过滑动手势轻松关闭的 Drawer。它允许用户更自然和抽屉交互

(2) 解释

• DismissibleDrawerSheet 的工作原理与 ModalDrawerSheet 类似,但不同的是它更注重用户手势关闭的体验。用户可以直接通过滑动关闭这个抽屉,而不是必须点击关闭按钮。

• 这为用户提供了更流畅的体验。

(3) 适用场景

• 比如社交类应用中的消息推送列表,当用户从侧边滑动出菜单后,浏览完内容,用户可以随时通过手势关闭,不需要再次点击关闭按钮。

3. PermanentDrawerSheet

(1) 场景:PermanentDrawerSheet 是一种固定的抽屉,它不会因为用户交互而隐藏。一般来说用于大屏设备,比如平板或者桌面端的应用。

(2) 解释

• PermanentDrawerSheet 与前两种抽屉不同,它是固定在界面左侧的,用户无法将它关闭。它适合那些需要一直显示导航的场景,比如电子邮件客户端或者文件管理器。

• 这种 Drawer 不会挡住主屏幕内容,而是始终内容排显示

(3) 适用场景

• 比如在邮件应用中,你可以看到左边有固定的邮箱文件夹列表,右边是邮件内容。文件夹导航不会随着用户操作消失。

2.5.3 源码的总结

三种 Drawer 的使用场景各有不同:

ModalDrawerSheet:适合短暂显示,需要用户手动关闭。

DismissibleDrawerSheet:更便捷的用户体验,允许通过滑动手势关闭。

PermanentDrawerSheet:在大屏设备上固定显示,适合信息密集型应用。

2.6 创建页面内容

每个菜单项对应的页面是一个简单的 Composable,每个页面只是展示一个简单的文本,代表对应的菜单项:

代码语言:java
AI代码解释
复制
@Composable
fun AccountScreen() {
    Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        Text("Nim账户页面")
    }
}

@Composable
fun SubscriptionScreen() {
    Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        Text("Nim订阅页面")
    }
}

@Composable
fun AddAccountScreen() {
    Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        Text("Nim添加账户页面")
    }
}

2.7 预览图

代码语言:java
AI代码解释
复制
@Preview(showBackground = true)
@Composable
fun PreviewDrawerContent() {
    DrawerContent(
        selectedItem = DrawerScreen.Account,
        onItemSelected = {}
    )
}

2.8 视频演示

三、技术难点

用 remember 和 mutableStateOf 存储用户点击的菜单项,通过 DrawerState 控制 Drawer 的显示和隐藏状态。这种方式为了是在用户点击菜单项时,可以同步显示对应的页面内容。

看这段代码理解是每次点击菜单项时,都会触发 onItemSelected 回调,这个回调函数通过 mutableStateOf 更新当前选中的菜单项,关闭 Drawer。

代码语言:java
AI代码解释
复制
var selectedItem by remember { mutableStateOf<DrawerScreen>(DrawerScreen.Account) }
val drawerState = rememberDrawerState(DrawerValue.Closed)
val scope = rememberCoroutineScope()

ModalNavigationDrawer(
    drawerContent = {
        DrawerContent(
            selectedItem = selectedItem,
            onItemSelected = { selectedItem = it; scope.launch { drawerState.close() } }
        )
    },
    drawerState = drawerState
)

核心逻辑是:每次用户点击菜单项时,都会通过 onItemSelected 修改 selectedItem,从而控制页面的显示和抽屉的关闭。

四、学习笔记

我深刻体会到了Material 3 中的 Drawer 的三种模式(ModalDrawerSheet、DismissibleDrawerSheet 和 PermanentDrawerSheet)让我对不同使用场景的 Drawer 有了更深入的理解。在交互体验和视觉展示上各有特色,可以适应不同应用场景。

五、总结

通过这个DrawerMenuAppDemo,展示了如何在Jetpack Compose M3中实现一个带有抽屉菜单的安卓应用,添加更多的菜单项以及对应的页面功能。

有任何问题欢迎提问,感谢大家阅读 )

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
安卓软件开发:使用Jetpack Compose和M3的轮播图和列表App-上篇
这个应用中常见的 UI 需求是轮播图、列表和弹窗,使用 Jetpack Compose 和 M3 的组件,可以快速、高效编码现代化的 UI。
Nimyears
2024/10/12
8570
compose--初入compose、资源获取、标准控件与布局
compose正式发布已经一年多了,越来越多的开发人员选择使用它,声明式UI也是未来的一个主流趋势,本人也是一年前学习后,并没有真正的使用,所以本着边学习,边分享的心态,准备写个compose系列的文章 首先compose目前只支持kotlin,基于google对移动端的鸿图,未来应该也不会支持其他语言,和传统安卓的xml布局不同,compose是通过kotlin定义一个一个组件,由于是通过代码定义的组件,每个组件都可以很方便的重用,这点在UI开发时确实便利了不少。至于声明式UI和命令式UI的区别,相信你会在后续实际使用时有很大的感触
aruba
2022/12/06
6.7K0
compose--初入compose、资源获取、标准控件与布局
安卓软件开发:使用Jetpack Compose实现高级NimNavBottomApp
展示 Jetpack Compose 如何简化 UI 的编码,如何使用 Material 3 提供的组件实现现代化的 Android 应用设计。初级开发可以看怎么通过实现跳转底部导航栏对应tiem对应的内容,也有详细介绍了中高级开发者提供了实用技巧,比如如何处理通知徽章(Badges)和导航状态的管理。这个Demo,我实现了一个常见的底部导航栏App,包括多个页面切换、选中状态的高亮显示、徽章通知的显示等功能。
Nimyears
2024/10/07
3960
compose--修饰符Modifier
上次介绍了compose中大多数的标准组件,此外还有两个重要的组件:列表LazyColumn和LazyRow,以及约束布局ConstraintLayout,在使用它们之前,先来认识Modifier
aruba
2022/12/11
2.1K0
compose--修饰符Modifier
安卓软件开发:学习Jetpack Compose实现Navigation组件App
在日常工作中经常面临复杂 UI 的构建挑战,以前的开发方式依赖繁琐的XML布局和Activity、Fragment之间的频繁切换,代码大量重复且难以维护。Jetpack Compose 的出现让我们看到了新的可能性:声明式UI让UI和业务逻辑的绑定很简洁,让页面导航更顺畅。
Nimyears
2024/09/28
6040
compose--附带效应、传统项目集成、导航
该文章将是compose基础系列中最后一篇,附带效应是这篇文章的重点,其余补充内容为如何在传统xml中集成compose、compose导航的使用
aruba
2023/01/18
2.3K0
安卓软件开发:用JetpackCompose实现NimReplyAppUI上篇
NimReplyApp 是一个模拟电子邮件应用的案例项目,用户可以浏览邮件、查看详细内容和发送回复,在日常工作和生活中都很常见。
Nimyears
2024/10/15
5650
安卓软件开发:使用Jetpack Compose实现 NimWebViewApp
本文展示如何使用 Jetpack Compose 中的 AndroidView 加载 WebView,处理页面的加载状态和返回导航操作。
Nimyears
2024/10/08
6990
Jetpack Compose中的基本组件及组件提取
除了布局组件外,Jetpack Compose 还提供了一系列其他常用的 UI 组件。
码客说
2024/03/29
3600
Jetpack Compose中的基本组件及组件提取
安卓软件开发:手把教Jetpack Compose实现对接接口服务层的开发
Jetpack Compose 是一个非常重要的 UI 工具,摆脱了传统 XML 布局的麻烦,实现了声明式 UI 开发。这篇文章详细介绍如何通过 Jetpack Compose 构建一个简单Demo,实现从远程 API 获取数据、显示分类列表的功能。Demo的主要目标是展示如何通过 ViewModel 和 Retrofit 实现接口服务层的对接。
Nimyears
2024/10/01
6010
安卓软件开发:使用Jetpack Compose和Room开发NimWishApp-上篇
在Demo中,采用了最新的Jetpack ComposeM3技术栈,结合了Room数据库实现数据的持久化存储,提供了一个从UI层到数据层的完整解决方案,展示了从0到1的开发。
Nimyears
2024/10/03
4710
安卓软件开发:Jetpack Compose、Material 3和Kotlin协程在Android开发协程App
NimTwoTrackApp模拟两位选手赛跑。应用界面中包含两个按钮:开始/停止和重置,两个用于显示赛跑者进度的进度条。选手 1 和 2 被设置为不同的速度“奔跑”。
Nimyears
2024/09/19
5650
安卓软件开发:JetpackCompose从零开发CURD列表App
CURD列表App的实用性和常见性成为一个典型的开发案例,涵盖了数据管理、UI、UX等基本的开发知识点。
Nimyears
2024/10/02
2980
Android Jetpack Compose开发体验
作为Android开发者,xml布局和Compose布局大家应该很熟悉,而Compose作为Android平台上第二款支持声明式UI的框架,第一款是Flutter框架了。
Rouse
2024/06/11
4820
Android Jetpack Compose开发体验
【建议收藏】Jetpack Compose编程知识全汇总 (含详细实例讲解)
Jetpack Compose是Google I/O 2019 发布的Andorid UI框架,它不同于Andorid常见的Xml+命令式Coding的UI开发范式,而是基于Kotlin的DSL实现了一套类似React的声明式UI框架。Jetpack Compose目前仍然处于Alpha版本目标是2020年能够发布稳定的Beta版本。伴随React Native、Flutter等大前端框架的兴起以及Jetpack Compose、SwiftUI等native框架的出现,声明式UI正逐渐成为客户端UI开发的新趋势。
网易Leo
2021/12/09
6.6K0
【建议收藏】Jetpack Compose编程知识全汇总 (含详细实例讲解)
Jetpack Compose中的下拉刷新
Jetpack Compose光下拉刷新,官方就提供了三种不同的方式,使用的依赖也不相同,特别的混乱。
码客说
2024/03/29
1K0
安卓软件开发:Jetpack Compose 和 Material 3 实现高级登录页面(Kotlin)
在项目的 build.gradle 文件中添加 Compose 和 Material 3 的依赖项:
Nimyears
2024/09/14
1K0
安卓软件开发:基于Jetpack Compose实现Redux架构
• 整个应用只有一个Store。Store是一个数据仓库,保存着当前应用的所有状态 (State)。
Nimyears
2025/02/02
2051
安卓软件开发:用JetpackCompose实现NimReplyAppLogic中篇
在上篇文章中,介绍了如何使用 Jetpack Compose 和 Material Design 3(M3)构建 NimReplyApp 的基础 UI 组件。在中篇中,深入探讨 NimReplyApp 的业务逻辑实现,重点关注应用的核心功能,如电子邮件的获取、筛选、状态管理。
Nimyears
2024/10/22
2060
安卓软件开发:怎么快速上手JetPackComposeUI框架
Jetpack Compose 是 Google 推出的现代安卓 UI 框架,彻底改变了安卓应用的界面开发方式。相比传统的 View 系统,Jetpack Compose 更加简洁、灵活,高度集成了 Kotlin 语言的声明式编程风格。在这个框架中,开发者通过编写函数来描述 UI,不再需要依赖复杂的 XML 布局文件。接下来,通过几个关键步骤,帮助你快速上手 Jetpack Compose,在实际项目中充分发挥它的优势。
Nimyears
2024/09/25
7910
推荐阅读
相关推荐
安卓软件开发:使用Jetpack Compose和M3的轮播图和列表App-上篇
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档