Compose基础入门
本文链接:https://blog.csdn.net/feather_wch/article/details/132139415
Compose项目配置开关
文章目录
app的build.gradle
android {
buildFeatures {
compose true // compose
}
composeOptions {
kotlinCompilerExtensionVersion '1.3.2' //编译时注解
}
}
dependencies {
// Compose相关
implementation 'androidx.activity:activity-compose:1.5.1'
implementation platform('androidx.compose:compose-bom:2022.10.00')
implementation 'androidx.compose.ui:ui'
implementation 'androidx.compose.ui:ui-graphics'
implementation 'androidx.compose.ui:ui-tooling-preview'
implementation 'androidx.compose.material3:material3'
implementation 'androidx.compose.material3:material3'
androidTestImplementation platform('androidx.compose:compose-bom:2022.10.00')
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
debugImplementation 'androidx.compose.ui:ui-tooling'
debugImplementation 'androidx.compose.ui:ui-test-manifest'
}
ComponentActivity中通过setContent方法达到以前setContentView的效果
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
// xxx
}
}
}
//
androidx.activity:activity-compose:1.5.1@aar
--ComponentActivity.kt
->ComponentActivity.setContent
Compose是什么?
1、为什么要用Compose?
- 声明式的UI框架
- 组合替换继承
2、为什么使用组合?
- 组合获得布局能力
- 粒度更细,更灵活
- 可以解决Java中单个父类的限制
3、Compose和View、ViewGroup的区别:
- Compose不存在多层绘制问题
4、Compose是如何实现的?
- 会形成ComposeUiNode和LayoutNode等各种节点
- text等微件对应于LayoutNode和Node组成树形结构
5、还需要Fragment吗?
不需要了,单个Activity可以搞定一切
6、微件相对无状态,不再提供getter和setter方法
State状态管理
1、remember和mutableStateOf
- 数据驱动ui
- 数据就需要有状态 => MutableStateOf
2、为什么需要remember+mutableStateOf(“”) 才会改变输入框的数据?
- 一起管理状态
mutableStateOf
是 Compose 中的一个函数,用于创建可变的状态。它接受一个初始值,并返回一个包装了该值的MutableState
对象。MutableState
对象可以在 Composable 函数中读取和更改,而且当其值发生变化时,Compose 会自动进行重新绘制。remember
是 Compose 中的一个函数,用于在 Composable 函数中记住一个值。它类似于常规 Android 中的savedInstanceState
,但它是为 Compose 中的状态管理而设计的。
3、写一个复选框
@Composable
fun MyCheckBox(){
var checked by remember{
mutableStateOf(false)
}
Checkbox(checked = checked, onCheckedChange = {
checked = it
})
}
3、remember内部是cache,get/put,相当于hashmap
实时预览 动画执行
Preview预览:
@Preview(showBackground = true, showSystemUi = true)
Compose和View/ViewGroup的关联😁
setContentView的原理是什么?
- 从DecorView中获取到ContentView,并设置进去
- DecorView由ContentView和TitleView组成
Compose中的contentview
- contentview就是ComposeView,内部会加载我们实现的部分AndoridComposeView(多套了一层壳)
- 根节点是layoutnode,其他微件都是该树的节点
- compose是国中国,有自己的绘制流程
LazyColumn和RecyclerView区别
-
RV从缓存拿数据可以不create view,直接bind view
-
LazyColumn:状态管理,每次都会新建,走一遍流程。会根据当前状态去描绘UI
-
不再需要适配器:LazyColumn
改属性,改xx
compose搭建app就一个activity结构最好。androudcomposeview就一个。
Box 帧布局 FrameLayout
内置函数
remmember
属性
所有属性都会转为xxxModify
Modify
// SizeModifier = Modifier.size(10.dp, 10.dp)
// 每个Text、Image都会转为 一个LayoutNode
// 链式加入到
SizeModifier = Modifier.size(10.dp, 10.dp)
SizeModifier :不是单纯的属性,会定义测量方法
MeasureScope.measure 有一个测量方法,原来部分功能转到了属性上
BackgroundModifier::ContentDrawScope.draw() // UI绘制操作
Modifier.size(100.dp, 100.dp)
.background(Blue)
.size(10.dp, 10.dp)
.background(Color.Magenta)
// size第一个才会生效
// color按顺序生效
// padding按顺序生效
Modifier.clip 在原有Shape上剪切
GraphicLayerModifier
圆形
Modifier.size(100.dp, 100.dp)
.clip(CircleShape)
.background(Color.Magenta)
// 需要先圆形,再赋值背景色,才能看出圆形背景
Border怎么生效?默认矩形,clip之后怎么办?
border(2.dp, RED, CircleShape)要加上Shape
Outline.Rectangle
Outline.Rounded
Outline.Generic(path)
Scaffold 脚手架
topBar
bottomBar
floatingActionButton
drawerContent
content:Scaffold是一个Material,包裹在content之上的
Compose控件大全
在Android Jetpack Compose中,有许多不同的控件可以用于构建用户界面。下面列举了一些常用的Compose控件:
- Text:用于显示文本内容。
- Button:用于创建按钮。
- TextField:用于接收用户的文本输入。
- Image:用于显示图像。
- Checkbox:用于创建复选框。
- RadioGroup:用于创建单选按钮组。
- Switch:用于创建开关。
- Slider:用于创建滑块。
- ProgressBar:用于显示进度条。
- FloatingActionButton:用于创建浮动操作按钮。
- Card:用于创建卡片式布局。
- Row:用于水平排列子组件。
- Column:用于垂直排列子组件。
- Box:用于自定义布局和定位子组件。
- Spacer:用于创建空白间隔。
- Divider:用于创建分割线。
- Scaffold:用于创建基本的应用程序布局。
- TopAppBar:用于创建应用栏。
- BottomAppBar:用于创建底部应用栏。
- Drawer:用于创建侧边栏。
不常见的控件
当谈到不常用的控件时,以下是一些在Android Jetpack Compose中可能不太常见的控件,但它们在特定的应用场景中可能会派上用场:
- FloatingActionButtonExtended:一个扩展版浮动操作按钮,可以显示扩展的标签和图标。
- DropdownMenu:用于创建下拉菜单,可选择从中选择项目。
- AutocompleteTextField:用于显示自动完成建议的文本字段。
- TimePicker:用于选择时间的时间选择器。
- DatePicker:用于选择日期的日期选择器。
- TabRow:用于创建选项卡式布局的组件。
- SliderValueRange:一个范围滑块,用于选择两个值之间的范围。
- CircularProgressIndicator:用于显示环形进度条。
- LinearProgressIndicator:用于显示线性进度条。
- Snackbar:用于在应用程序底部显示短时间消息的组件。
- Tooltip:用于提供关于视图的简短描述的工具提示。
请注意,这些控件可能在不同版本的Compose中进行了更新或更改,具体的功能和用法可能会有所不同。我建议查阅Compose的官方文档以获取最新的信息和示例代码。
MaterialTheme
shapes
MaterialTheme.shapes.small
MaterialTheme.shapes.medium
MaterialTheme.shapes.large
typography
typography:排版、字体排印
caption: 标题、说明或字幕
overline: 排版术语,指的是在文字的顶部画出一条横线
// 标题
Text(text = "h1"
, modifier = Modifier.padding(bottom = 10.dp)
, style = MaterialTheme.typography.h1)
// 副标题
Text(text = "MaterialTheme.typography.subtitle1"
, modifier = Modifier.padding(bottom = 10.dp)
, style = MaterialTheme.typography.subtitle1)
// 文本
Text(text = "MaterialTheme.typography.body1"
, modifier = Modifier.padding(bottom = 10.dp)
, style = MaterialTheme.typography.body1)
// bUtton
MaterialTheme.typography.button
//
MaterialTheme.typography.caption
//
MaterialTheme.typography.overline
OutlinedTextField:外边框文本输入框
- OutlinedTextField用于显示一个带有外边框的文本输入框。
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@Preview
fun EditTextView(){
val textState = remember { mutableStateOf("") }
Column(modifier = Modifier.padding(16.dp)) {
Text(text = "test"
, modifier = Modifier.padding(bottom = 10.dp)
, style = MaterialTheme.typography.headlineLarge)
OutlinedTextField(value = textState.value,
onValueChange = {textState.value=it}, label = {
Text(text = "Enter Your Name")
})
}
}
Surface
Surface是一个用于绘制矩形的组件,可以用来创建卡片、容器等。
Surface可以用来为其他组件提供背景和边框,可以应用阴影效果,并可以通过modifier来调整其外观。
1、要使用Surface,首先在build.gradle文件中添加Compose的依赖:
implementation 'androidx.compose.material:material:1.0.2'
2、然后,在Compose的代码中使用Surface组件:
@Composable
fun MyScreen() {
Surface(
modifier = Modifier.padding(16.dp),
elevation = 4.dp
) {
// 在这里添加你的组件
}
}
创建了一个名为MyScreen
的Compose函数,并在其中使用了Surface组件。我们通过modifier
属性为Surface添加了16dp的内边距,通过elevation
属性设置了Surface的阴影效果。
你可以在Surface组件内部添加其他组件,例如文本、图片等。它们将以Surface作为容器显示。
除了padding和elevation外,Surface还可以使用其他modifier来调整其外观,例如背景颜色、形状等。你可以根据自己的需求进行进一步的自定义。
Box
Box是一个容器组件,用于对其子组件进行布局和定位。你可以使用Box来创建复杂的布局结构和自定义界面。
要使用Box,你需要首先导入Compose库中的依赖:
implementation 'androidx.compose.foundation:foundation:1.0.2'
然后,在Compose的代码中使用Box组件:
@Composable
fun MyScreen() {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.LightGray)
) {
Box(
modifier = Modifier
.size(200.dp)
.background(Color.Blue)
)
Box(
modifier = Modifier
.size(100.dp)
.background(Color.Red)
)
}
}
在这个例子中,我们创建了一个名为MyScreen
的Compose函数,并在其中嵌套使用了两个Box组件。外部的Box组件占据了整个屏幕空间,使用fillMaxSize()
将其填满,并设置了背景颜色为浅灰色。内部的两个Box组件分别设置了不同的大小和背景颜色。
你可以在Box组件内部添加其他组件,并使用modifier来调整它们的位置、大小和其他样式。
通过在Box组件内部嵌套使用不同的子组件和多个modifier,你可以创建更复杂的布局结构和自定义界面。
Row
Row是一个用于水平排列子组件的容器组件。你可以使用Row来将子组件横向排列在一行上。
要使用Row,你需要首先导入Compose库中的依赖:
implementation 'androidx.compose.foundation:foundation:1.0.2'
然后,在Compose的代码中使用Row组件:
@Composable
fun MyScreen() {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Box(
modifier = Modifier
.width(50.dp)
.height(50.dp)
.background(Color.Blue)
)
Box(
modifier = Modifier
.width(100.dp)
.height(50.dp)
.background(Color.Red)
)
}
}
在这个例子中,我们创建了一个名为MyScreen
的Compose函数,并在其中使用了一个Row组件。我们使用modifier
属性为Row添加了填满宽度和16dp的内边距。
在Row组件内部,我们嵌套使用了两个Box组件,分别设置了不同的宽度、高度和背景颜色。
你可以在Row组件内部添加其他组件,并使用modifier来调整它们的位置、大小和其他样式。通过在Row组件内部嵌套使用不同的子组件和多个modifier,你可以创建更复杂的横向布局结构。
Spacer
ClickableText
ClickableText是Android Jetpack Compose中的一个控件,它用于在文本中创建可点击的部分,并对点击事件进行处理。
使用ClickableText,你可以在文本中标识出特定的部分,用户点击这些部分时可以执行自定义的操作。
这是一个示例使用ClickableText的代码片段:
@Composable
fun MyScreen() {
ClickableText(
text = "Click me!",
modifier = Modifier.clickable { /* 在这里处理点击事件 */ },
style = MaterialTheme.typography.h4
)
}
在这个例子中,我们使用了ClickableText组件,将"Click me!"作为文本传递给它。我们还使用Modifier的clickable函数来为ClickableText添加点击事件处理逻辑。最后,我们可以使用style属性来设置文本的样式,例如使用MaterialTheme中的typography。
当用户点击ClickableText时,clickable函数中定义的点击事件处理代码将执行。
你可以根据需要自定义ClickableText的样式、点击事件处理逻辑以及其中显示的文本内容。
BasicTextField
BasicTextField
是Android Jetpack Compose中的一个文本输入框组件,用于接收用户输入的文本。它是一个简单的文本输入框,提供了基本的文本输入功能。
BasicTextField
允许用户输入和编辑文本,并且可以通过监听文本变化的回调来响应用户输入的变化。它还提供了一些属性和函数,以控制文本输入的行为和样式。
以下是一个使用BasicTextField
的示例:
@Composable
fun MyTextField() {
val textState = remember { mutableStateOf("") }
BasicTextField(
value = textState.value,
onValueChange = { newValue ->
textState.value = newValue
},
textStyle = TextStyle(color = Color.Black),
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
)
}
在上面的示例中,我们首先创建了一个mutableStateOf
来保存文本的状态。然后,我们使用BasicTextField
组件来创建一个文本输入框。其中,value
属性用于设置文本输入框中的值,onValueChange
属性是一个回调函数,用于在文本发生变化时更新状态。我们还通过textStyle
属性设置了文本的样式,以及使用modifier
属性设置了文本输入框的宽度和间距。
通过使用BasicTextField
,您可以轻松地创建一个简单的文本输入框,并与状态变量进行绑定,以获得用户输入的文本。您还可以使用其他属性和函数来更改文本输入框的行为和样式,以满足您的需求。
其他
stringResources
stringResource是一个用于获取字符串资源的函数。它允许你通过资源ID来访问字符串资源,并在Compose中使用这些字符串。
要使用stringResource函数,首先确保在你的Compose工程中正确设置了资源文件。然后,可以在Compose代码中使用stringResource函数来获取字符串资源。
需要注意的是,在使用stringResource函数之前,确保你的Compose代码位于与字符串资源相关联的Context中,例如Activity或Fragment中。这样Compose才能正确获取到字符串资源。
示例代码如下:
@Composable
fun MyScreen() {
val appName = stringResource(id = R.string.app_name)
Text(text = "Welcome to $appName")
}
在这个例子中,我们在Compose函数MyScreen
中使用了stringResource函数来获取一个字符串资源。我们传递了资源的ID(例如R.string.app_name
)给stringResource
函数,然后将返回的字符串赋值给变量appName
。最后,我们在Text组件中使用$appName
将这个字符串插入到其他文本中。
这样,你就可以在Compose中方便地使用字符串资源了。
buildAnnotatedString
buildAnnotatedString
是一个用于构建带有样式和标记的字符串的函数。它是在Android Jetpack Compose中的core
包中提供的,用于创建富文本字符串。
buildAnnotatedString
函数接受一个Lambda表达式作为参数,Lambda表达式的上下文是AnnotatedString.Builder
对象。通过在Lambda表达式中调用addString
方法,您可以将文本添加到AnnotatedString.Builder
中,并为每个文本段设置不同的样式。
除了文本段的样式之外,buildAnnotatedString
还允许您为某些文本段添加标记。标记是一个键值对,您可以用来标识和区分文本段。标记可以与文本段的样式一起使用,以便根据需要对文本进行进一步处理。
以下是一个示例,展示了如何使用buildAnnotatedString
函数创建一个带有不同样式和标记的富文本字符串:
@Composable
fun MyAnnotatedText() {
val annotatedText = buildAnnotatedString {
withStyle(style = SpanStyle(color = Color.Red)) {
append("红色文本")
}
append("普通文本")
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
append("加粗文本")
}
append("普通文本")
addStringAnnotation(tag = "Tag1", start = 0, end = 5, annotation = "标记1")
addStringAnnotation(tag = "Tag2", start = 10, end = 15, annotation = "标记2")
}
Text(text = annotatedText)
}
在上面的示例中,我们使用withStyle
函数为一部分文本设置了不同的颜色和字体样式。我们还使用addStringAnnotation
方法为一部分文本添加了标记。
使用buildAnnotatedString
函数,您可以轻松地创建具有自定义样式和标记的富文本字符串,以实现更丰富和有趣的文本展示效果。
除了buildAnnotatedString
函数,Android Jetpack Compose还提供了一些与构建带有样式和标记的字符串相关的函数。以下是一些常用的函数:
-
withStyle
:该函数用于在AnnotatedString.Builder
中设置文本段的样式。它接受一个SpanStyle
对象作为参数,用于定义文本段的样式,例如颜色、字体大小、字体样式等。 -
addStringAnnotation
:该函数用于为文本段添加标记。它接受一个标记名称(可以是任意字符串)、文本段的起始索引、结束索引和标记对象作为参数。标记对象可以是任意类型的数据,用于标识和区分文本段。 -
merge
:该函数用于合并多个AnnotatedString
对象。当您想要将多个带有样式和标记的字符串合并为一个字符串时,可以使用merge
函数。 -
AnnotatedString
:AnnotatedString
类是buildAnnotatedString
函数的返回类型。它表示一个带有样式和标记的字符串,并提供一些方法用于操作和处理这些文本段。
这些函数一起提供了一种方便的方式来创建和处理带有样式和标记的富文本字符串。您可以根据需要选择适合您的用例的函数来构建和操作富文本字符串。
Theme主题
MaterialTheme
在Android Jetpack Compose中,MaterialTheme
是一个用于定义应用程序主题的组件。typography
是MaterialTheme
的一个属性,用于定义应用程序中文本元素的字体样式。
typography
属性是一个Typography
对象,它包含了不同文本元素(例如标题、副标题、正文等)的字体样式设置。通过在MaterialTheme
中设置typography
属性,您可以全局设置应用程序的字体样式。
typography
属性提供了一些预定义的字体样式,比如h1
、h2
、body1
等。您还可以通过自定义Typography
对象来定义自己的字体样式。例如,以下代码将应用程序的标题文本元素的字体样式设置为大写、加粗和红色:
@Composable
fun MyApp() {
MaterialTheme(typography = Typography(h1 = TextStyle(textTransform = TextTransform.Uppercase, fontWeight = FontWeight.Bold, color = Color.Red))) {
Text("Hello, World!")
}
}
使用typography
属性,您可以轻松地在应用程序中应用一致的字体样式,以确保应用程序的视觉一致性。