前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >安卓软件开发:使用Jetpack Compose和M3的轮播图和列表App-上篇

安卓软件开发:使用Jetpack Compose和M3的轮播图和列表App-上篇

原创
作者头像
Nimyears
修改2024-10-15 19:09:32
3360
修改2024-10-15 19:09:32
举报
文章被收录于专栏:JetpackCompose M3

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

一、项目背景

这个应用中常见的 UI 需求是轮播图、列表和弹窗,使用 Jetpack Compose 和 M3 的组件,可以快速、高效编码现代化的 UI。

二、项目开发

2.1 介绍轮播图(Carousel) UI

但是遗憾想要告诉大家,目前,Jetpack Compose 本身还没有现成的轮播图控件(,只能用Android原生实现-下篇会讲

2.2 轮播图实现

在首页的 HomeScreen 中使用了 LazyRow 来实现横向滚动的轮播图,还展示了如何使用 M3 的组件创建卡片样式的分类项,自定义颜色、样式和阴影效果。

代码语言:java
复制
@OptIn( ExperimentalFoundationApi::class)
@Composable
fun HomeScreen() {
    val categories = listOf("Nim", "Nim", "Nim", "Nim", "Nim", "Nim")
    val grouped = listOf("Nim大标题", "Nim 中标题" , " Nim标题").groupBy { it[3] }

    LazyColumn {
        grouped.forEach {
            stickyHeader {
                Text(
                    text = it.value[0],
                    style = MaterialTheme.typography.headlineMedium, 
                    color = MaterialTheme.colorScheme.primary,
                    modifier = Modifier.padding(16.dp)
                )
                LazyRow {
                    items(categories) { cat ->
                        BrowserItem(cat = cat, drawable = R.drawable.ic_launcher_foreground)
                    }
                }
            }
        }
    }
}

2.2.1 代码解释

• LazyRow: 这是水平滚动的核心组件,通过它实现了左右滑动效果。它类似于传统的 RecyclerView,但用起来要简单很多

• stickyHeader: 它可以让大家 Card: 包装分类项,提供了一个带有阴影、边框的卡片样式。

• Icon 和 Text: 使用这些组件来显示图标和文字,简单直观。轻松实现分组列表的标题部分,像音乐应用中的不同分类一样。

代码语言:java
复制
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BrowserItem(cat: String, drawable: Int) {
    Card(
        modifier = Modifier
            .padding(16.dp)
            .size(200.dp),
        border = BorderStroke(2.dp, color = MaterialTheme.colorScheme.onSurfaceVariant),
        colors = CardDefaults.cardColors(
            containerColor = MaterialTheme.colorScheme.surface,
            contentColor = MaterialTheme.colorScheme.onSurface
        ),
        shape = MaterialTheme.shapes.medium,
        elevation = CardDefaults.cardElevation(8.dp)
    ) {
        Column(
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally,
            modifier = Modifier.fillMaxSize()
        ) {
            Text(
                text = cat,
                style = MaterialTheme.typography.bodyMedium,
                color = MaterialTheme.colorScheme.onSurface
            )
            Spacer(modifier = Modifier.height(8.dp))
            Icon(
                painter = painterResource(id = drawable),
                contentDescription = cat,
                modifier = Modifier.size(64.dp),
                tint = MaterialTheme.colorScheme.primary
            )
        }
    }
}

2.2.2 测试UI

代码语言:javascript
复制
@Preview(showBackground = true,  widthDp = 700, heightDp = 1000)
@Composable
fun PreviewHomeScreen() {
    HomeScreen()
}

@Preview(showBackground = true)
@Composable
fun PreviewBrowserItem() {
    BrowserItem(cat = "Nim", drawable = R.drawable.ic_launcher_foreground)
}

2.3 轮播图实现-2

在 SubscriptionScreen页面中展示了实现简单轮播图。

代码语言:java
复制
@Composable
fun SubscriptionScreen() {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(
            text = "Nim订阅页面",
            style = MaterialTheme.typography.headlineMedium,
            color = MaterialTheme.colorScheme.primary
        )

        Spacer(modifier = Modifier.height(16.dp))

        // 轮播图的实现
        CarouselView(
            imageList = listOf(
                R.drawable.a,
                R.drawable.a,
                R.drawable.a,
                R.drawable.a,
                R.drawable.a
            )
        )
    }
}

@Composable
fun CarouselView(imageList: List<Int>) {
    LazyRow(
        modifier = Modifier
            .fillMaxWidth()
            .height(200.dp),
        horizontalArrangement = Arrangement.spacedBy(16.dp)
    ) {
        items(imageList) { imageResId ->
            CarouselItem(imageResId = imageResId)
        }
    }
}

@Composable
fun CarouselItem(imageResId: Int) {
    Image(
        painter = painterResource(id = imageResId),
        contentDescription = null,
        modifier = Modifier
            .size(150.dp)
            .padding(8.dp)
    )
}

2.3.1 测试UI

代码语言:java
复制
@Preview(showBackground = true, widthDp = 850)
@Composable
fun PreviewSubscriptionScreen() {
    SubscriptionScreen()
}

2.4 列表和弹窗实现

在MyScreen 页面,展示了如何实现带有点击事件的列表,在用户点击某个项目时弹出对话框(AlertDialog)。

代码语言:java
复制
@Composable
fun MyScreen() {
    var showDialog by remember { mutableStateOf(false) }
    var selectedItem by remember { mutableStateOf("") }

    LazyColumn(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        items(libraries) { lib ->
            LibItem(lib = lib, onClick = {
                selectedItem = lib.name
                showDialog = true
            })
        }
    }

    if (showDialog) {
        AlertDialog(
            onDismissRequest = { showDialog = false },
            confirmButton = {
                TextButton(onClick = { showDialog = false }) {
                    Text("确定")
                }
            },
            title = {
                Text(text = "未开发")
            },
            text = {
                Text(text = "你选择: $selectedItem")
            }
        )
    }
}

2.4.1 代码解释

• LazyColumn: 展示竖向的列表。

• AlertDialog: 通过 showDialog 这个布尔值来控制它的显示和关闭。当用户点击某个列表项时,触发弹窗。

代码语言:java
复制
@Composable
fun LibItem(lib: Lib, onClick: () -> Unit) {
    Column {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(vertical = 16.dp)
                .clickable { onClick() },
            horizontalArrangement = Arrangement.SpaceBetween
        ) {
            Text(text = lib.name)
            Icon(imageVector = Icons.Default.KeyboardArrowRight, contentDescription = "Arrow Right")
        }
        Divider(color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.2f))
    }
}

2.4.2 代码解释

• clickable: 用来处理用户点击事件,当用户点击某个项目时,通过 onClick 触发相应的逻辑。

• Row: 把文字和图标水平排列,在两端留有一定的间距,视觉上很整齐。

2.4.3 测试UI

代码语言:java
复制
@Preview(showBackground = true)
@Composable
fun PreviewMyScreen() {
    MyScreen()
}

2.5 视频演示

视频内容

三 总结

通过本次Demo,使用 Jetpack ComposeM3 实现了常见的轮播图、列表和弹窗功能,展示了如何高效构建现代化 UI 界面,希望这篇文章帮助大家更好理解 Compose 的强大。

未完待续,下一篇介绍如何使用原生 AndroidView 实现类似功能,敬请期待。

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


四、新增:2024/10/15-更新文章

近期我看了一篇更新轮播图组件的新闻,说JetpackComposeM3支持material3最新版本1.3.0,网址是https://m3.material.io/blog/material-3-compose-1-3

4.1 项目配置

代码语言:javascript
复制
implementation ("androidx.compose.material3:material3:1.3.0")

4.2 核心代码

代码语言:java
复制
@OptIn(ExperimentalMaterial3Api::class)
@Preview
@Composable
private fun CarouselExamples() {
    data class CarouselItem(
        val id: Int,
        @DrawableRes val imageResId: Int,
        val contentDescription: String
    )

    val items = remember {
        listOf(
            CarouselItem(0, R.drawable.nim, ""),
            CarouselItem(1, R.drawable.nim, ""),
            CarouselItem(2, R.drawable.nim, ""),
            CarouselItem(3, R.drawable.nim,""),
            CarouselItem(4, R.drawable.nim, ""),
        )
    }
    HorizontalUncontainedCarousel(
        state = rememberCarouselState { items.count() },
        modifier = Modifier.fillMaxWidth()
            .wrapContentHeight()
            .padding(top = 40.dp, bottom = 16.dp),
        itemWidth = 186.dp,
        itemSpacing = 8.dp,
        contentPadding = PaddingValues(start = 16.dp)
    ) { i ->
        val item = items[i]
        Image(
            modifier = Modifier.height(205.dp)
                .maskClip(MaterialTheme.shapes.extraLarge),
            painter = painterResource(id = item.imageResId),
            contentDescription = item.contentDescription,
            contentScale = ContentScale.Crop
        )
    }
}

4.3 视频演示

视频内容

4.4 轮播图加边框的代码

实现了轮播图添加边框,可以通过maskBorder修饰符可以使用以下方法为提供不同的形状maskClip

代码语言:java
复制
modifier = Modifier.height(205.dp)
                .maskClip(MaterialTheme.shapes.extraLarge)
                .maskBorder(BorderStroke(1.dp, MaterialTheme.colorScheme.secondary), MaterialTheme.shapes.extraLarge),

4.5 效果图

4.6 视频演示

视频内容

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、项目背景
  • 二、项目开发
    • 2.1 介绍轮播图(Carousel) UI
      • 2.2 轮播图实现
        • 2.2.1 代码解释
          • 2.2.2 测试UI
            • 2.3 轮播图实现-2
              • 2.3.1 测试UI
                • 2.4 列表和弹窗实现
                  • 2.4.1 代码解释
                    • 2.4.2 代码解释
                      • 2.4.3 测试UI
                        • 2.5 视频演示
                        • 三 总结
                        • 四、新增:2024/10/15-更新文章
                          • 4.1 项目配置
                            • 4.2 核心代码
                              • 4.3 视频演示
                                • 4.4 轮播图加边框的代码
                                  • 4.5 效果图
                                    • 4.6 视频演示
                                    领券
                                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档