Layout - Row, Column, Box
Hướng dẫn sử dụng các layout cơ bản trong Compose Multiplatform.
Column - Xếp dọc
@Composable
fun ColumnExample() {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Item 1")
Text("Item 2")
Text("Item 3")
}
}Vertical Arrangement
@Composable
fun ColumnArrangements() {
val items = listOf("A", "B", "C")
Row(modifier = Modifier.fillMaxWidth()) {
// Top (default)
Column(
modifier = Modifier.weight(1f).height(200.dp).background(Color.LightGray),
verticalArrangement = Arrangement.Top
) {
items.forEach { Text(it) }
}
// Center
Column(
modifier = Modifier.weight(1f).height(200.dp).background(Color.Gray),
verticalArrangement = Arrangement.Center
) {
items.forEach { Text(it) }
}
// Bottom
Column(
modifier = Modifier.weight(1f).height(200.dp).background(Color.DarkGray),
verticalArrangement = Arrangement.Bottom
) {
items.forEach { Text(it, color = Color.White) }
}
// SpaceBetween
Column(
modifier = Modifier.weight(1f).height(200.dp).background(Color.LightGray),
verticalArrangement = Arrangement.SpaceBetween
) {
items.forEach { Text(it) }
}
// SpaceEvenly
Column(
modifier = Modifier.weight(1f).height(200.dp).background(Color.Gray),
verticalArrangement = Arrangement.SpaceEvenly
) {
items.forEach { Text(it) }
}
}
}Row - Xếp ngang
@Composable
fun RowExample() {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Icon(Icons.Default.Menu, contentDescription = null)
Text("Title")
Icon(Icons.Default.Settings, contentDescription = null)
}
}Weight modifier
@Composable
fun RowWithWeight() {
Row(modifier = Modifier.fillMaxWidth()) {
// Chiếm 1 phần
Box(
modifier = Modifier
.weight(1f)
.height(50.dp)
.background(Color.Red)
)
// Chiếm 2 phần
Box(
modifier = Modifier
.weight(2f)
.height(50.dp)
.background(Color.Green)
)
// Chiếm 1 phần
Box(
modifier = Modifier
.weight(1f)
.height(50.dp)
.background(Color.Blue)
)
}
}Box - Xếp chồng
@Composable
fun BoxExample() {
Box(
modifier = Modifier
.size(200.dp)
.background(Color.LightGray)
) {
// Bottom layer
Text(
"Bottom",
modifier = Modifier.align(Alignment.BottomStart)
)
// Middle layer
Box(
modifier = Modifier
.size(100.dp)
.background(Color.Blue)
.align(Alignment.Center)
)
// Top layer
Text(
"Top",
modifier = Modifier.align(Alignment.TopEnd),
color = Color.White
)
}
}Box Alignment
@Composable
fun BoxAlignments() {
Box(
modifier = Modifier
.size(200.dp)
.background(Color.LightGray)
) {
Text("TopStart", Modifier.align(Alignment.TopStart))
Text("TopCenter", Modifier.align(Alignment.TopCenter))
Text("TopEnd", Modifier.align(Alignment.TopEnd))
Text("CenterStart", Modifier.align(Alignment.CenterStart))
Text("Center", Modifier.align(Alignment.Center))
Text("CenterEnd", Modifier.align(Alignment.CenterEnd))
Text("BottomStart", Modifier.align(Alignment.BottomStart))
Text("BottomCenter", Modifier.align(Alignment.BottomCenter))
Text("BottomEnd", Modifier.align(Alignment.BottomEnd))
}
}Spacer
@Composable
fun SpacerExamples() {
Column {
Text("Item 1")
Spacer(Modifier.height(16.dp))
Text("Item 2")
Spacer(Modifier.height(32.dp))
Text("Item 3")
}
Row {
Text("Left")
Spacer(Modifier.weight(1f)) // Push to edges
Text("Right")
}
}Modifier Order Matters
@Composable
fun ModifierOrderExample() {
Row {
// Padding THEN background
Box(
modifier = Modifier
.padding(16.dp)
.background(Color.Red)
.size(50.dp)
)
// Background THEN padding
Box(
modifier = Modifier
.background(Color.Blue)
.padding(16.dp)
.size(50.dp)
)
}
}Common Patterns
Card Layout
@Composable
fun CardLayout() {
Card(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(12.dp)
) {
Row(
modifier = Modifier.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
// Avatar
Box(
modifier = Modifier
.size(48.dp)
.background(Color.Gray, CircleShape),
contentAlignment = Alignment.Center
) {
Text("JD", color = Color.White)
}
Spacer(Modifier.width(16.dp))
// Content
Column(modifier = Modifier.weight(1f)) {
Text("John Doe", fontWeight = FontWeight.Bold)
Text("john@example.com", color = Color.Gray)
}
// Action
IconButton(onClick = { }) {
Icon(Icons.Default.ChevronRight, contentDescription = null)
}
}
}
}Header + Content + Footer
@Composable
fun ScreenLayout() {
Column(modifier = Modifier.fillMaxSize()) {
// Header
TopAppBar(
title = { Text("Screen Title") }
)
// Content - takes remaining space
Box(
modifier = Modifier
.weight(1f)
.fillMaxWidth()
) {
// Main content here
Text("Content", modifier = Modifier.align(Alignment.Center))
}
// Footer
BottomAppBar {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly
) {
IconButton(onClick = { }) {
Icon(Icons.Default.Home, contentDescription = "Home")
}
IconButton(onClick = { }) {
Icon(Icons.Default.Search, contentDescription = "Search")
}
IconButton(onClick = { }) {
Icon(Icons.Default.Person, contentDescription = "Profile")
}
}
}
}
}Overlay Pattern
@Composable
fun OverlayPattern() {
Box(modifier = Modifier.fillMaxSize()) {
// Main content
LazyColumn(modifier = Modifier.fillMaxSize()) {
items(50) { index ->
Text("Item $index", modifier = Modifier.padding(16.dp))
}
}
// FAB overlay
FloatingActionButton(
onClick = { },
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(16.dp)
) {
Icon(Icons.Default.Add, contentDescription = "Add")
}
// Loading overlay
if (false) { // isLoading
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.Black.copy(alpha = 0.5f)),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator()
}
}
}
}📝 Tóm tắt
| Layout | Mục đích |
|---|---|
Column | Xếp children theo chiều dọc |
Row | Xếp children theo chiều ngang |
Box | Xếp chồng children |
Spacer | Tạo khoảng trống |
| Modifier | Mô tả |
|---|---|
weight() | Chia tỷ lệ trong Row/Column |
align() | Căn chỉnh trong Box |
fillMaxSize/Width/Height | Fill parent |
padding() | Thêm padding |
Tiếp theo
Học về LazyColumn và LazyRow.
Last updated on