一文講完Jetpack常用修飾符

語言: CN / TW / HK

「這是我參與2022首次更文挑戰的第15天,活動詳情檢視:2022首次更文挑戰」。

Jetpack Compose系列(4) - 修飾符

修飾符

Modifier,即JetpackCompose中的修飾符,可以用來修飾以下內容:

· 更改可組合項的大小、佈局、行為和外觀

· 新增資訊,如無障礙標籤

· 處理使用者輸入

· 新增高階互動,如使元素可點選、可滾動、可拖動或可縮放

修飾符是標準的Kotlin物件,可以通過呼叫某個Modifier類函式來建立修飾符,例如: @Preview(showBackground = true) @Composable fun DefaultPreview() { Column(modifier = Modifier.padding(35.dp)){ Text(text = "Hello") Text(text = "Modifier") } } 對應生成的padding值為15dp的兩個Text列表效果為:

image.gif 相信到這裡你已經開始明白,Modifier可以像原先View體系中的XML檔案裡設定padding等擴充套件函式來調節佈局效果,當然也可以調節width和height一系列屬性,下面就讓我們來熟悉這些你以後經常使用到的擴充套件函式:

背景(background)和透明度(alpha)

· background(color: Color, shape: Shape?):設定背景及背景形狀,shape可以指定形狀,例如可以使用RoundedCornerShape來指定圓角大小。

· alpha(alpha: Float):設定透明度,範圍值從0到1。

如果是漸變背景,可以使用background(brush: Brush, shape: Shape?, alpha: Float?)。其中Brush引數就是我們指定的漸變,例如使用verticalGradient建立的豎直方向漸變: @Composable fun CustomView() { Column(modifier = Modifier.background( Brush.verticalGradient(listOf(Color.Blue,Color.Red)) ) .alpha(0.3f)){ Text(text = "Hello") Text(text = "Modifier") } } 對應生成的效果為:

image.gif 需要注意的是,這裡設定的alpha透明度指的是{}裡的物件的透明度,而如果要修改背景透明度則要把alpha設定進background()內,例如:

image.gif

在設定Brush的時候,你會發現可以設定很多函式:

image.gif

這些函式可以做到橫向漸變、線性漸變、掃描漸變,外加指定開始結束位置等等,這裡就不多做介紹了。

大小 ( size ) 和寬高

· width(width: dp): 設定寬度,單位dp。

· height(height: dp): 設定高度,單位dp。

· size(width: dp,height: dp) :同時設定寬高,單位dp。

下面兩段程式碼是等價的: Column(modifier = Modifier .background(Color.Red) .width(60.dp) .height(120.dp)){ Text(text = "Hello") Text(text = "Modifier") } Column(modifier = Modifier .background(Color.Red) .size(60.dp,120.dp)){ Text(text = "Hello") Text(text = "Modifier") } 實現效果也是一致的:

image.gif

邊框 (border) 和點選

· border(width: Dp, color: Color, shape: Shape?):新增邊框,color引數指定顏色,shape引數指定粗細和形狀。

· clickable():讓任意控制元件變的可點選,且會附加水波紋效果。

@Composable fun CustomView() { Column(modifier = Modifier .background(Color.Red) .width(60.dp) .height(120.dp) .clickable (onClick = { Log.i("clickEvent"," get clicked ! ") })){ Text(text = "Hello") Text(text = "Modifier") } } 點選列表,對應的控制檯輸出日誌為:

image.gif 當然,clickable()也有其他引數可以設定不可點選等: Modifier.clickable( enabled: Boolean = true, // 是否可點選狀態,預設可點選,false則不可點選 onClickLabel: String? = null, // 語義/可訪問性標籤 role: Role? = null, // 點選元素的型別,例如Button、Checkbox、Image等。用於可訪問性服務。 onClick: () -> Unit // 響應點選事件 ) · combinedClickable:可設定長按,多次點選,普通點選監聽等。注意:這是實驗性的API隨時可能刪除(使用時會要求方法和方法被呼叫處帶上@ExperimentalFoundationApi)。示例如下: @ExperimentalFoundationApi @Composable fun CustomView() { Column(modifier = Modifier .background(Color.Red) .width(60.dp) .height(120.dp) .combinedClickable ( onLongClick = { Log.i("clickEvent"," onLongClick event happened ! ") }, onDoubleClick = { Log.i("clickEvent"," onDoubleClick event happened ! ") }, onClick = { Log.i("clickEvent"," onClick event happened ! ") } )){ Text(text = "Hello") Text(text = "Modifier") } } 對應日誌也能在控制檯正確輸出:

image.gif · onFocusChanged():監聽焦點變化事件。

· focusable():設定焦點。

· requiredWidth(width: Dp):強制設定寬度,可以忽略父元素的寬高限制。

· requiredHeight(height: Dp):強制設定高度,可以忽略父元素的寬高限制。

· heightIn(min: Dp, max: Dp ),設定高度的最大最小值。widthIn同理。

· padding(all: Dp): 在元素周圍留出空間,即內邊距。

· rotate(degrees: Float):設定旋轉度數。

· scale(scaleX: Float, scaleY: Float):設定縮放,如果是負數可以實現映象效果。

· horizontalScroll(),允許子元素在寬度大於最大限制時橫向滾動。(指超出螢幕寬度後,我們還可以水平方向滾動)

· verticalScroll(),允許子元素在寬度大於最大限制時垂直滾動。

例如: Row(Modifier.horizontalScroll(rememberScrollState())) { Box( Modifier .size(700.dp, 50.dp) .background(Color.Red) ){ Text("123") } } 對應輸出效果為:

image.gif 這時這個紅色的條目是可以左右拖動的。

· fillMaxHeight(fraction: Float = 1f):子佈局填充父項允許的所有可用高度,效果類似於XML中的match_parent,預設值1f。fillMaxSize 和 fillMaxWidth同理。

例如如下程式碼: Box(Modifier.requiredSize(100.dp).background(Color.Red)) { Box( Modifier.fillMaxWidth(0.6f) .fillMaxHeight(0.5f) .background(color = Color.Yellow) ) } 對應的效果為:

image.gif · wrapContentSize:元件的控制元件寬高若是小與定義的最小寬高,會將元件進行排列的設定(看名字是不是想起了wrap_content)。

· sizeIn(minWidth: Dp ,minHeight: Dp ,maxWidth: Dp ,maxHeight: Dp):設定寬高的最小值和最大值,寬度在minWidth ~ maxWidth之間,高度在minHeight ~ maxHeight之間。 Column { Box( Modifier .sizeIn(minWidth = 50.dp, minHeight = 50.dp) .size(20.dp) .background(Color.Black) ) Box( Modifier .sizeIn(minWidth = 50.dp, minHeight = 50.dp) .wrapContentSize(Alignment.TopCenter) .size(20.dp)//設定的size小於最小寬高,最終渲染出來的就是20*20的,對齊方式為TopCenter .background(Color.Red) ) } 對應的效果為:

image.gif 由程式碼可知,黑色的Box設定的size小於最小寬高,最終渲染出來的就是5050的長寬。紅色的Box設定了wrapContentSize,設定的size小於最小寬高,最終渲染出來的就是2020的長寬,同時對齊方式為TopCenter。

當然,也可以單獨設定寬高wrap: //設定寬度 wrapContentWidth( align: Alignment.Horizontal = Alignment.CenterHorizontally, unbounded: Boolean = false ) //設定高度 wrapContentHeight( align: Alignment.Vertical = Alignment.CenterVertically, unbounded: Boolean = false ) 我們修改上述程式碼中的兩個屬性: Column { Box( Modifier .sizeIn(minWidth = 50.dp, minHeight = 50.dp) .wrapContentHeight(Alignment.CenterVertically) .height(20.dp)//高20dp,寬50dp,垂直居中 .background(Color.Black) ) Box( Modifier .sizeIn(minWidth = 50.dp, minHeight = 50.dp) .wrapContentWidth(Alignment.CenterHorizontally) .width(20.dp)//寬20dp,高50dp,水平居中 .background(Color.Red) ) } 對應的效果展示為:

image.gif

修飾符順序

修飾符函式的順序非常重要,每個函式都會對上一個函式返回的 Modifier 進行更改。

例如: Column { Box( Modifier .size(100.dp) .background(Color.Red) .padding(25.dp) ) Box( Modifier .size(100.dp) .padding(25.dp) .background(Color.Yellow) ) } 對應的效果為:

image.gif 觀察程式碼,不難發現,如果先設定背景,然後設定padding值,那麼padding值是在其背景的基礎上進行的。如果是先設定padding值,那麼後設置的背景是針對padding之後的佈局進行設定的。原因很簡單,僅僅是因為每個函式都會對上一個函式返回的Modifier 進行更改。當然,點選事件也會受到影響,但也只是影響點選區域,這點不難理解,不做贅述了。