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
,指定水平方向的對(duì)齊方式,有Start
、CenterHorizontally
,End
三種,默認(rèn)Start
。這部分和我們的android:gravity
屬性類似,這里是通過兩個(gè)屬性分開配置。content
,就是我們的子元素,用大括號(hào)包住。
@Composable fun ArtistCard() { Column { Text("Alfred Sisley") Text("3 minutes ago") } }
2. Row
子元素按水平順序排列,相當(dāng)于水平方向的LinearLayout
?;居梅ㄅcColumn
一致,簡(jiǎn)單說明一下。
@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
,指定垂直方向的對(duì)齊方式,有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
,指定子元素的對(duì)齊方式,八個(gè)方向加一個(gè)正中九種位置,默認(rèn)是左上角(LTR)。這個(gè)屬性我個(gè)人覺得使用頻率不高,主要還是需要單獨(dú)去指定各個(gè)子元素位置(使用Modifier
的align
方法)。
這里可以看個(gè)文檔中的例子:
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中的各個(gè)子Box從底部向上疊加。通過align
指定位置,通過size
、padding
調(diào)整大小。matchParentSize
類似match_parent
屬性,寬高填充滿父布局。
注意:這個(gè)子元素的Box和父元素Box雖然長(zhǎng)得一樣,但實(shí)際不是一個(gè)組件。前者類似于View,不能添加子View,可以指定大小樣式,而后者類似ViewGroup。
propagateMinConstraints
,子元素是否使用指定的最小約束,默認(rèn)false。這個(gè)屬性直接這么解釋很抽象,我們可以接著用上面的例子,添加下面的代碼:
Box( Modifier.sizeIn(100.dp, 200.dp), propagateMinConstraints = true ) { ... }
我們指定子元素最小寬是100dp,高是200dp后,預(yù)覽效果如下:
可以看到原本的紅藍(lán)色塊因?yàn)楦叨戎挥?50dp,所以被約束為了最小的200dp,變成的長(zhǎng)方形。
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)時(shí),在嵌套某些 View(如 RelativeLayout)時(shí),可能會(huì)出現(xiàn)一些性能問題。由于 Compose 可以避免多次測(cè)量,因此可以根據(jù)需要進(jìn)行深層次嵌套,而不會(huì)影響性能。
雖然不用考慮嵌套帶來的性能問題,但是這寫起來一層套一層的也挺鬧心的。加上ConstraintLayout
我個(gè)人已經(jīng)非常習(xí)慣使用了,所以也很希望在Compose中也能使用到它。個(gè)人感覺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
約束。通常我們不需要修改它。
這里用官方的一個(gè)例子簡(jiǎn)單說明一下它的使用方法:
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)建引用。或者說定義需要使用的id。Modifier.constrainAs
是定義約束條件。括號(hào)內(nèi)填寫開始創(chuàng)建的引用。類似android:id="@+id/xxx"
。createGuidelineFromXXX
就是創(chuàng)建一個(gè)Guideline
,例子中創(chuàng)建了左右兩個(gè)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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android實(shí)現(xiàn)底部圖標(biāo)與Fragment的聯(lián)動(dòng)實(shí)例
本篇文章主要介紹了Android實(shí)現(xiàn)底部圖標(biāo)與Fragment的聯(lián)動(dòng)實(shí)例,具有一定的參考價(jià)值,有興趣的可以了解一下2017-07-07Android中EditText+Button組合導(dǎo)致輸入板無法收起的原因分析及解決辦法
這篇文章主要介紹了Android中EditText+Button組合導(dǎo)致輸入板無法收起的原因分析及解決辦法的相關(guān)資料,需要的朋友可以參考下2016-01-01Android編程實(shí)現(xiàn)隨機(jī)生成顏色的方法示例
這篇文章主要介紹了Android編程實(shí)現(xiàn)隨機(jī)生成顏色的方法,結(jié)合實(shí)例形式分析了Android使用java Random類針對(duì)隨機(jī)數(shù)及顏色值相關(guān)操作技巧,需要的朋友可以參考下2017-08-08mui.init()與mui.plusReady()區(qū)別和關(guān)系
給大家分享一下在使用MUI進(jìn)行APP開發(fā)的時(shí)候,mui.init()與mui.plusReady()區(qū)別以及使用上不同之處。2017-11-11Android開發(fā)筆記 Handler使用總結(jié)
當(dāng)應(yīng)用程序啟動(dòng)時(shí),Android首先會(huì)開啟一個(gè)主線程(也就是UI線程),主線程為管理界面中的UI控件,進(jìn)行事件分發(fā)2012-11-11Android 友盟第三方登錄與分享的實(shí)現(xiàn)代碼
這篇文章主要介紹了Android 友盟第三方登錄與分享的實(shí)現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09Android組件化工具ARouter使用方法詳細(xì)分析
這篇文章主要介紹了Android組件化工具ARouter使用方法,組件化項(xiàng)目存在各個(gè)模塊之間耦合,通信麻煩的問題,為了解決這個(gè)問題,阿里巴巴的開發(fā)者就搞出了Arouter這個(gè)框架,以解決上述問題2022-10-10Android開發(fā)判斷一個(gè)app應(yīng)用是否在運(yùn)行的方法詳解
這篇文章主要介紹了Android開發(fā)判斷一個(gè)app應(yīng)用是否在運(yùn)行的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了Android判斷應(yīng)用運(yùn)行狀態(tài)的相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2017-11-11