在排版 UI 時,有時會想要把元件群組、彼此堆疊,或有時就只是需要一個可以動態撐開的空間。在 Compose 的世界裡,有些排版元件的功能就是協助我們更快的做出一些常見的排版小塊,方便我們做更彈性的組合。今天的耕讀筆記,就要來研究除了 Column
和 Row
之外的其他排版元件。
Surface
元件Surface
直譯就是一個「平面」,用來擺放許多元件在這個平面裡,透過對 Surface
設定 Modifier
來改變整個平台的形狀、邊框、顏色、陰影…等,如此就可以達成群組的效果。
Surface(
modifier = Modifier.width(300.dp).height(100.dp),
shape = RoundedCornerShape(8.dp),
elevation = 7.dp,
) {
Row {
AsyncImage(
load = { loadImageBitmap("https://picsum.photos/500") },
painterFor = { remember { BitmapPainter(it) } },
contentDescription = "Photo",
contentScale = ContentScale.Crop,
modifier = Modifier.size(100.dp)
.padding(end = 12.dp),
)
Column(
modifier = Modifier.fillMaxHeight(),
verticalArrangement = Arrangement.Center
) {
Text(
text = "Lorem Ipsum",
fontSize = 15.sp
)
Text(
text = "Lorem ipsum dolor sit amet...",
fontSize = 8.sp,
modifier = Modifier.padding(vertical = 8.dp)
)
}
}
}
在上例裡,我們用先 Column
及 Row
做出了一個左邊放一張正方形圖片、右上一句標題、右下一段文字,再把這些元件放在一個 Surface
裡,接著就可以透過 Modifier
設定其寬(300 dp)、高(100 dp)、形狀(圓角矩形)、海拔(決定下落式陰影的深淺)。
Box
元件Box
可以將包住的元件,依照程式碼從上而下的順序,依次將元件推疊在畫面上。若有 Web 前端經驗、寫過 CSS 的話,可以類比為寫在 Box
裡的每個元件,其 z 值一層一層加上去一樣。
Box(
modifier = Modifier.fillMaxSize(),
) {
Text(
text = "This text is drawn first",
modifier = Modifier.align(Alignment.TopCenter),
)
Box(
modifier = Modifier.align(Alignment.TopCenter)
.fillMaxHeight()
.width(50.dp)
.background(Color.Blue)
)
Text(
text = "This text is drawn last",
modifier = Modifier.align(Alignment.Center)
)
}
在上面的例子裡,最外層的 Box
被設定為撐到整個畫面,其內的第一個 Text
元件會第一個被繪製在畫面的中間靠上。第二個 Box
元件的高度被撐到整個畫面,寬度只有 50 dp,背景色為藍色,所以畫面看起來有一個直長條在正中央。也因為是第二個被繪製的元件,所以會壓過第一個繪製的 Text
元件重疊的部份。第三個 Text
元件會最後才被繪製在畫面的正中央,因為是最後一個繪製,所以會壓過第二個繪製的 Box
元件。
透過這個範例,就可以了解 Box
內元件層層疊疊的效果。
Spacer
元件還記得早期在做網頁切版時,有時為了精準的控制版面,會在頁面上放一個 1 x 1 像素的透明圖片,透過控制透明圖片的尺寸,來撐大或推擠畫面上的元素,以達成排版的效果,Spacer
的用途就像如此。使用它只需要用 Modifier
來控制它的寬高,就可以用這個「空間」來微調畫面上元件的位置:
var sliderPosition by remember { mutableStateOf(0f) }
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
Column(
modifier = Modifier.width(250.dp)
) {
Row(
modifier = Modifier.padding(end = 20.dp),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
imageVector = Icons.Filled.Favorite,
contentDescription = "Favorite Icon"
)
Spacer(
modifier = Modifier.width(ceil(sliderPosition * 100).dp)
)
Icon(
imageVector = Icons.Filled.Lock,
contentDescription = "Lock Icon"
)
}
Slider(
value = sliderPosition,
onValueChange = { sliderPosition = it },
)
}
}
在上面的例子裡,筆者試著將 Spacer
的寬度改變利用前面研究過的元件來做動態展示。首先將 Box
撐滿整個畫面,並將所有內容水平垂直置中,接著用 Column
切分上半部的 Row
及下半部的 Slider
,在 Row
裡面放兩個 Icon
,中間以 Spacer
隔開。最後,再透過 Slider
的操控,來調整 Spacer
的 modifier
參數裡,width
的寬度值,如此就能以視覺化的方式,了解 Spacer
在版面控制上的效果了。
透過今天的三個例子,將前面研究過的元件組合起來一起使用,讀者是不是可以逐漸感受到 Compose 的好用之處呢?