在排版 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 的好用之處呢?