Jetpack Compose 知识点整理2【个人用】

目录

一、常见布局

1.Row

[1.1 核心属性](#1.1 核心属性)

[1.2 子元素专属修饰符(RowScope内使用)](#1.2 子元素专属修饰符(RowScope内使用))

[1.2.1 权重分配 - weight()](#1.2.1 权重分配 - weight())

[1.2.2 对齐控制 - align()或者verticalAlignment](#1.2.2 对齐控制 - align()或者verticalAlignment)

[1.3 性能优化技巧](#1.3 性能优化技巧)

[1.3.1 避免深度嵌套](#1.3.1 避免深度嵌套)

[1.3.2 固定尺寸元素优先测量](#1.3.2 固定尺寸元素优先测量)

[1.4 高级用法示例](#1.4 高级用法示例)

2.Column

[2.1 核心属性](#2.1 核心属性)

[2.2 常见场景](#2.2 常见场景)

[2.2.1 表单布局](#2.2.1 表单布局)

[2.2.2 卡片列表](#2.2.2 卡片列表)

[2.2.3 混合对齐](#2.2.3 混合对齐)

[2.2.4 权重布局 (Modifier.weight)](#2.2.4 权重布局 (Modifier.weight))

[2.3 与 Row 的对比](#2.3 与 Row 的对比)

3.Box

[3.1 常见用法](#3.1 常见用法)

4.懒加载布局

[4.1 基础用法](#4.1 基础用法)

[4.1.1 LazyColumn竖向列表基础用法](#4.1.1 LazyColumn竖向列表基础用法)

[4.1.2 LazyRow横向列表用法](#4.1.2 LazyRow横向列表用法)

[4.1.3 LazyVerticalGrid网格列表基础用法](#4.1.3 LazyVerticalGrid网格列表基础用法)

[4.2 新闻列表案例](#4.2 新闻列表案例)

[4.2.1 简单新闻列表](#4.2.1 简单新闻列表)

[4.2.2 可变新闻列表](#4.2.2 可变新闻列表)

[4.2.3 多样式新闻列表](#4.2.3 多样式新闻列表)


一、常见布局

1.Row

Row 是 Compose 中最基础的布局组件之一,用于水平排列子元素。类似于LinearLayout中的horizontal效果。Row 作为 Compose 布局系统的核心组件,掌握后可以实现很多常见的UI需求,配合其他布局组件可构建任意复杂界面。

Kotlin 复制代码
Row {
    Text("Item 1")
    Text("Item 2")
    Text("Item 3")
}

默认行为:

  • 子元素从左到右顺序排列
  • 高度由最高子元素决定
  • 宽度包裹内容

1.1 核心属性

|-----------------------|------------------------|----------|--------------------------------------------------------|
| 属性 | 类型 | 说明 | 常用值示例 |
| modifier | Modifier | 基础修饰符 | .fillMaxWidth(),.padding(16.dp) |
| horizontalArrangement | Arrangement.Horizontal | 水平方向排列规则 | Start,Center,End,SpaceBetween ,SpaceAround,SpaceEvenly |
| verticalAlignment | Alignment.Vertical | 垂直方向对齐方式 | Top,CenterVertically,Bottom |

排列方式(horizontalArrangement)

|--------------|------------|--------------------------|
| 排列类型 | 效果图示 | 代码示例 |
| Start(默认) | 左对齐 | Arrangement.Start |
| End | 右对齐 | Arrangement.End |
| Center | 居中 | Arrangement.Center |
| SpaceBetween | 两端对齐 | Arrangement.SpaceBetween |
| SpaceAround | 元素周围等距 | Arrangement.SpaceAround |
| SpaceEvenly | 所有间距相等 | Arrangement.SpaceEvenly |

Kotlin 复制代码
// 两端对齐示例
Row(
    modifier = Modifier.fillMaxWidth(),
    horizontalArrangement = Arrangement.SpaceBetween
) {
    Text("Back")
    Text("Title")
    Text("Menu")
}

1.2 子元素专属修饰符(RowScope内使用)

在 Row 内部,子元素可使用下面这些特殊修饰符

1.2.1 权重分配 - weight()
Kotlin 复制代码
Row(Modifier.fillMaxWidth()) {
    Text("Left", Modifier.weight(1f))   //占1/3空间    weight只能在Row的内部被使用
    Text("Right", Modifier.weight(2f)) // 占2/3空间
}
1.2.2 对齐控制 - align()或者verticalAlignment
Kotlin 复制代码
Row(Modifier.height(100.dp).background(Color.Green),
    verticalAlignment = Alignment.CenterVertically ) {        //verticalAlignment可以控制子组件的竖直方向对齐方式 
    Text("Top", modifier = Modifier.align(Alignment.Bottom))    //如果子组件有设置align,会覆盖父组件的verticalAlignment效果
    Text("Center")
    Text("Bottom")
}

1.3 性能优化技巧

1.3.1 避免深度嵌套
Kotlin 复制代码
// 错误示范:三层嵌套Row
Row {
    Row {
        Row { /* ... */ }
    }
}

// 正确:使用单个Row+合理修饰符
Row(horizontalArrangement = Arrangement.SpaceBetween) {
    // 使用weight替代嵌套
}
1.3.2 固定尺寸元素优先测量
Kotlin 复制代码
Row {
    // 固定尺寸元素放前面
    Icon(..., Modifier.size(24.dp))
    // 动态尺寸元素放后面
    Text(..., Modifier.weight(1f))
}

1.4 高级用法示例

响应式排列:根据屏幕宽度来决定布局分布,比如宽度大于600dp的时候,表示是宽屏,在侧边额外增加一个侧边栏,提升用户体验

Kotlin 复制代码
val screenWidth = LocalConfiguration.current.screenWidthDp.dp

Row(Modifier.fillMaxWidth()) {
    if (screenWidth > 600.dp) {
        // 宽屏:显示侧边栏
        Sidebar(Modifier.width(200.dp))
    }
    MainContent(Modifier.weight(1f))
}

自定义分隔线:如果有分割线需求,可以使用Divider组件添加分割线

Kotlin 复制代码
Row {
    repeat(3) { index ->
        Text("Item $index")
        if (index < 2) {
            Divider(
                Modifier
                  .height(20.dp)//分割线的高度
                  .width(1.dp)//宽度
                  .background(Color.Gray)//颜色
            )
        }
    }
}

交互动画排列:点击按钮后,在row中添加新的组件,**Modifier.animateContentSize()**在内容大小发生变化时自动添加平滑的过渡动画效果。它特别适用于动态调整布局的场景(如展开/折叠内容、文本换行、列表项高度变化等)

Kotlin 复制代码
var expanded by remember { mutableStateOf(false) }

Row(Modifier.animateContentSize()) {
    Button({ expanded = !expanded }) {
        Text("点击")
    }
    if (expanded) {
        Text("老张", modifier = Modifier.padding(16.dp).background(Color.Red))
        Text("老孙", modifier = Modifier.padding(16.dp).background(Color.Yellow))
        Text("老李", modifier = Modifier.padding(16.dp).background(Color.Blue))
        Text("老王", modifier = Modifier.padding(16.dp).background(Color.Green))
    }
}

2.Column

类似于LinearLayout的vertical效果

Kotlin 复制代码
Column {
    Text("Item 1")
    Text("Item 2")
    Button(onClick = {}) { Text("Button") }
}

默认行为:

  • 子元素从上到下顺序排列
  • 宽度由最宽的子元素决定
  • 高度包裹内容

2.1 核心属性

|---------------------|----------------------------------------------------|
| 参数 | 作用 |
| modifier | 设置布局尺寸、边距等(如Modifier.fillMaxSize().padding(16.dp)) |
| verticalArrangement | 控制子组件的垂直分布方式(默认Arrangement.Top) |
| horizontalAlignment | 控制子组件的水平对齐方式(默认Alignment.Start) |

水平对齐(horizontalAlignment)

Kotlin 复制代码
Column(
    horizontalAlignment = Alignment.CenterHorizontally // 子组件水平居中
) {
    Text("Centered Text")
    Button(onClick = {}) { Text("Centered Button") }
}

可选值:

  • Alignment.Start(默认左对齐)
  • Alignment.CenterHorizontally 水平居中
  • Alignment.End(右对齐)

垂直分布 (verticalArrangement)

Kotlin 复制代码
Column(
    modifier = Modifier.height(200.dp),
    verticalArrangement = Arrangement.SpaceEvenly // 子组件均匀分布
) {
    Text("Top")
    Text("Middle")
    Text("Bottom")
}

常用值:

  • Arrangement.Top(默认顶部开始排列)
  • Arrangement.Center(整体垂直居中)
  • Arrangement.SpaceBetween(首尾贴边,中间均匀分布)
  • Arrangement.SpaceEvenly(完全均匀分布,包括首尾)

2.2 常见场景

2.2.1 表单布局
Kotlin 复制代码
Column(
    modifier = Modifier.padding(16.dp),
    verticalArrangement = Arrangement.spacedBy(8.dp) // 子组件间距 8.dp
) {
    Text("Username", style = MaterialTheme.typography.labelMedium)
    TextField(value = "", onValueChange = {})
    Text("Password", style = MaterialTheme.typography.labelMedium)
    TextField(value = "", onValueChange = {})
    Button(onClick = {}) { Text("Submit") }
}
2.2.2 卡片列表
Kotlin 复制代码
Column(
    modifier = Modifier.verticalScroll(rememberScrollState()) // 支持滚动
) {
    repeat(10) { index ->
        Card(
            modifier = Modifier
                .fillMaxWidth()
                .padding(8.dp)
        ) {
            Text("Item $index", Modifier.padding(16.dp))
        }
    }
}
2.2.3 混合对齐
Kotlin 复制代码
Column(
    modifier = Modifier.fillMaxWidth(),
    horizontalAlignment = Alignment.End, // 子组件默认右对齐
    verticalArrangement = Arrangement.spacedBy(16.dp)
) {
    Text("Right Aligned")
    Button(
        onClick = {},
        modifier = Modifier.align(Alignment.Start) // 单独左对齐
    ) { Text("Left Button") }
}
2.2.4 权重布局 (Modifier.weight)

效果:红色区域占 1/3 高度,蓝色区域占 2/3。

Kotlin 复制代码
Column(Modifier.height(200.dp)) {
    Box(
        modifier = Modifier
            .weight(1f) // 占据剩余空间的 1/3
            .background(Color.Red)
    )
    Box(
        modifier = Modifier
            .weight(2f) // 占据剩余空间的 2/3
            .background(Color.Blue)
    )
}

2.3 与 Row 的对比

|------|---------------------|-----------------------|
| 特性 | Column | Row |
| 排列方向 | 垂直(从上到下) | 水平(从左到右) |
| 对齐参数 | horizontalAlignment | verticalAlignment |
| 分布参数 | verticalArrangement | horizontalArrangement |
| 典型场景 | 表单、列表、卡片堆叠 | 导航栏、横向菜单、按钮组 |

3.Box

Box 是一个常用的布局组件,它允许您将多个子组件堆叠在一起,子组件默认会按照添加顺序堆叠。

3.1 常见用法

Kotlin 复制代码
//在这个例子中,两个 Text 组件会被堆叠在一起,后面的组件会覆盖在前面的组件之上。
Box {
    Text("这是底部的文本")
    Text("这是顶部的文本")
}

//在这个例子中,Image会被放在底下,Text在上面,并且在box中底部居中
Box {
    Image(
        painter = painterResource(R.drawable.background),
        contentDescription = "背景图片"
    )
    Text(
        text = "图片上的文字",
        color = Color.White,
        modifier = Modifier.align(Alignment.BottomCenter)
    )
}
Kotlin 复制代码
//内对齐
Box(
    contentAlignment = Alignment.Center,  // 内容居中对齐
    modifier = Modifier.size(200.dp).background(Color.LightGray)
) {
    Text("居中文本")
}

4.懒加载布局

LazyColumn 和 LazyRow 是专门用于高效显示大量数据的列表布局组件,它们通过 懒加载(只渲染可见项) 显著提升性能,类似于传统 Android 中的 RecyclerView。

4.1 基础用法

4.1.1 LazyColumn竖向列表基础用法
Kotlin 复制代码
val dataList = (1..100).toList()

LazyColumn(
    modifier = Modifier.fillMaxSize(),
    verticalAgangement = Arrangement.spacedBy(8.dp), // 项间距
    horizontalAlignment = Alignment.CenterHorizontally // 水平居中
) {
    item { Text("我是一个头部", textAlign = TextAlign.Center, modifier = Modifier.fillMaxWidth().background(Color.Green).padding(8.dp))} // 单个头部
    items(dataList) { item -> // 列表项
        Text("Item $item", modifier = Modifier.padding(8.dp))
        Divider(modifier = Modifier.fillMaxWidth().height(0.5.dp).background(Color.Gray))
    }
    item { Text("我是一个尾部",  textAlign = TextAlign.Center,modifier = Modifier.fillMaxWidth().background(Color.Green).padding(8.dp))} // 单个头部
}
4.1.2 LazyRow横向列表用法
Kotlin 复制代码
val dataList = (1..100).toList()

LazyRow(
    modifier = Modifier.fillMaxWidth(),
    horizontalArrangement =Arrangement.spacedBy(16.dp) // 水平居中
) {
    item { Text("我是一个头部", textAlign = TextAlign.Center, modifier = Modifier.fillMaxWidth().background(Color.Green).padding(8.dp))} // 单个头部
    items(dataList) { item -> // 列表项
        Text("Item $item", modifier = Modifier.padding(8.dp))
        Divider(modifier = Modifier.fillMaxWidth().height(0.5.dp).background(Color.Gray))
    }
    item { Text("我是一个尾部",  textAlign = TextAlign.Center,modifier = Modifier.fillMaxWidth().background(Color.Green).padding(8.dp))} // 单个头部
}
4.1.3 LazyVerticalGrid网格列表基础用法
Kotlin 复制代码
LazyVerticalGrid(
    columns = GridCells.Fixed(2), // 2列布局
    modifier = Modifier.fillMaxSize()//宽高最大
) {
    items(100) { index ->
        Card(//定义一个card布局组件,效果类似于cardView
            modifier = Modifier.padding(12.dp),//card的内边距
            elevation = CardDefaults.cardElevation(defaultElevation = 6.dp)//阴影效果尺寸
        ) {
            Text("Item $index", modifier = Modifier.padding(16.dp))
        }
    }
}

4.2 新闻列表案例

4.2.1 简单新闻列表
Kotlin 复制代码
package com.ls.mycomposeapplication

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Divider
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

class ArticleListActivity : ComponentActivity() {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            ArticleListScreen()
        }
    }

    @Composable
    fun ArticleListScreen() {
        // 列表区
        LazyColumn {
            items(
                items = items,
                //*以下情况强制需要key
                // 1、列表包含内部的状态(勾选框、输入框)2、列表动态修改(删除item、新增、排序) 3、添加了item动画
                //除此之外,要求自己必须加上key
                key = { it.title }//识别item的唯一值
            ) { article ->
                ArticleItem(article = article)
            }
        }
    }

    private fun createData(): List<Article> {
        return listOf(
            Article(
                title = "辽宁清原抽水蓄能电站最后一台定子吊装完成",
                author = "人民网-图片频道,供稿:人民资讯",
                picture = R.drawable.ic_article_1
            ),
            Article(
                title = "通行时间再缩短!广湛高铁佛山站建设正式启动",
                author = "人民网-广东频道,供稿:人民资讯",
                picture = R.drawable.ic_article_2
            ),
            Article(
                title = "19岁杭州帅小伙第一名,还有人抓到一只甲鱼!今早3000多人在钱塘江边,太欢乐了",
                author = "杭州网",
                picture = R.drawable.ic_article_3
            ),
            Article(
                title = "今日起"两江小渡"航线恢复正常运营",
                author = "上游新闻",
                picture = R.drawable.ic_article_4
            ),
            Article(
                title = "中国太保小排球夏令营在漳州火热启航",
                author = "国际时事讲解",
                picture = R.drawable.ic_article_5
            ),
            Article(
                title = "奋力推动民族地区高质量发展和现代化建设迈出新步伐",
                author = "当代先锋网",
                picture = R.drawable.ic_article_6
            ),
            Article(
                title = "相信青春的力量|写在我省2024年万名大学生志愿服务西部计划出征之际",
                author = "人民网-图片频道,供稿:人民资讯",
                picture = R.drawable.ic_article_7
            ),
            Article(
                title = "量身定制"海外订单" 贵州汽车制造开拓国际市场",
                author = "当代先锋网",
                picture = R.drawable.ic_article_8
            ),
            Article(
                title = "势不可挡......在这里,乡村振兴的新引擎正发出强劲动力",
                author = "鲁网",
                picture = R.drawable.ic_article_9
            ),
            Article(
                title = "菏泽职业学院召开2024届毕业生第二轮就业核查工作部署会",
                author = "大众报业·齐鲁壹点",
                picture = R.drawable.ic_article_10
            ),
            Article(
                title = "菏泽职业学院学前教育系(育中教育学院)斩获省级大赛一等奖",
                author = "西安快线",
                picture = R.drawable.ic_article_11
            ),
            Article(
                title = "菏泽职业学院一类教学大赛,二等奖+2!",
                author = "大众报业·齐鲁壹点",
                picture = R.drawable.ic_article_12
            ),
            Article(
                title = "中央气象台停止对"格美"编号 湖南辽宁吉林等地仍有强降雨",
                author = "国际时事讲解",
                picture = R.drawable.ic_article_13
            ),
            Article(
                title = "习水仙源镇:清凉山水引客来 消夏避暑人气足",
                author = "多彩贵州网",
                picture = R.drawable.ic_article_14
            ),
            Article(
                title = "习水县寨坝镇:清凉避暑地 康养第二乡",
                author = "多彩贵州网",
                picture = R.drawable.ic_article_15
            ),
            Article(
                title = "赤水市元厚镇:新品荔枝出山记",
                author = "人民网-图片频道,供稿:人民资讯",
                picture = R.drawable.ic_article_16
            ),
            Article(
                title = "习水三岔河镇小小错车道 畅通出行暖民心",
                author = "湖南日报",
                picture = R.drawable.ic_article_17
            ),
            Article(
                title = "习水土城镇社会实践活动丰富学生假期生活",
                author = "上海咨询",
                picture = R.drawable.ic_article_18
            ),
            Article(
                title = "赤水建强"小站点"释放乡村振兴新动能",
                author = "福建新闻网,供稿:人民资讯",
                picture = R.drawable.ic_article_19
            ),
            Article(
                title = "习水同民镇:火龙果喜丰收 果农笑开颜",
                author = "上游新闻,供稿:人民资讯",
                picture = R.drawable.ic_article_20
            )
        )
    }

    /**
     * item布局定义
     *
     */
    @Composable
    fun ArticleItem(article: Article) {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .background(Color.White)
                .padding(12.dp),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            // 图片
            Image(
                painter = painterResource(id = article.picture),
                contentDescription = null,
                modifier = Modifier
                    .size(100.dp, 70.dp)
                    .clip(RoundedCornerShape(4.dp)),
                contentScale = ContentScale.Crop
            )

            // 文字区域
            Column(
                modifier = Modifier
                    .padding(start = 8.dp)
                    .weight(1f)
            ) {
                // 标题(最大2行)
                Text(
                    text = article.title,
                    color = Color.Black,
                    fontSize = 18.sp,
                    maxLines = 2,
                    overflow = TextOverflow.Ellipsis,
                    modifier = Modifier.fillMaxWidth()
                )

                // 作者(底部对齐)
                Text(
                    text = article.author,
                    fontSize = 16.sp,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                    modifier = Modifier.fillMaxWidth()
                )
            }
        }

        // 分割线
        Divider(
            color = Color.LightGray,
            thickness = 1.dp,
            modifier = Modifier.padding(horizontal = 12.dp)
        )
    }
}
4.2.2 可变新闻列表

主要演示了item数据的变化,而导致的ui更新

Kotlin 复制代码
package com.ls.mycomposeapplication

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.Divider
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

class ArticleListActivity : ComponentActivity() {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            ArticleListScreen()
        }

    }

    @Preview
    @Composable
    fun ArticleListScreen() {
        var articles by remember { mutableStateOf(emptyList<Article>()) }
        val scrollState = rememberLazyListState()

        Column {
            // 操作按钮区
            Row(
                modifier = Modifier
                    .fillMaxWidth(),
                horizontalArrangement = Arrangement.SpaceEvenly
            ) {
                Button(onClick = { articles = createData() }) {
                    Text("加载数据")
                }
                Button(onClick = {
                    articles = articles.toMutableList().apply {
                        if (size > 1) {
                            val old = articles[1]
                            set(1, Article("我修改了第二条数据的标题", old.author, old.picture))
                        }
                    }
                }) {
                    Text("修改第二条")
                }
                Button(onClick = {
                    //articles.toMutableList().apply 临时将不可变列表转为可变列表并进行修改
                    articles = articles.toMutableList().apply {
                        if (isNotEmpty()) removeAt(0)

                    }
                }) {
                    Text("删除第一条")
                }
                Button(onClick = {
                    articles = articles.toMutableList().apply {
                        add(
                            1,
                            Article(
                                title = "习水同民镇:火龙果喜丰收 果农笑开颜" + 1,//+1是为了确保key不冲突
                                author = "上游新闻,供稿:人民资讯",
                                picture = R.drawable.ic_article_20
                            )
                        ) // 直接修改副本
                    }
                }) {
                    Text("插入数据")
                }
            }

            // 列表区
            LazyColumn(state = scrollState) {
                items(
                    items = articles,
                    //建议始终添加key,最佳性能 + 状态安全 + 正确动画
                    //通过 key 识别哪些项需要更新(避免不必要的重组),另外滚动时复用相同 key 的项,减少创建新实例的开销
                    //确保项内部状态(如输入框文字、复选框状态)在滚动时不会错乱
                    key = { it.title } // 使用数据自带的唯一值作为唯一键
                ) { article ->
                    ArticleItem(article = article)
                }
            }
        }
    }

    private fun createData(): List<Article> {
        return listOf(
            Article(
                title = "辽宁清原抽水蓄能电站最后一台定子吊装完成",
                author = "人民网-图片频道,供稿:人民资讯",
                picture = R.drawable.ic_article_1
            ),
            Article(
                title = "通行时间再缩短!广湛高铁佛山站建设正式启动",
                author = "人民网-广东频道,供稿:人民资讯",
                picture = R.drawable.ic_article_2
            ),
            Article(
                title = "19岁杭州帅小伙第一名,还有人抓到一只甲鱼!今早3000多人在钱塘江边,太欢乐了",
                author = "杭州网",
                picture = R.drawable.ic_article_3
            ),
            Article(
                title = "今日起"两江小渡"航线恢复正常运营",
                author = "上游新闻",
                picture = R.drawable.ic_article_4
            ),
            Article(
                title = "中国太保小排球夏令营在漳州火热启航",
                author = "国际时事讲解",
                picture = R.drawable.ic_article_5
            ),
            Article(
                title = "奋力推动民族地区高质量发展和现代化建设迈出新步伐",
                author = "当代先锋网",
                picture = R.drawable.ic_article_6
            ),
            Article(
                title = "相信青春的力量|写在我省2024年万名大学生志愿服务西部计划出征之际",
                author = "人民网-图片频道,供稿:人民资讯",
                picture = R.drawable.ic_article_7
            ),
            Article(
                title = "量身定制"海外订单" 贵州汽车制造开拓国际市场",
                author = "当代先锋网",
                picture = R.drawable.ic_article_8
            ),
            Article(
                title = "势不可挡......在这里,乡村振兴的新引擎正发出强劲动力",
                author = "鲁网",
                picture = R.drawable.ic_article_9
            ),
            Article(
                title = "菏泽职业学院召开2024届毕业生第二轮就业核查工作部署会",
                author = "大众报业·齐鲁壹点",
                picture = R.drawable.ic_article_10
            ),
            Article(
                title = "菏泽职业学院学前教育系(育中教育学院)斩获省级大赛一等奖",
                author = "西安快线",
                picture = R.drawable.ic_article_11
            ),
            Article(
                title = "菏泽职业学院一类教学大赛,二等奖+2!",
                author = "大众报业·齐鲁壹点",
                picture = R.drawable.ic_article_12
            ),
            Article(
                title = "中央气象台停止对"格美"编号 湖南辽宁吉林等地仍有强降雨",
                author = "国际时事讲解",
                picture = R.drawable.ic_article_13
            ),
            Article(
                title = "习水仙源镇:清凉山水引客来 消夏避暑人气足",
                author = "多彩贵州网",
                picture = R.drawable.ic_article_14
            ),
            Article(
                title = "习水县寨坝镇:清凉避暑地 康养第二乡",
                author = "多彩贵州网",
                picture = R.drawable.ic_article_15
            ),
            Article(
                title = "赤水市元厚镇:新品荔枝出山记",
                author = "人民网-图片频道,供稿:人民资讯",
                picture = R.drawable.ic_article_16
            ),
            Article(
                title = "习水三岔河镇小小错车道 畅通出行暖民心",
                author = "湖南日报",
                picture = R.drawable.ic_article_17
            ),
            Article(
                title = "习水土城镇社会实践活动丰富学生假期生活",
                author = "上海咨询",
                picture = R.drawable.ic_article_18
            ),
            Article(
                title = "赤水建强"小站点"释放乡村振兴新动能",
                author = "福建新闻网,供稿:人民资讯",
                picture = R.drawable.ic_article_19
            ),
            Article(
                title = "习水同民镇:火龙果喜丰收 果农笑开颜",
                author = "上游新闻,供稿:人民资讯",
                picture = R.drawable.ic_article_20
            )
        )
    }

    /**
     * item布局定义
     *
     */
    @Composable
    fun ArticleItem(article: Article) {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .background(Color.White)
                .padding(12.dp)
                .height(IntrinsicSize.Min),//按内容最小高度,目的是为了给row一个高度标准
            verticalAlignment = Alignment.CenterVertically,
        ) {
            // 图片
            Image(
                painter = painterResource(id = article.picture),
                contentDescription = null,
                modifier = Modifier
                    .size(100.dp, 70.dp)
                    .clip(RoundedCornerShape(4.dp)),
                contentScale = ContentScale.Crop
            )

            // 文字区域
            Column(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(start = 8.dp),
                verticalArrangement = Arrangement.SpaceBetween,
            ) {
                // 标题(最大2行)
                Text(
                    text = article.title,
                    color = Color.Black,
                    fontSize = 18.sp,
                    maxLines = 2,
                    overflow = TextOverflow.Ellipsis,
                )

                // 作者(底部对齐)
                Text(
                    text = article.author,
                    fontSize = 16.sp,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                    modifier = Modifier.fillMaxWidth()
                )
            }
        }

        // 分割线
        Divider(
            color = Color.LightGray,
            thickness = 1.dp,
            modifier = Modifier.padding(horizontal = 12.dp)
        )
    }
}
4.2.3 多样式新闻列表
  • Article数据类
Kotlin 复制代码
data class Article(
    val title: String,
    val author: String,
    val desc: String = "", // 默认空字符串
    val publish: Long = System.currentTimeMillis(),
    @DrawableRes var picture: Int = 0,
    @DrawableRes var picture2: Int = 0,
    @DrawableRes var picture3: Int = 0,
    val isAd: Boolean = false,
    @DrawableRes val adPicture: Int = 0
) {
    // 专门用于广告的辅助构造方法
    constructor(isAd: Boolean, @DrawableRes adPicture: Int) : this(
        title = if (isAd) "广告" else "",
        author = "",
        isAd = isAd,
        adPicture = adPicture
    )
}
  • Item的类型
Kotlin 复制代码
sealed class NewsItem {
    data class SingleImageArticle(val article: Article) : NewsItem()
    data class DoubleImageArticle(val article: Article) : NewsItem()
    data class TripleImageArticle(val article: Article) : NewsItem()
    data class AdItem(val article: Article) : NewsItem()
}
  • Activity代码
Kotlin 复制代码
package com.ls.mycomposeapplication

import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Divider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp

class ArticleListActivity : ComponentActivity() {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {

            val articles = remember { createArticleList() }

            ArticleMultiTypeList(
                articles = articles,
                onItemClick = { article ->
                    when {
                        article.isAd -> showToast("点击了广告")
                        article.picture2 != 0 && article.picture3 != 0 ->
                            showToast("三图新闻")

                        article.picture2 != 0 ->
                            showToast("双图新闻")

                        else ->
                            showToast("单图新闻")
                    }
                }
            )
        }

    }

    private fun showToast(msg: String) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
    }

    @Composable
    fun ArticleMultiTypeList(articles: List<Article>, onItemClick: (Article) -> Unit) {
        val newsItems = remember(articles) {
            articles.map { article ->
                when {
                    article.isAd -> NewsItem.AdItem(article)
                    article.picture != 0 && article.picture2 != 0 && article.picture3 != 0 ->
                        NewsItem.TripleImageArticle(article)

                    article.picture != 0 && article.picture2 != 0 ->
                        NewsItem.DoubleImageArticle(article)

                    else -> NewsItem.SingleImageArticle(article)
                }
            }
        }

        LazyColumn(
            modifier = Modifier.fillMaxSize(),
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            items(
                items = newsItems,
                key = {
                    when (it) {//此时的it指的是NewsItem类型,在when中,如果 is xx类型成立,那么就会被转为对应的子类型,
                        //此时it指的就是SingleImageArticle类型,可以直接访问成员变量 article
                        is NewsItem.SingleImageArticle -> "single_${it.article.title}"
                        is NewsItem.DoubleImageArticle -> "double_${it.article.title}"
                        is NewsItem.TripleImageArticle -> "triple_${it.article.title}"
                        is NewsItem.AdItem -> "ad_${it.article.adPicture}"
                    }
                }
            ) { item ->
                when (item) {
                    is NewsItem.SingleImageArticle ->
                        SingleImageItem(item.article, onItemClick)

                    is NewsItem.DoubleImageArticle ->
                        DoubleImageItem(item.article, onItemClick)

                    is NewsItem.TripleImageArticle ->
                        TripleImageItem(item.article, onItemClick)

                    is NewsItem.AdItem ->
                        AdItem(item.article, onItemClick)
                }
                Divider(color = Color.LightGray, thickness = 1.dp)
            }
        }
    }


    @Composable
    fun SingleImageItem(article: Article, onClick: (Article) -> Unit) {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .clickable { onClick(article) }
                .padding(12.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Image(
                painter = painterResource(article.picture),
                contentDescription = null,
                modifier = Modifier
                    .size(100.dp, 70.dp)
                    .clip(RoundedCornerShape(4.dp)),
                contentScale = ContentScale.Crop
            )

            Column(
                modifier = Modifier
                    .padding(start = 8.dp)
                    .weight(1f)
            ) {
                Text(
                    text = article.title,
                    style = MaterialTheme.typography.titleMedium,
                    maxLines = 2,
                    overflow = TextOverflow.Ellipsis
                )
                Spacer(modifier = Modifier.height(4.dp))
                Text(
                    text = article.author,
                    style = MaterialTheme.typography.bodySmall,
                    color = Color.Gray
                )
            }
        }
    }


    @Composable
    fun DoubleImageItem(article: Article, onClick: (Article) -> Unit) {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .clickable { onClick(article) }
                .padding(12.dp)
        ) {
            Text(
                text = article.title,
                style = MaterialTheme.typography.titleMedium,
                maxLines = 2,
                overflow = TextOverflow.Ellipsis
            )

            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(top = 8.dp),
                horizontalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                Image(
                    painter = painterResource(article.picture),
                    contentDescription = null,
                    modifier = Modifier
                        .weight(1f)
                        .aspectRatio(16f / 9f),
                    contentScale = ContentScale.Crop
                )
                Image(
                    painter = painterResource(article.picture2),
                    contentDescription = null,
                    modifier = Modifier
                        .weight(1f)
                        .aspectRatio(16f / 9f),
                    contentScale = ContentScale.Crop
                )
            }

            Text(
                text = article.author,
                modifier = Modifier.padding(top = 8.dp),
                style = MaterialTheme.typography.bodySmall,
                color = Color.Gray
            )
        }
    }

    @Composable
    fun TripleImageItem(article: Article, onClick: (Article) -> Unit) {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .clickable { onClick(article) }
                .padding(12.dp)
        ) {
            Text(
                text = article.title,
                style = MaterialTheme.typography.titleMedium,
                maxLines = 2,
                overflow = TextOverflow.Ellipsis
            )

            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(top = 8.dp),
                horizontalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                Image(
                    painter = painterResource(article.picture),
                    contentDescription = null,
                    modifier = Modifier
                        .weight(1f)
                        .aspectRatio(1f),
                    contentScale = ContentScale.Crop
                )
                Image(
                    painter = painterResource(article.picture2),
                    contentDescription = null,
                    modifier = Modifier
                        .weight(1f)
                        .aspectRatio(1f),
                    contentScale = ContentScale.Crop
                )
                Image(
                    painter = painterResource(article.picture3),
                    contentDescription = null,
                    modifier = Modifier
                        .weight(1f)
                        .aspectRatio(1f),
                    contentScale = ContentScale.Crop
                )
            }

            Text(
                text = article.author,
                modifier = Modifier.padding(top = 8.dp),
                style = MaterialTheme.typography.bodySmall,
                color = Color.Gray
            )
        }
    }

    @Composable
    fun AdItem(article: Article, onClick: (Article) -> Unit) {
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .clickable { onClick(article) }
        ) {
            Image(
                painter = painterResource(article.adPicture),
                contentDescription = null,
                modifier = Modifier
                    .fillMaxWidth()
                    .height(200.dp),
                contentScale = ContentScale.Crop
            )

            Text(
                text = "广告",
                modifier = Modifier
                    .align(Alignment.TopEnd)
                    .padding(8.dp)
                    .background(Color.Black.copy(alpha = 0.7f))
                    .padding(4.dp),
                color = Color.White,
                fontWeight = FontWeight.Bold
            )
        }
    }


    fun createArticleList(): List<Article> = listOf(
        Article(
            title = "辽宁清原抽水蓄能电站最后一台定子吊装完成",
            author = "人民网-图片频道,供稿:人民资讯",
            picture = R.drawable.ic_article_1
        ),
        Article(
            title = "通行时间再缩短!广湛高铁佛山站建设正式启动",
            author = "人民网-广东频道,供稿:人民资讯",
            picture = R.drawable.ic_article_2
        ),
        Article(
            title = "19岁杭州帅小伙第一名,还有人抓到一只甲鱼!今早3000多人在钱塘江边,太欢乐了",
            author = "杭州网",
            picture = R.drawable.ic_article_3
        ),
        Article(
            title = "今日起\"两江小渡\"航线恢复正常运营",
            author = "上游新闻",
            picture = R.drawable.ic_article_4
        ).apply {
            picture2 = R.drawable.ic_article_12
        },
        Article(
            title = "中国太保小排球夏令营在漳州火热启航",
            author = "国际时事讲解",
            picture = R.drawable.ic_article_5
        ),
        Article(isAd = true, adPicture = R.drawable.bg_ad1),
        Article(
            title = "奋力推动民族地区高质量发展和现代化建设迈出新步伐",
            author = "当代先锋网",
            picture = R.drawable.ic_article_6
        ),
        Article(
            title = "相信青春的力量|写在我省2024年万名大学生志愿服务西部计划出征之际",
            author = "人民网-图片频道,供稿:人民资讯",
            picture = R.drawable.ic_article_7
        ).apply {
            picture2 = R.drawable.ic_article_5
        },
        Article(
            title = "量身定制\"海外订单\" 贵州汽车制造开拓国际市场",
            author = "当代先锋网",
            picture = R.drawable.ic_article_8
        ),
        Article(
            title = "势不可挡......在这里,乡村振兴的新引擎正发出强劲动力",
            author = "鲁网",
            picture = R.drawable.ic_article_9
        ),
        Article(
            title = "菏泽职业学院召开2024届毕业生第二轮就业核查工作部署会",
            author = "大众报业·齐鲁壹点",
            picture = R.drawable.ic_article_10
        ),
        Article(isAd = true, adPicture = R.drawable.bg_ad2),
        Article(
            title = "菏泽职业学院学前教育系(育中教育学院)斩获省级大赛一等奖",
            author = "西安快线",
            picture = R.drawable.ic_article_11
        ),
        Article(
            title = "菏泽职业学院一类教学大赛,二等奖+2!",
            author = "大众报业·齐鲁壹点",
            picture = R.drawable.ic_article_12
        ).apply {
            picture2 = R.drawable.ic_article_3
            picture3 = R.drawable.ic_article_16
        },
        Article(
            title = "中央气象台停止对\"格美\"编号 湖南辽宁吉林等地仍有强降雨",
            author = "国际时事讲解",
            picture = R.drawable.ic_article_13
        ),
        Article(
            title = "习水仙源镇:清凉山水引客来 消夏避暑人气足",
            author = "多彩贵州网",
            picture = R.drawable.ic_article_14
        ),
        Article(
            title = "习水县寨坝镇:清凉避暑地 康养第二乡",
            author = "多彩贵州网",
            picture = R.drawable.ic_article_15
        ),
        Article(
            title = "赤水市元厚镇:新品荔枝出山记",
            author = "人民网-图片频道,供稿:人民资讯",
            picture = R.drawable.ic_article_16
        ),
        Article(
            title = "习水三岔河镇小小错车道 畅通出行暖民心",
            author = "湖南日报",
            picture = R.drawable.ic_article_17
        ),
        Article(
            title = "习水土城镇社会实践活动丰富学生假期生活",
            author = "上海咨询",
            picture = R.drawable.ic_article_18
        ),
        Article(
            title = "赤水建强\"小站点\"释放乡村振兴新动能",
            author = "福建新闻网,供稿:人民资讯",
            picture = R.drawable.ic_article_19
        ),
        Article(
            title = "习水同民镇:火龙果喜丰收 果农笑开颜",
            author = "上游新闻,供稿:人民资讯",
            picture = R.drawable.ic_article_20
        )
    )
}
相关推荐
cao23331 小时前
关于 x1 y1 等变量名冲突的指正(校对版)
笔记
是真的小外套2 小时前
2024年软考中级信息安全工程师|选择题考点+案例分析真题解析(含答案)
android·网络
dadaobusi2 小时前
学习:灵犀指令集
学习
Demons_kirit2 小时前
CTFHub 信息泄露通关笔记:Git泄露 Log - 教程
笔记·git·网络安全
xhyu613 小时前
【学习笔记】图像质量评估方法 (5.生成图像是否符合用户要求)
笔记·学习·计算机视觉
2601_961146204 小时前
实验室用等离子表面处理设备处理新能源汽车塑料件的一点记录
笔记·汽车·设备
知产xiao_xin4 小时前
专利主体及权利归属
经验分享·笔记·知识产权
用户2018792831674 小时前
一文讲透 Android Native Heap 监控原理:一间"只进不出"的仓库,和总部派来的侦探
android
学电子她就能回来吗4 小时前
LeetCode Hot 100|普通数组专题学习笔记(零基础版)
笔记·算法·leetcode