Jetpack Compose实战教程(六)
第六章 没有了margin,如何区分外边距?内边距?
文章目录
- Jetpack Compose实战教程(六)
- 一、前言
- 二、本章目标
- 三、开始编码
- 3.1 特殊情况下的margin
- 3.2 使用padding设置外边距
- 3.3 使用padding设置内边距
- **修饰符(Modifier)的函数调用先后顺序很重要!!**
- **修饰符(Modifier)的函数调用先后顺序很重要!!**
- **修饰符(Modifier)的函数调用先后顺序很重要!!**
一、前言
我们在写xml布局的时候,经常会用到android:margin属性,毕竟除了居中以外,固定位置的偏移就得用到margin,xml中我们使用margin来设置外边距,使用padding来设置内边距。但在compose中,没有了margin属性,只有一个padding,那么我们如何设置外边距和内边距呢?
二、本章目标
能熟练的使用padding来设置内边距和外边距
友情提醒,如果各位看官有不懂的代码可以先看一下之前的章节,循序渐进,如果还是有不懂的,可以给我留言
三、开始编码
请留意:以下代码都是在清单文件中设置了横屏的
3.1 特殊情况下的margin
之所以先说特殊情况下的margin,是为了防止杠精说:明明有margin啊,只是要引入一个组件而已。没错,它就是我们第四章中提到的ConstraintLayout。 compose中的约束布局用法基本和xml一致,第四章我们也进行了一些解析,这里我们就简单上代码说明一下margin的使用
BaseTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
ConstraintLayout(
Modifier
.fillMaxSize()
.background(color = Color.Yellow)) {
Box(modifier = Modifier
.size(200.dp)
.constrainAs(createRef()) {
top.linkTo(parent.top,100.dp)
start.linkTo(parent.start,100.dp)
}.background(color = Color.Blue))
}
}
}
3.2 使用padding设置外边距
在使用xml代码时,我们设置外边距(margin)是在子View设置的,比如有如下代码:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#ffff00">
<RelativeLayout
android:layout_width="200dp"
android:layout_height="200dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:background="#0000ff"
android:layout_marginTop="100dp"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
这段代码产生的UI效果如下:
但在compose中,设置外边距恰恰是反过来的,它是在父View中设置,等价的代码写法如下:
BaseTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
ConstraintLayout(
Modifier
.fillMaxSize()
.background(color = Color.Yellow).padding(top=100.dp)) {
Box(modifier = Modifier
.size(200.dp)
.constrainAs(createRef()) {
top.linkTo(parent.top)
start.linkTo(parent.start)
}.background(color = Color.Blue))
}
}
}
这时候,有好奇的小伙伴会问了,那如果我就把这个padding写到Box 里面去,会出现什么效果呢?那么我们就来实践一下
BaseTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
ConstraintLayout(
Modifier
.fillMaxSize()
.background(color = Color.Yellow)) {
Box(modifier = Modifier
.size(200.dp)
.constrainAs(createRef()) {
top.linkTo(parent.top)
start.linkTo(parent.start)
}.background(color = Color.Blue)
.padding(top=100.dp)
)
}
}
}
运行结果如下:
可以看到,我们移除了ConstraintLayout(父View)的padding,所以Box(子View)的外间距就没有了,而我们在Box 设置的padding是应用于Box的子View的外边距,那么我们现在来给Box添加一下子View
BaseTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
ConstraintLayout(
Modifier
.fillMaxSize()
.background(color = Color.Yellow)) {
Box(modifier = Modifier
.size(200.dp)
.constrainAs(createRef()) {
top.linkTo(parent.top)
start.linkTo(parent.start)
}
.background(color = Color.Blue)
.padding(top = 100.dp)
){
Box(modifier = Modifier.size(100.dp).background(color = Color.Red))
}
}
}
}
这样就很好理解了吧
3.3 使用padding设置内边距
在尝试使用padding设置内边距之前,大家需要先留意一个坑,这也是为什么我上面的例子全部是用background 来说明的原因,在xml中,我们可以给一个View设置android:background属性,然后如果再设置android:alpha是可以应用到背景上的,并且不需要关心属性设置的先后顺序,比如如下代码:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#ffff00">
<RelativeLayout
android:layout_width="200dp"
android:layout_height="200dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:background="#0000ff"
android:alpha="0.6"
android:layout_marginTop="100dp"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
我们设置的颜色是蓝色,但因为设置了40%的透明度,最终和黄色的底色交融,就变成了这个灰色,但使用compose的话,必须要将alpha的属性提前,否则将失效,所以重要的话说三遍:
修饰符(Modifier)的函数调用先后顺序很重要!!
修饰符(Modifier)的函数调用先后顺序很重要!!
修饰符(Modifier)的函数调用先后顺序很重要!!
那么我们来看compose的等价代码:
BaseTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
ConstraintLayout(
Modifier
.fillMaxSize()
.background(color = Color.Yellow).padding(top = 100.dp)) {
Box(modifier = Modifier
.size(200.dp)
.constrainAs(createRef()) {
top.linkTo(parent.top)
start.linkTo(parent.start)
}
.alpha(0.6f) //如果这行代码放在.background之后,那么将失效
.background(color = Color.Blue)
)
}
}
}
好,进入整体,为了让大家更好的理解内边距,这里我不再单纯使用background,而是添加一张图片,我们先看如下代码:
BaseTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
ConstraintLayout(
Modifier
.fillMaxSize()
.background(color = Color.Yellow)
.padding(50.dp)) {
Box(modifier = Modifier
.size(200.dp)
.constrainAs(createRef()) {
top.linkTo(parent.top)
start.linkTo(parent.start)
}
.background(color = Color.Blue)){
Image(painter = painterResource(id = R.mipmap.ic_person_detail_delete_unable),
contentDescription = null, modifier = Modifier.background(color = Color.Green)
.size(100.dp).padding(20.dp))
}
}
}
}
但还记得我们上面说的“修饰符(Modifier)的函数调用先后顺序很重要!!” 吗?让我们来稍微改一下代码,改变一下padding的位置
BaseTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
ConstraintLayout(
Modifier
.fillMaxSize()
.background(color = Color.Yellow)
.padding(50.dp)) {
Box(modifier = Modifier
.size(200.dp)
.constrainAs(createRef()) {
top.linkTo(parent.top)
start.linkTo(parent.start)
}
.background(color = Color.Blue)){
Image(painter = painterResource(id = R.mipmap.ic_person_detail_delete_unable),
contentDescription = null, modifier = Modifier.background(color = Color.Green)
.padding(20.dp).size(100.dp)) //我们将padding的调用提升至size之前
}
}
}
}
由于我们在设置图片的size之前先设置了padding,所以最终Image所占据的宽高都加上了padding的值,就变成了140dp,这也是实际开发中我们最容易疏忽的地方
至此,各位看官应该可以比较熟练的运用padding来设置内外边距了,实践大于阅读,一定要去实际使用才能牢固的掌握哦!