Skip to Content

Button và IconButton

Hướng dẫn sử dụng các loại Button trong Compose Multiplatform.

Các loại Button

@Composable fun ButtonTypes() { Column( modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(12.dp) ) { // Filled Button (Primary) Button(onClick = { }) { Text("Filled Button") } // Outlined Button OutlinedButton(onClick = { }) { Text("Outlined Button") } // Text Button TextButton(onClick = { }) { Text("Text Button") } // Elevated Button ElevatedButton(onClick = { }) { Text("Elevated Button") } // Filled Tonal Button FilledTonalButton(onClick = { }) { Text("Tonal Button") } } }

Button với Icon

@Composable fun ButtonsWithIcons() { Column(verticalArrangement = Arrangement.spacedBy(12.dp)) { // Icon ở đầu Button(onClick = { }) { Icon( Icons.Default.Add, contentDescription = null, modifier = Modifier.size(18.dp) ) Spacer(Modifier.width(8.dp)) Text("Add Item") } // Icon ở cuối Button(onClick = { }) { Text("Next") Spacer(Modifier.width(8.dp)) Icon( Icons.Default.ArrowForward, contentDescription = null, modifier = Modifier.size(18.dp) ) } // Outlined với icon OutlinedButton(onClick = { }) { Icon(Icons.Default.Share, contentDescription = null) Spacer(Modifier.width(8.dp)) Text("Share") } } }

IconButton

@Composable fun IconButtons() { Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { // Standard IconButton IconButton(onClick = { }) { Icon(Icons.Default.Favorite, contentDescription = "Like") } // Filled IconButton FilledIconButton(onClick = { }) { Icon(Icons.Default.Add, contentDescription = "Add") } // Outlined IconButton OutlinedIconButton(onClick = { }) { Icon(Icons.Default.Edit, contentDescription = "Edit") } // Tonal IconButton FilledTonalIconButton(onClick = { }) { Icon(Icons.Default.Share, contentDescription = "Share") } } }

Toggle IconButton

@Composable fun ToggleIconButtonExample() { var isFavorite by remember { mutableStateOf(false) } IconButton( onClick = { isFavorite = !isFavorite } ) { Icon( imageVector = if (isFavorite) Icons.Filled.Favorite else Icons.Outlined.FavoriteBorder, contentDescription = "Favorite", tint = if (isFavorite) Color.Red else Color.Gray ) } }

Floating Action Button

@Composable fun FABExamples() { Column(verticalArrangement = Arrangement.spacedBy(16.dp)) { // Standard FAB FloatingActionButton(onClick = { }) { Icon(Icons.Default.Add, contentDescription = "Add") } // Small FAB SmallFloatingActionButton(onClick = { }) { Icon(Icons.Default.Add, contentDescription = "Add") } // Large FAB LargeFloatingActionButton(onClick = { }) { Icon( Icons.Default.Add, contentDescription = "Add", modifier = Modifier.size(36.dp) ) } // Extended FAB ExtendedFloatingActionButton( onClick = { }, icon = { Icon(Icons.Default.Add, contentDescription = null) }, text = { Text("Create") } ) } }

Custom Button Styling

@Composable fun CustomStyledButtons() { Column(verticalArrangement = Arrangement.spacedBy(12.dp)) { // Custom colors Button( onClick = { }, colors = ButtonDefaults.buttonColors( containerColor = Color(0xFF6200EE), contentColor = Color.White ) ) { Text("Custom Color") } // Custom shape Button( onClick = { }, shape = RoundedCornerShape(50) // Pill shape ) { Text("Rounded Button") } // Full width Button( onClick = { }, modifier = Modifier .fillMaxWidth() .height(56.dp), shape = RoundedCornerShape(12.dp) ) { Text("Full Width Button") } // Gradient button Box( modifier = Modifier .fillMaxWidth() .height(56.dp) .background( brush = Brush.horizontalGradient( colors = listOf(Color(0xFF6200EE), Color(0xFFBB86FC)) ), shape = RoundedCornerShape(12.dp) ) .clickable { }, contentAlignment = Alignment.Center ) { Text("Gradient Button", color = Color.White) } } }

Button States

@Composable fun ButtonWithStates() { var isLoading by remember { mutableStateOf(false) } Button( onClick = { isLoading = true // Simulate loading }, enabled = !isLoading, modifier = Modifier .fillMaxWidth() .height(56.dp) ) { if (isLoading) { CircularProgressIndicator( modifier = Modifier.size(24.dp), color = MaterialTheme.colorScheme.onPrimary, strokeWidth = 2.dp ) } else { Text("Submit") } } }

Disabled states

@Composable fun DisabledButtons() { Column(verticalArrangement = Arrangement.spacedBy(12.dp)) { Button( onClick = { }, enabled = false ) { Text("Disabled Filled") } OutlinedButton( onClick = { }, enabled = false ) { Text("Disabled Outlined") } TextButton( onClick = { }, enabled = false ) { Text("Disabled Text") } } }

Reusable Button Component

@Composable fun AppButton( text: String, onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, isLoading: Boolean = false, leadingIcon: ImageVector? = null, trailingIcon: ImageVector? = null ) { Button( onClick = onClick, modifier = modifier.height(52.dp), enabled = enabled && !isLoading, shape = RoundedCornerShape(12.dp) ) { if (isLoading) { CircularProgressIndicator( modifier = Modifier.size(20.dp), color = MaterialTheme.colorScheme.onPrimary, strokeWidth = 2.dp ) } else { leadingIcon?.let { Icon(it, contentDescription = null, modifier = Modifier.size(20.dp)) Spacer(Modifier.width(8.dp)) } Text(text, style = MaterialTheme.typography.labelLarge) trailingIcon?.let { Spacer(Modifier.width(8.dp)) Icon(it, contentDescription = null, modifier = Modifier.size(20.dp)) } } } } // Sử dụng @Composable fun Example() { Column { AppButton( text = "Login", onClick = { }, leadingIcon = Icons.Default.Login ) AppButton( text = "Loading...", onClick = { }, isLoading = true ) } }

📝 Tóm tắt

Button TypeUse Case
ButtonPrimary action
OutlinedButtonSecondary action
TextButtonLow emphasis
ElevatedButtonMedium emphasis
FilledTonalButtonMedium emphasis, softer
FloatingActionButtonMain screen action
IconButtonIcon-only actions

Tiếp theo

Học về Layout - Row, Column, Box.

Last updated on