Jetpack?Compose入門基礎(chǔ)全面精講
1. Column
子元素按豎直順序排列,相當(dāng)于豎直方向的LinearLayout。
@Composable
inline fun Column(
modifier: Modifier = Modifier,
verticalArrangement: Arrangement.Vertical = Arrangement.Top,
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
content: @Composable ColumnScope.() -> Unit
)
modifier是修飾符,我們放到下一篇詳細(xì)說明。verticalArrangement,指定子元素在Column中的排列方式,默認(rèn)是Top。下圖是文檔給的各屬性示意,很直觀。

horizontalAlignment,指定水平方向的對齊方式,有Start、CenterHorizontally,End三種,默認(rèn)Start。這部分和我們的android:gravity屬性類似,這里是通過兩個屬性分開配置。content,就是我們的子元素,用大括號包住。
@Composable
fun ArtistCard() {
Column {
Text("Alfred Sisley")
Text("3 minutes ago")
}
}
2. Row
子元素按水平順序排列,相當(dāng)于水平方向的LinearLayout?;居梅ㄅcColumn一致,簡單說明一下。
@Composable
inline fun Row(
modifier: Modifier = Modifier,
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
verticalAlignment: Alignment.Vertical = Alignment.Top,
content: @Composable RowScope.() -> Unit
)
horizontalArrangement,指定子元素在水平方向的排列方式,默認(rèn)是Start。直接上圖:

verticalAlignment,指定垂直方向的對齊方式,有Top、CenterVertically,Bottom三種,默認(rèn)Top。
3. Box
box就像盒子一樣,里面的東西可以層層擺放。大體相當(dāng)于FrameLayout。
@Composable
inline fun Box(
modifier: Modifier = Modifier,
contentAlignment: Alignment = Alignment.TopStart,
propagateMinConstraints: Boolean = false,
content: @Composable BoxScope.() -> Unit
)
contentAlignment,指定子元素的對齊方式,八個方向加一個正中九種位置,默認(rèn)是左上角(LTR)。這個屬性我個人覺得使用頻率不高,主要還是需要單獨(dú)去指定各個子元素位置(使用Modifier的align方法)。
這里可以看個文檔中的例子:
Box {
Box(Modifier.fillMaxSize().background(Color.Cyan))
Box(
Modifier.matchParentSize()
.padding(top = 20.dp, bottom = 20.dp)
.background(Color.Yellow)
)
Box(
Modifier.matchParentSize()
.padding(40.dp)
.background(Color.Magenta)
)
Box(
Modifier.align(Alignment.Center)
.size(300.dp, 300.dp)
.background(Color.Green)
)
Box(
Modifier.align(Alignment.TopStart)
.size(150.dp, 150.dp)
.background(Color.Red)
)
Box(
Modifier.align(Alignment.BottomEnd)
.size(150.dp, 150.dp)
.background(Color.Blue)
)
}
預(yù)覽效果:

Box中的各個子Box從底部向上疊加。通過align指定位置,通過size、padding調(diào)整大小。matchParentSize類似match_parent屬性,寬高填充滿父布局。
注意:這個子元素的Box和父元素Box雖然長得一樣,但實(shí)際不是一個組件。前者類似于View,不能添加子View,可以指定大小樣式,而后者類似ViewGroup。
propagateMinConstraints,子元素是否使用指定的最小約束,默認(rèn)false。這個屬性直接這么解釋很抽象,我們可以接著用上面的例子,添加下面的代碼:
Box(
Modifier.sizeIn(100.dp, 200.dp),
propagateMinConstraints = true
) {
...
}
我們指定子元素最小寬是100dp,高是200dp后,預(yù)覽效果如下:

可以看到原本的紅藍(lán)色塊因?yàn)楦叨戎挥?50dp,所以被約束為了最小的200dp,變成的長方形。
4. BoxWithConstraints
BoxWithConstraints和上面的Box很相似,唯一不同是它多了約束。我們先看源碼:
@Composable
fun BoxWithConstraints(
modifier: Modifier = Modifier,
contentAlignment: Alignment = Alignment.TopStart,
propagateMinConstraints: Boolean = false,
content: @Composable BoxWithConstraintsScope.() -> Unit
)
注意到不同處是BoxWithConstraintsScope,它繼承自BoxScope。BoxScope就是提供了上面使用到的align和matchParentSize方法的作用域。
/**
* Receiver scope being used by the children parameter of [BoxWithConstraints]
*/
@Stable
interface BoxWithConstraintsScope : BoxScope {
/**
* The constraints given by the parent layout in pixels.
*
* Use [minWidth], [maxWidth], [minHeight] or [maxHeight] if you need value in [Dp].
*/
val constraints: Constraints
/**
* The minimum width in [Dp].
*
* @see constraints for the values in pixels.
*/
val minWidth: Dp
/**
* The maximum width in [Dp].
*
* @see constraints for the values in pixels.
*/
val maxWidth: Dp
/**
* The minimum height in [Dp].
*
* @see constraints for the values in pixels.
*/
val minHeight: Dp
/**
* The maximum height in [Dp].
*
* @see constraints for the values in pixels.
*/
val maxHeight: Dp
}
所以BoxWithConstraints不同就是在Box的基礎(chǔ)上多了最大最小寬度高度的屬性??梢杂盟鼇碜鲆恍╉撁孢m配之類的工作,使用例子如下:
BoxWithConstraints {
if (maxWidth < 400.dp) {
Column {
Image(/* ... */)
Title(/* ... */)
}
} else {
Row {
Column {
Title(/* ... */)
Description(/* ... */)
}
Image(/* ... */)
}
}
}
5. ConstraintLayout
使用 Android View 系統(tǒng)時,在嵌套某些 View(如 RelativeLayout)時,可能會出現(xiàn)一些性能問題。由于 Compose 可以避免多次測量,因此可以根據(jù)需要進(jìn)行深層次嵌套,而不會影響性能。
雖然不用考慮嵌套帶來的性能問題,但是這寫起來一層套一層的也挺鬧心的。加上ConstraintLayout我個人已經(jīng)非常習(xí)慣使用了,所以也很希望在Compose中也能使用到它。個人感覺ConstraintLayout 可以提高可讀性。
使用Compose中的ConstraintLayout需要額外添加依賴:
implementation "androidx.constraintlayout:constraintlayout-compose:1.0.0-rc02"
@Composable
inline fun ConstraintLayout(
modifier: Modifier = Modifier,
optimizationLevel: Int = Optimizer.OPTIMIZATION_STANDARD,
crossinline content: @Composable ConstraintLayoutScope.() -> Unit
)
optimizationLevel和layout_optimizationLevel一樣,用來約束優(yōu)化的。默認(rèn)OPTIMIZATION_STANDARD,只優(yōu)化直接約束和barrier約束。通常我們不需要修改它。
這里用官方的一個例子簡單說明一下它的使用方法:
ConstraintLayout(
modifier = Modifier
.fillMaxSize()
) {
val (image, header, tag1, tag2, tag3, bSignup, bLogin, disclaimer) = createRefs()
val g1 = createGuidelineFromStart(44.dp)
val g2 = createGuidelineFromEnd(44.dp)
Image(
modifier = Modifier.constrainAs(image) {
width = Dimension.value(201.dp)
height = Dimension.value(179.dp)
top.linkTo(parent.top, 32.dp)
start.linkTo(g1)
},
painter = painterResource(id = R.drawable.intercom_snooze),
contentDescription = null
)
Text(
modifier = Modifier.constrainAs(header) {
top.linkTo(image.bottom, 32.dp)
start.linkTo(g1)
end.linkTo(g2)
width = Dimension.fillToConstraints
},
text = stringResource(id = R.string.welcome_header),
style = MaterialTheme.typography.h5,
)
Text(
modifier = Modifier.constrainAs(tag1) {
top.linkTo(header.bottom, 16.dp)
start.linkTo(g1)
end.linkTo(g2)
width = Dimension.fillToConstraints
},
text = stringResource(id = R.string.welcome_tagline1)
)
Text(
modifier = Modifier.constrainAs(tag2) {
top.linkTo(tag1.bottom, 8.dp)
start.linkTo(g1)
end.linkTo(g2)
width = Dimension.fillToConstraints
},
text = stringResource(id = R.string.welcome_tagline2)
)
Text(
modifier = Modifier.constrainAs(tag3) {
top.linkTo(tag2.bottom, 8.dp)
start.linkTo(g1)
end.linkTo(g2)
width = Dimension.fillToConstraints
},
text = stringResource(id = R.string.welcome_tagline3)
)
Button(
modifier = Modifier.constrainAs(bSignup) {
bottom.linkTo(bLogin.top, 16.dp)
start.linkTo(g1)
end.linkTo(g2)
width = Dimension.fillToConstraints
},
onClick = {}
) {
Text(text = stringResource(id = R.string.sign_up))
}
Button(
modifier = Modifier.constrainAs(bLogin) {
bottom.linkTo(disclaimer.top, 16.dp)
start.linkTo(g1)
end.linkTo(g2)
width = Dimension.fillToConstraints
},
onClick = {},
) {
Text(text = stringResource(id = R.string.log_in))
}
Text(
modifier = Modifier.constrainAs(disclaimer) {
bottom.linkTo(parent.bottom, 8.dp)
start.linkTo(g1)
end.linkTo(g2)
width = Dimension.fillToConstraints
},
text = stringResource(id = R.string.trial_disclaimer),
style = MaterialTheme.typography.caption,
)
}
預(yù)覽效果如下(包括約束效果):


說明一下代碼中的屬性和方法:
createRefs()是創(chuàng)建引用?;蛘哒f定義需要使用的id。Modifier.constrainAs是定義約束條件。括號內(nèi)填寫開始創(chuàng)建的引用。類似android:id="@+id/xxx"。createGuidelineFromXXX就是創(chuàng)建一個Guideline,例子中創(chuàng)建了左右兩個Guideline作為左右兩邊間距參考線。linkTo是用來指定約束條件的。例如top.linkTo(image.bottom, 32.dp)相當(dāng)于app:layout_constraintTop_toBottomOf="@+id/image"加android:layout_marginTop="32dp"。Dimension.fillToConstraints,填充滿約束,類似寬高指定0dp。
當(dāng)然還有許多的屬性方法沒有用到,也就不詳細(xì)的介紹了,有興趣的可以看官方demo。
到此,基礎(chǔ)布局篇結(jié)束,下一篇詳細(xì)介紹 Modifier修飾符。
6. 參考
到此這篇關(guān)于Jetpack Compose入門基礎(chǔ)全面精講的文章就介紹到這了,更多相關(guān)Jetpack Compose內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android 設(shè)置主題實(shí)現(xiàn)點(diǎn)擊波紋效果的示例
本篇文章主要介紹了Android 設(shè)置主題實(shí)現(xiàn)點(diǎn)擊波紋效果的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-11-11
Android EditText 實(shí)現(xiàn)監(jiān)聽實(shí)例
本文主要介紹Android EditText 組件 實(shí)現(xiàn)監(jiān)聽事件,并附有代碼實(shí)例,在Android開發(fā)過程中如果能用到可以參考下2016-07-07
Android實(shí)現(xiàn)USB掃碼槍獲取掃描內(nèi)容
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)USB掃碼槍獲取掃描內(nèi)容,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09
Android利用ViewPager實(shí)現(xiàn)可滑動放大縮小畫廊效果
這篇文章主要介紹了Android利用ViewPager實(shí)現(xiàn)可滑動放大縮小畫廊效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-08-08
Android開發(fā)升級AGP7.0后的一些適配方法技巧
這篇文章主要為大家介紹了升級AGP7.0后的一些適配方法技巧,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
Android TabLayout 實(shí)現(xiàn)底部Tab的示例代碼
本篇文章主要介紹了Android TabLayout 實(shí)現(xiàn)底部Tab的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01
Android 自定義SeekBar 實(shí)現(xiàn)分段顯示不同背景顏色的示例代碼
這篇文章主要介紹了Android 自定義SeekBar 實(shí)現(xiàn)分段顯示不同背景顏色,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06
Android ConnectivityManager網(wǎng)絡(luò)管理詳解
在android平臺中ConnectivityManager主要負(fù)責(zé)查詢網(wǎng)絡(luò)連接狀態(tài)以及在連接狀態(tài)有變化的時候發(fā)出通知,這篇文章主要介紹了Android ConnectivityManager網(wǎng)絡(luò)管理2022-11-11

