Jetpack?Compose入門基礎全面精講
1. Column
子元素按豎直順序排列,相當于豎直方向的LinearLayout
。
@Composable inline fun Column( modifier: Modifier = Modifier, verticalArrangement: Arrangement.Vertical = Arrangement.Top, horizontalAlignment: Alignment.Horizontal = Alignment.Start, content: @Composable ColumnScope.() -> Unit )
modifier
是修飾符,我們放到下一篇詳細說明。verticalArrangement
,指定子元素在Column
中的排列方式,默認是Top。下圖是文檔給的各屬性示意,很直觀。
horizontalAlignment
,指定水平方向的對齊方式,有Start
、CenterHorizontally
,End
三種,默認Start
。這部分和我們的android:gravity
屬性類似,這里是通過兩個屬性分開配置。content
,就是我們的子元素,用大括號包住。
@Composable fun ArtistCard() { Column { Text("Alfred Sisley") Text("3 minutes ago") } }
2. Row
子元素按水平順序排列,相當于水平方向的LinearLayout
。基本用法與Column
一致,簡單說明一下。
@Composable inline fun Row( modifier: Modifier = Modifier, horizontalArrangement: Arrangement.Horizontal = Arrangement.Start, verticalAlignment: Alignment.Vertical = Alignment.Top, content: @Composable RowScope.() -> Unit )
horizontalArrangement
,指定子元素在水平方向的排列方式,默認是Start
。直接上圖:
verticalAlignment
,指定垂直方向的對齊方式,有Top
、CenterVertically
,Bottom
三種,默認Top
。
3. Box
box就像盒子一樣,里面的東西可以層層擺放。大體相當于FrameLayout
。
@Composable inline fun Box( modifier: Modifier = Modifier, contentAlignment: Alignment = Alignment.TopStart, propagateMinConstraints: Boolean = false, content: @Composable BoxScope.() -> Unit )
contentAlignment
,指定子元素的對齊方式,八個方向加一個正中九種位置,默認是左上角(LTR)。這個屬性我個人覺得使用頻率不高,主要還是需要單獨去指定各個子元素位置(使用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) ) }
預覽效果:
Box中的各個子Box從底部向上疊加。通過align
指定位置,通過size
、padding
調整大小。matchParentSize
類似match_parent
屬性,寬高填充滿父布局。
注意:這個子元素的Box和父元素Box雖然長得一樣,但實際不是一個組件。前者類似于View,不能添加子View,可以指定大小樣式,而后者類似ViewGroup。
propagateMinConstraints
,子元素是否使用指定的最小約束,默認false。這個屬性直接這么解釋很抽象,我們可以接著用上面的例子,添加下面的代碼:
Box( Modifier.sizeIn(100.dp, 200.dp), propagateMinConstraints = true ) { ... }
我們指定子元素最小寬是100dp,高是200dp后,預覽效果如下:
可以看到原本的紅藍色塊因為高度只有150dp,所以被約束為了最小的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
的基礎上多了最大最小寬度高度的屬性??梢杂盟鼇碜鲆恍╉撁孢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ù)需要進行深層次嵌套,而不會影響性能。
雖然不用考慮嵌套帶來的性能問題,但是這寫起來一層套一層的也挺鬧心的。加上ConstraintLayout
我個人已經(jīng)非常習慣使用了,所以也很希望在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)化的。默認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, ) }
預覽效果如下(包括約束效果):
說明一下代碼中的屬性和方法:
createRefs()
是創(chuàng)建引用。或者說定義需要使用的id。Modifier.constrainAs
是定義約束條件。括號內填寫開始創(chuàng)建的引用。類似android:id="@+id/xxx"
。createGuidelineFromXXX
就是創(chuàng)建一個Guideline
,例子中創(chuàng)建了左右兩個Guideline
作為左右兩邊間距參考線。linkTo
是用來指定約束條件的。例如top.linkTo(image.bottom, 32.dp)
相當于app:layout_constraintTop_toBottomOf="@+id/image"
加android:layout_marginTop="32dp"
。Dimension.fillToConstraints
,填充滿約束,類似寬高指定0dp。
當然還有許多的屬性方法沒有用到,也就不詳細的介紹了,有興趣的可以看官方demo。
到此,基礎布局篇結束,下一篇詳細介紹 Modifier
修飾符。
6. 參考
到此這篇關于Jetpack Compose入門基礎全面精講的文章就介紹到這了,更多相關Jetpack Compose內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Android實現(xiàn)底部圖標與Fragment的聯(lián)動實例
本篇文章主要介紹了Android實現(xiàn)底部圖標與Fragment的聯(lián)動實例,具有一定的參考價值,有興趣的可以了解一下2017-07-07Android中EditText+Button組合導致輸入板無法收起的原因分析及解決辦法
這篇文章主要介紹了Android中EditText+Button組合導致輸入板無法收起的原因分析及解決辦法的相關資料,需要的朋友可以參考下2016-01-01mui.init()與mui.plusReady()區(qū)別和關系
給大家分享一下在使用MUI進行APP開發(fā)的時候,mui.init()與mui.plusReady()區(qū)別以及使用上不同之處。2017-11-11Android開發(fā)判斷一個app應用是否在運行的方法詳解
這篇文章主要介紹了Android開發(fā)判斷一個app應用是否在運行的方法,結合實例形式較為詳細的分析了Android判斷應用運行狀態(tài)的相關操作技巧與注意事項,需要的朋友可以參考下2017-11-11