Jetpack Compose 中的基础知识

本文是根据官方文档学习 作笔记记录

目录

  • Composable functions (可组合函数)
  • Layouts(文本,cloumn,图片,布置布局)
  • Material Design (Color(颜色),Typography(排版),Shape(形状),启用深色主题)
  • Lists and animations(列表和动画)
  • 领会的一些使用技巧

Jetpack Compose 是 Google 推出的 用来构建 Android 用户界面的工具包,采用的是声明式的方法。(如果你接触过 Flutter ,会有似曾相识的感觉。)对于本文的学习,如果你有 Kotlin 的开发基础, 一点Android 应用开发的知识,会轻松一点。

Composable functions

Compose 可组合函数是 Jetpack Compose 的基本构建块,用于定义UI 组件。

下面是一个简单示例 Greeting widget ,接收 String 参数 并通过 Text widget 显示出来。

kotlin 复制代码
// ...
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState) 
        setContent {
            Greeting("AndroidDeveloper")
        }
    }
}

@Composable
fun Greeting(name: String) {
    Text("Hello $name!")
}

关于此函数,有几点需要注意。

  • @Composable 注解。这个注解告诉编译器,这个函数的目的是将数据转换为用户界面。
  • 带有此注解的函数也被称为可组合函数,简称可组合函数。这些函数是 Compose 中用户界面的构件。添加此注解非常简单快捷,可帮助您将用户界面组织成一个可重复使用的元素库
  • 此函数接收数据, 可组合函数可接收参数,用于界面描述。
  • 此函数不返回任何内容 (但它会返回 Unit ),声明式命名组件,用于描述屏幕状态而非构建界面widget。

在 Android Studio 预览你的函数

@Preview 注解 可帮助你实时预览可组合函数,无需构建应用程序并安装在Android 设备或者浏览器。 该注释必须用在不接受参数的可组合函数,因此无法直接预览 Greeting 的功能,需要创建一个 DefaultPreview ,传入参数去调用 Greeting

kotlin 复制代码
@Composable
fun Greeting(name: String) {
    Text("Hello $name!")
}

@Preview(showBackground = true,widthDp = 360, heightDp = 360)
@Composable
fun DefaultPreview() {
    Greeting(" Developer!")
}
  • @Preview 注解中各项配置可设置,供你预览效果。

Layouts

在绘制页面时,UI元素是分层的, 元素包裹在其他元素中,(各种Layout,View 的嵌套),而在Compose 中,我们可以通过其他组合函数调用可组合函数来构建UI层次结构。

到这里,我们已经知道 Compose 可组合函数 和 预览的用法了,接下来 是学会如何使用布局去完善效果。

这里我和官方文档一样 ,使用消息列表 这个样例来学习。

添加多个文本

kotlin 复制代码
class SecondActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MessageCard(Message("Android", "Jetpack Compose"))
        }
    }
}

data class Message(val author: String, val body: String)

@Composable
fun MessageCard(msg: Message) {
    Text(text = msg.author)
    Text(text = msg.body)
}

从上图效果,我们创建的两个 Text 元素,是会重叠在一起,原因是我们未提供有关如何排列文本元素的信息。

使用 Column

Column函数 可以垂直排列 其布局内元素。 你也可以使用 RowBox 去实现想要的效果。

kotlin 复制代码
 @Composable
fun MessageCard(msg: Message) {
    Column() {
        Text(text = msg.author)
        Text(text = msg.body)
    }
}

添加Image

kotlin 复制代码
@Composable
fun MessageCard(msg: Message) {
    Row() {
        Image(painter = painterResource(id = R.drawable.cat), contentDescription = "Contact profile picture")
        Column() {
            Text(text = msg.author)
            Text(text = msg.body)

        }
    }
}

预览效果

现在看到的效果, 图片太大了, 间距也没有。这时候就需要就需要 Modifier ,点进Row 的源码可以看到默认参数是有 Modifier ,它的用途类似 将Android Layout 中的配置属性,做了一个集合,详细的各位可以看源码 或者文档, 我这里就不细说了。

kotlin 复制代码
@Composable
fun MessageCard(msg: Message) {
    Row() {
        Image(
            painter = painterResource(id = R.drawable.cat),
            contentDescription = null,
            modifier = Modifier
                .size(40.dp)
                .clip(CircleShape)
        )
        Spacer(modifier = Modifier.width(8.dp))
        Column() {
            Text(text = msg.author)
            Spacer(modifier = Modifier.height(4.dp))
            Text(text = msg.body)
        }

    }
}

这个效果比之前的好点了, Modifier 可玩性很高,更多功能各位可以自己去发掘。

Material Design

Compose 当然也是支持 Material Design 原则的, 它许多页面元素都原生支持 Material Design ,这里我使用了 项目中创建的Material 主题 和 Surface 来修改了 MessageCard 的外观 。

Material Design 是围绕 ColorTypographyShape 这三大要素构建的。下面的代码将围绕这三大元素修改。

  • 预览效果 & 主题文件位置

Color

使用 MaterialTheme.colors ,可用封装在主题的颜色来设置效果。

kotlin 复制代码
@Composable
fun MessageCard(msg: Message) {
    Row() {
        Image(
            painter = painterResource(id = R.drawable.cat),
            contentDescription = null,
            modifier = Modifier
                .size(40.dp)
                .clip(CircleShape)
                **.border(1.5.dp, MaterialTheme.colors.secondary, CircleShape)**
        )
        Spacer(modifier = Modifier.width(8.dp))
        Column() {
            Text(text = msg.author, **color = MaterialTheme.colors.secondaryVariant**)
            Spacer(modifier = Modifier.height(4.dp))
            Text(text = msg.body)
        }

    }
}
  • 预览效果

Typography

MaterialTheme.typography.* 这里用在 text的 style 中

Shape

这块是我作为UI仔最喜欢的地方了,(整点花里胡哨的) 兄弟们,你看看这效果,就一句代码 !!就一句!! 不用写shape.xml , 不用盲猜了, 还能预览 !! 赶紧上号更新呀!

这里设置了shape 的大小(有三种尺寸选择,我们大部分的需求都能满足), 阴影加了1dp ,对了 ,各位发现没 ,直接是1.dp

kotlin 复制代码
@Composable
fun MessageCard(msg: Message) {
    Row() {
        Image(
            painter = painterResource(id = R.drawable.cat),
            contentDescription = null,
            modifier = Modifier
                .size(40.dp)
                .clip(CircleShape)
                .border(1.5.dp, MaterialTheme.colors.secondary, CircleShape)
        )
        Spacer(modifier = Modifier.width(8.dp))
        Column() {
            Text(
                text = msg.author,
                color = MaterialTheme.colors.secondary,
                style = MaterialTheme.typography.subtitle2
            )
            Spacer(modifier = Modifier.height(4.dp))
            **Surface(shape = MaterialTheme.shapes.medium, elevation = 1.dp)** {
                Text(text = msg.body,modifier = Modifier.padding(all = 4.dp) , style = MaterialTheme.typography.body2)
            }
        }

    }

深色主题

因为Jetpack Compose 默认支持 Material Design ,所以系统会自动适应深色背景

添加新的预览注解并启用夜间模式。

kotlin 复制代码
@Preview(name = "Light Mode")
@Preview(
    uiMode = Configuration.UI_MODE_NIGHT_YES,
    showBackground = true,
    name = "Dark Mode"
)
@Preview(showBackground = true)
@Composable
fun PreviewMessageCard() {
    MySootheTheme {
        Surface {
            MessageCard(
                msg = Message("Lexi", "Hey, Look at this cute cat, it's so so lovely!")
            )
        }
    }
}

这里浅色和深色主题的颜色选项是在 IDE 生成 的 Theme.kt 中定义的。

Lists and animations

来到我们常用的列表和动画了, 跟着官方文档学完后,我觉得这代码写起来真的变轻松了🥺 。

创建消息列表

这里的子项items 接收 传递 过来的参数list,lambda 省略了 遍历list这块代码 ,这里的message 是自定义命名的,LazyColumn 顾名思义只加载屏幕上显示的内容,对于长列表布局会更高效。

保存状态 & 添加动画

到这里,消息列表的雏形就有了 ,在这块内容要做的是把一些过长的内容收起来,加上动画效果,把跟踪消息是否展开储存为本地界面状态。 需要用到 **remember**mutableStateOf 函数 。

**remember** 可将本地状态存储在内存中,并把跟踪的值的变化传递给 mutableStateOf 。这个值的更新,系统会自动重新绘制使用此状态的可组合项(及其子项),这叫重组,可以看下链接的官方解释。

通过使用 Compose 的状态 API(如 remembermutableStateOf),系统会在状态发生任何变化时自动更新界面。

kotlin 复制代码
@Composable
fun MessageCard(msg: Message) {
    Row(modifier = Modifier.padding(all = 8.dp)) {
        Image(
            painter = painterResource(id = R.drawable.cat),
            contentDescription = null,
            modifier = Modifier
                .size(40.dp)
                .clip(CircleShape)
                .border(1.5.dp, MaterialTheme.colors.secondary, CircleShape)
        )
        Spacer(modifier = Modifier.width(8.dp))
        **var isExtended by remember { mutableStateOf(false) }**
        Column(**Modifier.clickable { isExtended = !isExtended }**) {
            Text(
                text = msg.author,
                color = MaterialTheme.colors.secondary,
                style = MaterialTheme.typography.subtitle2
            )
            Spacer(modifier = Modifier.height(4.dp))
            Surface(shape = MaterialTheme.shapes.medium, elevation = 1.dp) {
                Text(
                    text = msg.body,
                    modifier = Modifier.padding(all = 4.dp),
                    style = MaterialTheme.typography.body2,
                    **maxLines = if (isExtended) Int.MAX_VALUE else 1**
                )
            }
        }

    }
}
  • 预览效果

根据 isExpanded 跟踪的状态,修改展开和 收起来消息的背景颜色 (使用 MaterialTheme.colors 的两种颜色 )。 animateContentSize 消息容器的动画效果。

kotlin 复制代码
@Composable
fun MessageCard(msg: Message) {
    Row(modifier = Modifier.padding(all = 8.dp)) {
        Image(
            painter = painterResource(id = R.drawable.cat),
            contentDescription = null,
            modifier = Modifier
                .size(40.dp)
                .clip(CircleShape)
                .border(1.5.dp, MaterialTheme.colors.secondary, CircleShape)
        )
        Spacer(modifier = Modifier.width(8.dp))
        var isExpanded by remember { mutableStateOf(false) }
        v**al surfaceColor by animateColorAsState(
            if (isExpanded) MaterialTheme.colors.primary else MaterialTheme.colors.surface,
        )**
        Column(Modifier.clickable { isExpanded = !isExpanded }) {
            Text(
                text = msg.author,
                color = MaterialTheme.colors.secondary,
                style = MaterialTheme.typography.subtitle2
            )
            Spacer(modifier = Modifier.height(4.dp))
            Surface(shape = MaterialTheme.shapes.medium, **color = surfaceColor**, elevation = 1.dp) {
                Text(
                    text = msg.body,
                    modifier = Modifier.padding(all = 4.dp),
                    style = MaterialTheme.typography.body2,
                    maxLines = if (isExpanded) Int.MAX_VALUE else 1
                )
            }
        }

    }
}
  • 最终加上 背景色的动态效果

以下是您目前为止所学的内容,所有内容只需不到 100 行代码!:

  • 定义可组合函数
  • 在可组合项中添加不同的元素
  • 使用布局可组合项构建界面组件
  • 使用修饰符扩展可组合项 Modifiers
  • 创建高效列表
  • 跟踪状态以及修改状态
  • 在可组合项上添加用户互动
  • 在展开消息时显示动画效果

改进的技巧,发现了比我讲得好的博主,我这里就不写了,分享给大家。

改进Jetpack Compose 的 12 个使用技巧

相关推荐
一切皆是定数16 分钟前
Android车载——VehicleHal初始化(Android 11)
android·gitee
一切皆是定数18 分钟前
Android车载——VehicleHal运行流程(Android 11)
android
problc19 分钟前
Android 组件化利器:WMRouter 与 DRouter 的选择与实践
android·java
图王大胜1 小时前
Android SystemUI组件(11)SystemUIVisibility解读
android·framework·systemui·visibility
服装学院的IT男5 小时前
【Android 13源码分析】Activity生命周期之onCreate,onStart,onResume-2
android
Arms2065 小时前
android 全面屏最底部栏沉浸式
android
服装学院的IT男5 小时前
【Android 源码分析】Activity生命周期之onStop-1
android
ChinaDragonDreamer8 小时前
Kotlin:2.0.20 的新特性
android·开发语言·kotlin
网络研究院10 小时前
Android 安卓内存安全漏洞数量大幅下降的原因
android·安全·编程·安卓·内存·漏洞·技术
凉亭下10 小时前
android navigation 用法详细使用
android