setContent块定义了activity的布局,在此处我们添加了Text即“Hello World!”。
自定义可组合函数
如果需要将一个函数转换为Composable function,我们需要添加注解“@Composable”。
修改MainActivity:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MessageCard("Android")//使用我们自定义的Composable function
}
}
}
@Composable//添加注解,使该函数成为Composable function
fun MessageCard(name: String) {
Text(text = "Hello $name!")
}
在AS中预览Composable function
借助 @Preview注解,可以在AS中预览Composable function,无需安装到设备或虚拟器中。
唯一要求是该注解不能用于接收参数的函数中,因此在MainActivity新增如下函数:
@Preview
@Composable
fun PreviewMessageCard() {
MessageCard("Android")
}
在重新构建后,该函数没有被调用,应用本身不会改变,但是AS对于所有添加了 @Preview 注解的界面元素可以进行预览,点击如下两个按钮之一即可:
布局(Layout)
在此处我们实现一个简单的聊天界面,显示发送者和消息内容,点击消息时可缩放。
添加多个文本
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
//向Composable function中传入发送者名称和消息内容
MessageCard(Message("Android", "Jetpack Compose"))
}
}
}
//一个Message类,包含消息发送者和消息内容
data class Message(val author: String, val body: String)
@Composable
fun MessageCard(msg: Message) {
Text(text = msg.author)
Text(text = msg.body)
}
@Preview
@Composable
fun PreviewMessageCard() {
MessageCard(
msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!")
)
}
这段代码会在内容视图中创建两个文本元素。不过,由于未提供有关如何排列这两个文本元素的信息,因此它们会相互重叠,使文本无法阅读。
使用Column、Row、Box
Column,直译为“圆柱体、长列”。
使用该函数修改MessageCard,可以垂直排列元素,使其不再重叠文本。
@Composable
fun MessageCard(msg: Message) {
Column {
Text(text = msg.author)
Text(text = msg.body)
}
}
同样的,可以使用Row函数水平排列元素,而使用Box函数可以堆叠元素。
添加图片元素
使用Resource Manager从照片库中导入图片,修改MessageCard:
@Composable
fun MessageCard(msg: Message) {
//使用Row方法,水平排列图片和消息
Row {
Image(
painter = painterResource(R.drawable.profile_picture),
contentDescription = "Contact profile picture",
)
Column {
Text(text = msg.author)
Text(text = msg.body)
}
}
}
配置布局(Modifier)
使用修饰符(Modifier)实现。
Compose中的每一个组件都具有Modifier属性,通过他我们可以设置组件的大小、间距、外观,甚至添加互动事件,如点击、触摸事件。
@Composable
fun MessageCard(msg: Message) {
//在消息周围添加8dp的距离
Row(modifier = Modifier.padding(all = 8.dp)) {
Image(
painter = painterResource(R.drawable.profile_picture),
contentDescription = "Contact profile picture",
modifier = Modifier
//设置图片大小
.size(40.dp)
//将图片修剪为圆形
.clip(CircleShape)
)
//在图片和消息之间添加一个水平的空间(Spacer),间距为8dp
Spacer(modifier = Modifier.width(8.dp))
Column {
Text(text = msg.author)
// 在发送者和消息内容之间添加一个垂直的空间
Spacer(modifier = Modifier.height(4.dp))
Text(text = msg.body)
}
}
}
Material Design
Compose 旨在支持 Material Design 原则。它的许多界面元素都原生支持 Material Design。
使用
Jetpack Compose 原生提供 Material Design 3 及其界面元素的实现。我们使用 Material Design 样式改进MessageCard可组合项的外观。
在创建ComposeTutorial项目时,会同时创建一个名为“ComposeTutorialTheme”的Material主题,和一个来自Material Design 3的“Surface”。我们将用到这两位来封装MessageCard函数。
Material Design是围绕Color、Typography、Shape来构建的,我们将逐一添加这些元素。
修改MainActivity:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
//使用ComposeTutorialTheme和Surface封装MessageCard函数
ComposeTutorialTheme {
//将给定的组件或布局填满父容器的界面
Surface(modifier = Modifier.fillMaxSize()) {
MessageCard(Message("Android", "Jetpack Compose"))
}
}
}
}
@Preview
@Composable
fun PreviewMessageCard() {
//在@Preview中也要封装,沿用应用主题中定义的样式,保持统一
ComposeTutorialTheme {
Surface {
MessageCard(
msg = Message("Lexi", "Take a look at Jetpack Compose, it's great!")
}
}
}
}
颜色
@Composable
fun MessageCard(msg: Message) {
Row(modifier = Modifier.padding(all = 8.dp)) {
Image(
painter = painterResource(R.drawable.profile_picture),
contentDescription = null,
modifier = Modifier
.size(40.dp)
.clip(CircleShape)
//为图像增加一个圆框
.border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)
)
Spacer(modifier = Modifier.width(8.dp))
Column {
Text(
text = msg.author,
//通过MaterialTheme.colorScheme,使用已封装主题中的颜色设置样式
color = MaterialTheme.colorScheme.secondary)
Spacer(modifier = Modifier.height(4.dp))
Text(text = msg.body)
}
}
}
Typography(排版)
MaterialTheme 中提供了 Material Typography 样式,只需将其添加到 Text 可组合项中即可。
@Composable
fun MessageCard(msg: Message) {
Row(modifier = Modifier.padding(all = 8.dp)) {
Image(
painter = painterResource(R.drawable.profile_picture),
contentDescription = null,
modifier = Modifier
.size(40.dp)
.clip(CircleShape)
.border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)
)
Spacer(modifier = Modifier.width(8.dp))
Column {
Text(
text = msg.author,
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.titleSmall
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = msg.body,
style = MaterialTheme.typography.bodyMedium
)
}
}
}
Shape(形状)
@Composable
fun MessageCard(msg: Message) {
Row(modifier = Modifier.padding(all = 8.dp)) {
Image(
painter = painterResource(R.drawable.profile_picture),
contentDescription = null,
modifier = Modifier
.size(40.dp)
.clip(CircleShape)
.border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)
)
Spacer(modifier = Modifier.width(8.dp))
Column {
Text(
text = msg.author,
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.titleSmall
)
Spacer(modifier = Modifier.height(4.dp))
//将消息详情封装在Surface中,此时可自定义消息详情的大小、形状等布局
Surface(shape = MaterialTheme.shapes.medium, shadowElevation = 1.dp) {
Text(
text = msg.body,
modifier = Modifier.padding(all = 4.dp),
style = MaterialTheme.typography.bodyMedium
)
}
}
}
}
启用深色主题
又称夜间模式。由于支持Material Design,Jetpack Compose默认能够处理深色主题。
使用Material Design颜色、文本和背景时,系统会自动适应深色背景。
//可以在文件中以单独函数的形式创建多个预览,也可以向同一个函数中添加多个注解
@Preview(name = "Light Mode")
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_YES,
showBackground = true,
name = "Dark Mode"
)
@Composable
fun PreviewMessageCard() {
ComposeTutorialTheme {
Surface {
MessageCard(
msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!")
)
}
}
}
标题栏
右侧抽屉
MyModalNavigationDrawer(,,,)
fun MyModalNavigationDrawer(){
Box(,)
}
列表和动画
创建消息列表(LazyColumn、LazyRow)
LazyColumn、LazyRow是Compose常见的两个组件,他们的优点是可以延迟加载 。他们只会加载当前可见的列表项,并在滚动时动态回收其他项,这使得他们适用于展示大量数据或无限滚动的列表。
在使用中,会包含一个items子项。他接受LIst作为参数,并且其lambda会接收到参数。系统会针对提供的List的每个项调用此lambda。
@Composable
fun Conversation(messages: List<Message>) {
LazyColumn {
//items子项
items(messages) { message ->
MessageCard(message)
}
}
}
@Preview
@Composable
fun PreviewConversation() {
ComposeTutorialTheme {
Conversation(SampleData.conversationSample)
}
}
在展开消息时显示动画效果
为了存储某条消息是否已展开,我们使用remember和mutableStateOf函数。
可组合函数可以使用remember将本地状态存储到内存中,并跟踪传递给mutableStateOf的值的变化。而mutableStateOf函数可以在可组合函数内部创建一个可变的状态,并将其与UI组件进行绑定。当状态值发生变化时,Compose会自动重绘相关的组件。
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposeTutorialTheme {
Conversation(SampleData.conversationSample)
}
}
}
}
@Composable
fun MessageCard(msg: Message) {
Row(modifier = Modifier.padding(all = 8.dp)) {
Image(
painter = painterResource(R.drawable.profile_picture),
contentDescription = null,
modifier = Modifier
.size(40.dp)
.clip(CircleShape)
.border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)
)
Spacer(modifier = Modifier.width(8.dp))
// 在此变量中,跟踪当前消息是否展开
var isExpanded by remember { mutableStateOf(false) }
// 当点击该消息时,改变展开状态
Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) {
Text(
text = msg.author,
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.titleSmall
)
Spacer(modifier = Modifier.height(4.dp))
Surface(
shape = MaterialTheme.shapes.medium,
shadowElevation = 1.dp,
) {
Text(
text = msg.body,
modifier = Modifier.padding(all = 4.dp),
// 若展开,全部显示;不展开,最大显示一行
maxLines = if (isExpanded) Int.MAX_VALUE else 1,
style = MaterialTheme.typography.bodyMedium
)
}
}
}
}
注:需要添加以下导入内容才能正确使用 Kotlin 的委托属性语法(
by关键字):import androidx.compose.runtime.getValueimport androidx.compose.runtime.setValue 使用by关键字是避免每次都访问value属性的好方法。同时需要注意的是,我们应该**只在可组合函数的作用域之外改变状态**。这是因为可组合项可以频繁运行、且以任何顺序执行。此处我们可以在clickable中修改isExpanded的值,是因为clickable不是可组合函数。
除了remember关键字,我们还可以使用rememberSaveable ,它与前者类似,但存储的值可以在重新创建activity和进程后保存下来。需要注意的是,rememberSaveable适用于UI状态,如购物车的商品数量或选定的标签页,但不适用于过渡动画状态等。
同时我们可以加入颜色,在消息缩放时改变消息的颜色。但不能只是简单的改变消息的背景颜色,我们应当加入动画,使得变化时逐步更改。
相同的,在点击缩放时,我们也可以加上动画,使得缩放更加顺滑。
@Composable
fun MessageCard(msg: Message) {
Row(modifier = Modifier.padding(all = 8.dp)) {
Image(
painter = painterResource(R.drawable.profile_picture),
contentDescription = null,
modifier = Modifier
.size(40.dp)
.clip(CircleShape)
.border(1.5.dp, MaterialTheme.colorScheme.secondary, CircleShape)
)
Spacer(modifier = Modifier.width(8.dp))
var isExpanded by remember { mutableStateOf(false) }
// 该变量会逐步更新颜色,animateColorAsState函数实现颜色之间的过渡动画效果
val surfaceColor by animateColorAsState(
if (isExpanded) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surface,
)
Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) {
Text(
text = msg.author,
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.titleSmall
)
Spacer(modifier = Modifier.height(4.dp))
Surface(
shape = MaterialTheme.shapes.medium,
shadowElevation = 1.dp,
color = surfaceColor,
//加入animateContentSize,给缩放加入动画,更加顺滑
modifier = Modifier.animateContentSize().padding(1.dp)
) {
Text(
text = msg.body,
modifier = Modifier.padding(all = 4.dp),
maxLines = if (isExpanded) Int.MAX_VALUE else 1,
style = MaterialTheme.typography.bodyMedium
)
}
}
}
}
// ...**import androidx.compose.ui.tooling.preview.Preview**@Composablefun MessageCard(name: String) { Text(text = "Hello $name!")}**@Preview@Composablefun PreviewMessageCard() { MessageCard("Android")}**
隐藏预览
第 2 课:布局
界面元素采用多层次结构,元素中又包含其他元素。在 Compose 中,您可以通过从可组合函数中调用其他可组合函数来构建界面层次结构。
添加多个文本
到目前为止,您已经构建了第一个可组合函数和预览!为探索更多 Jetpack Compose 功能,您将构建一个简单的消息界面,界面上显示可以展开且具有动画效果的消息列表。
首先,通过显示消息发送者和消息内容,使消息可组合项更丰富。您需要先将可组合参数更改为接受 Message 对象(而非 String),然后在 MessageCard 可组合项中添加另一个 Text 可组合项。请务必同时更新预览。
这段代码会在内容视图中创建两个文本元素。不过,由于您未提供有关如何排列这两个文本元素的信息,因此它们会相互重叠,使文本无法阅读。
使用 Column
Column 函数可让您垂直排列元素。向 MessageCard 函数中添加一个 Column。 您可以使用 Row 水平排列各项,并使用 Box 堆叠元素。
添加图片元素
下面我们来添加消息发送者的个人资料照片,以丰富消息卡片。使用 Resource Manager 从照片库中导入图片,或使用这张图片 。添加一个 Row 可组合项,以实现良好的设计结构,并向该可组合项中添加一个 Image 可组合项。
配置布局
您的消息布局拥有良好的结构,但其元素的间距不合理,并且图片过大!为了装饰或配置可组合项,Compose 使用了* 修饰符*。通过修饰符,您可以更改可组合项的大小、布局、外观,还可以添加高级互动,例如使元素可点击。您可以将这些修饰符链接起来,以创建更丰富的可组合项。您将使用其中一些修饰符来改进布局。
// ...
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
@Composable
fun MessageCard(msg: Message) {
// Add padding around our message
Row(modifier = Modifier.padding(all = 8.dp)) {
Image(
painter = painterResource(R.drawable.profile_picture),
contentDescription = "Contact profile picture",
modifier = Modifier
// Set image size to 40 dp
.size(40.dp)
// Clip image to be shaped as a circle
.clip(CircleShape)
)
// Add a horizontal space between the image and the column
Spacer(modifier = Modifier.width(8.dp))
Column {
Text(text = msg.author)
// Add a vertical space between the author and message texts
Spacer(modifier = Modifier.height(4.dp))
Text(text = msg.body)
}
}
}
隐藏预览
第 3 课:Material Design
Compose 旨在支持 Material Design 原则。它的许多界面元素都原生支持 Material Design。在本课中,您将使用 Material Design widget 来设置应用的样式。
使用 Material Design
您的消息设计现在已有布局,但看上去还不是特别理想。
Jetpack Compose 原生提供 Material Design 3 及其界面元素的实现。您将使用 Material Design 样式改进 MessageCard 可组合项的外观。
首先,使用在您的项目中创建的 Material 主题 ComposeTutorialTheme 和 Surface 来封装 MessageCard 函数。 在 @Preview 和 setContent 函数中都需要执行此操作。这样一来,可组合项即可沿用应用主题中定义的样式,从而在整个应用中确保一致性。
Material Design 是围绕 Color、Typography、Shape 这三大要素构建的。您将逐一添加这些要素。
注意:Empty Compose Activity 模板会为您的项目生成默认主题,使您能够自定义 MaterialTheme。 如果您为项目指定的名称不是 ComposeTutorial,可以在 ui.theme 子软件包的 Theme.kt 文件中找到您的自定义主题。
颜色
通过 MaterialTheme.colorScheme,使用已封装主题中的颜色来设置样式。您可以在需要颜色的任何位置使用主题中的这些值。此示例使用动态主题颜色(由设备偏好设置定义)。 如需更改此设置,您可以在 MaterialTheme.kt 文件中将 dynamicColor 设为 false。
设置标题样式,并为图片添加边框:
Typography(排版)
MaterialTheme 中提供了 Material Typography 样式,只需将其添加到 Text 可组合项中即可。
Shape(形状)
通过 Shape ,我们可以添加最后的“点睛之笔”。首先,将消息正文封装在 Surface 可组合项中。这样即可自定义消息正文的形状和高度。此外,还要为消息添加内边距,以改进布局。
启用深色主题
您可以启用深色主题 (或夜间模式),以避免显示屏过亮(尤其是在夜间),或者只是节省设备电量。由于支持 Material Design,Jetpack Compose 默认能够处理深色主题。使用 Material Design 颜色、文本和背景时,系统会自动适应深色背景。
您可以在文件中以单独函数的形式创建多个预览,也可以向同一个函数中添加多个注解。
添加新的预览注解并启用夜间模式。
浅色和深色主题的颜色选项是在由 IDE 生成的 Theme.kt 文件中定义的。
到目前为止,您已创建了一个消息界面元素,它会以不同样式显示一张图片和两项文本,并且在浅色和深色主题下都有良好的视觉效果!
显示浅色和深色主题可组合项的预览。
第 4 课:列表和动画
列表和动画在应用内随处可见。在本课中,您将学习如何利用 Compose 轻松创建列表并添加有趣的动画效果。
创建消息列表
只包含一条消息的聊天略显孤单,因此我们将更改对话,使其包含多条消息。您需要创建一个可显示多条消息的 Conversation 函数。对于此用例,请使用 Compose 的 LazyColumn 和 LazyRow 。这些可组合项只会呈现屏幕上显示的元素,因此,对于较长的列表,使用它们会非常高效。
在此代码段中,您可以看到 LazyColumn 包含一个 items 子项。它接受 List 作为参数,并且其 lambda 会收到我们命名为 message 的参数(可以随意为其命名),该参数是 Message 的实例。简而言之,系统会针对提供的 List 的每个项调用此 lambda。将示例数据集 复制到您的项目中,以便快速引导对话。
在展开消息时显示动画效果
对话变得更加有趣了。是时候添加动画效果了!您将添加展开消息以显示更多内容的功能,同时为内容大小和背景颜色添加动画效果。为了存储此本地界面状态,您需要跟踪消息是否已展开。为了跟踪这种状态变化,您必须使用 remember 和 mutableStateOf 函数。
可组合函数可以使用 remember 将本地状态存储在内存中,并跟踪传递给 mutableStateOf 的值的变化。该值更新时,系统会自动重新绘制使用此状态的可组合项(及其子项)。这称为重组。
通过使用 Compose 的状态 API(如 remember 和 mutableStateOf),系统会在状态发生任何变化时自动更新界面。
注意:您需要添加以下导入内容才能正确使用 Kotlin 的委托属性语法(by 关键字)。按 Alt+Enter 或 Option+Enter 即可添加这些内容。 import androidx.compose.runtime.getValue import androidx.compose.runtime.setValue
现在,您可以根据点击消息时消息的 isExpanded 状态,更改消息内容的背景颜色。您将使用 clickable 修饰符来处理可组合项上的点击事件。您会为背景颜色添加动画效果,使其值逐步从 MaterialTheme.colorScheme.surface 更改为 MaterialTheme.colorScheme.primary(反之亦然),而不只是切换 Surface 的背景颜色。为此,您将使用 animateColorAsState 函数。最后,您将使用 animateContentSize 修饰符顺畅地为消息容器大小添加动画效果:
// ...
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
@Composable
fun Conversation(messages: List<Message>) {
LazyColumn {
items(messages) { message ->
MessageCard(message)
}
}
}
@Preview
@Composable
fun PreviewConversation() {
ComposeTutorialTheme
Conversation(SampleData.conversationSample)
}
}
- *
后续步骤
恭喜,您已完成 Compose 教程!您已高效地构建了一个简单的聊天界面,该界面显示包含图片和文字的可展开动画消息列表,使用 Material Design 原则设计,添加了深色主题且具有预览功能,所有内容只需不到 100 行代码!
以下是您目前为止所学的内容:
- 定义可组合函数
- 在可组合项中添加不同的元素
- 使用布局可组合项构建界面组件
- 使用修饰符扩展可组合项
- 创建高效列表
- 跟踪状态以及修改状态
- 在可组合项上添加用户互动
- 在展开消息时显示动画效果
如果您想深入了解其中的一些步骤,请浏览以下资源。
Jetpack Compose中的LaunchedEffect与rememberCoroutineScope
深入了解Compose副作用API LaunchedEffect和rememberCoroutineScope。 探索使用LaunchedEffect和rememberCoroutineScope的区别和使用场景。
什么是副作用? 副作用是指在可组合函数范围之外发生的任何事情,最终会影响可组合函数,可能是一些状态的改变或在用户界面上发生的与可组合有关的用户操作。这两个API都是为了在受控环境中处理这些影响而构建的。
首先,让我们详细了解LaunchedEffect。
LaunchedEffect副作用API LaunchedEffect是一个可组合函数,只能从另一个可组合函数中执行。LaunchedEffect至少需要一个参数和一个挂起函数。它通过在容器可组合的范围内启动一个协程来执行该挂起函数。当第一次进入组合时,LaunchedEffect会立即执行该挂起函数,以及当其传递的变量之一的值发生改变时。当LaunchedEffect必须执行一个新的挂起函数以处理副作用时,它会取消先前正在运行的协程,并使用新的挂起函数启动一个新的协程。当离开组合本身时,LaunchedEffect也会取消已启动的协程。协程始终在容器可组合函数的范围内启动。
LaunchedEffect与rememberCoroutineScope的主要区别在于它们的使用场景和功能。
-
LaunchedEffect:(类似vue 的watch? Compute?)
-
LaunchedEffect是一个可组合函数,它允许你在满足特定条件时执行一些副作用操作,如更新UI或执行其他挂起函数。当提供的key(如Unit或其他任何不可变对象)发生变化时,LaunchedEffect会重新计算其block,并且如果之前的LaunchedEffect实例还在运行,则会取消之前的实例。这确保了只有当前的LaunchedEffect实例在运行,避免了资源的浪费12。
-
LaunchedEffect特别适用于那些需要根据某些状态变化触发副作用的情况,例如动画、网络请求等。当状态变化时,可以重新启动或取消之前的副作用操作3。
LaunchedEffect(pagerState.currentPage == index) { color.animateTo( if (pagerState.currentPage == index) { Color.Cyan } else { Color(0xFFDDDDDD) } ) }数据变更时,需要执行一些其他动作
@Composable fun WatchExample(data: SomeDataType) { // 每次 data 改变时,都会执行一次副作用 LaunchedEffect(data) { // 这里放置你想要执行的副作用代码,比如发送网络请求等 println("Data changed to: $data") } // 组件的其余部分... }
-
-
rememberCoroutineScope:
-
rememberCoroutineScope返回一个协程作用域,这个作用域可以在非可组合函数中使用。这意味着你可以在可组合函数外部启动协程,并且这些协程在组合被销毁时会自动取消,这对于管理生命周期和避免资源泄漏非常有用23。
-
使用rememberCoroutineScope可以在组合外部管理协程的生命周期,这对于需要在用户交互或其他事件发生时手动控制协程的开始和结束非常有用23。
-
总的来说,LaunchedEffect更适合用于在状态变化时触发副作用,而rememberCoroutineScope更适合用于在可组合函数外部管理协程的生命周期和执行需要手动控制的长时间运行任务。
@Composable
fun OutlinedBtn() {
//compose作用区域
//协程scope创建方式一:
LaunchedEffect(key1 = Unit, block = {
delay(1000)
})
//协程scope创建方式二:
val scope = rememberCoroutineScope()
OutlinedButton(onClick = {
//非compose区域
scope.launch {
delay(2000)
}
}) {
Text(text = "button")
}
}
Modifier 详解
modifier = Modifier
// .fillMaxSize()//横向 纵向 都铺满,设置了fillMaxSize就不需要设置fillMaxHeight和fillMaxWidth了
// .fillMaxHeight()//fillMaxHeight纵向铺满
.fillMaxWidth()//fillMaxWidth()横向铺满 match
.padding(8.dp)//外边距 vertical = 8.dp 上下有8dp的边距; horizontal = 8.dp 水平有8dp的边距
.padding(8.dp)//内边距 padding(8.dp)=.padding(8.dp,8.dp,8.dp,8.dp)左上右下都有8dp的边距
// .width(100.dp)//宽100dp
// .height(100.dp)//高100dp
.size(100.dp)//宽高 100dp
// .widthIn(min: Dp = Dp.Unspecified, max: Dp = Dp.Unspecified)//设置自身的最小和最大宽度(当子级元素超过自身时,子级元素超出部分依旧可见);
.background(Color.Green)//背景颜色
.border(1.dp, Color.Gray, shape = RoundedCornerShape(20.dp))//边框
- fillMaxSize 设置布局纵向横向都铺满
- fillMaxHeight 设置布局铺满纵向
- fillMaxWidth 设置布局铺满横向,这三个属性再使用了fillMaxSize 就没必要在设置下面两个了
- padding 设置边距,方向由左上右下设置,添加了vertical就是设置垂直的上下边距,horizontal设置了水平的左右边距。这里注意写了两个padding,第一个是外边距,第二个是内边距,外边距最好是放在Modifier的第一个元素。
- width 设置元素的宽
- height 设置元素的高
- size 设置元素大小,只有一个值时宽高都是一个值,.size(100.dp,200.dp)两个值前者是宽,后者是高
- widthIn 设置自身的最小和最大宽度(当子级元素超过自身时,子级元素超出部分依旧可见)
- background 设置元素的背景颜色
- border 设置边框,参数值:边框大小,边框颜色,shape