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

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

原创
作者头像
Nimyears
修改2024-10-09 21:26:03
3530
修改2024-10-09 21:26:03
举报
文章被收录于专栏:JetpackCompose M3

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

一、项目背景

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

二、项目开发

2.1 配置项目依赖

代码语言:java
复制
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
复制

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
复制

@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
复制
@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
复制
selectedItem: DrawerScreen, onItemSelected: (DrawerScreen) -> Unit

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

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

代码语言:txt
复制
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
复制
@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
复制
@Preview(showBackground = true)
@Composable
fun PreviewDrawerContent() {
    DrawerContent(
        selectedItem = DrawerScreen.Account,
        onItemSelected = {}
    )
}

2.8 视频演示

视频内容

三、技术难点

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

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

代码语言:java
复制
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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、项目背景
  • 2.1 配置项目依赖
  • 2.2 介绍DrawerUI组件
  • 2.3 创建菜单项类
  • 2.3.1 解释代码
  • 2.4 开发DrawerMenu UI
  • 2.4.1 解释代码
  • 2.5 定义Drawer菜单项内容
  • 2.5.1 解释代码
  • 2.5.2 介绍三种Drawer源码
  • 2.5.3 源码的总结
  • 2.6 创建页面内容
  • 2.7 预览图
  • 2.8 视频演示
  • 三、技术难点
  • 四、学习笔记
  • 五、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档