Skip to Content

Button trong SwiftUI

1. Button cơ bản

Button("Tap Me") { print("Button tapped!") } // Action riêng Button(action: { print("Action executed") }) { Text("Click Here") }

2. Button với Label

Button { // Action } label: { Label("Add to Cart", systemImage: "cart.badge.plus") } Button { // Action } label: { HStack { Image(systemName: "heart.fill") Text("Like") } }

3. Button Styles

Built-in Styles

Button("Default") { } Button("Bordered") { } .buttonStyle(.bordered) Button("Bordered Prominent") { } .buttonStyle(.borderedProminent) Button("Borderless") { } .buttonStyle(.borderless) Button("Plain") { } .buttonStyle(.plain)

Tint Color

Button("Green Button") { } .buttonStyle(.borderedProminent) .tint(.green) Button("Red Button") { } .buttonStyle(.bordered) .tint(.red)

4. Custom Button Style

struct PrimaryButtonStyle: ButtonStyle { func makeBody(configuration: Configuration) -> some View { configuration.label .padding() .frame(maxWidth: .infinity) .background(configuration.isPressed ? .blue.opacity(0.8) : .blue) .foregroundColor(.white) .cornerRadius(12) .scaleEffect(configuration.isPressed ? 0.95 : 1.0) } } // Sử dụng Button("Login") { } .buttonStyle(PrimaryButtonStyle())

5. Custom Styled Buttons

// Pill Button Button { // Action } label: { Text("Subscribe") .fontWeight(.semibold) .padding(.horizontal, 24) .padding(.vertical, 12) .background(.blue) .foregroundColor(.white) .clipShape(Capsule()) } // Icon Button Button { // Action } label: { Image(systemName: "plus") .font(.title2) .foregroundColor(.white) .frame(width: 56, height: 56) .background(.blue) .clipShape(Circle()) .shadow(radius: 4) } // Outline Button Button { // Action } label: { Text("Cancel") .padding() .frame(maxWidth: .infinity) .overlay( RoundedRectangle(cornerRadius: 12) .stroke(.blue, lineWidth: 2) ) }

6. Button với State

struct ContentView: View { @State private var count = 0 @State private var isLoading = false var body: some View { VStack(spacing: 20) { // Counter HStack { Button("-") { count -= 1 } .buttonStyle(.bordered) Text("\(count)") .font(.title) .frame(width: 50) Button("+") { count += 1 } .buttonStyle(.bordered) } // Loading button Button { isLoading = true // Simulate async operation DispatchQueue.main.asyncAfter(deadline: .now() + 2) { isLoading = false } } label: { if isLoading { ProgressView() } else { Text("Submit") } } .buttonStyle(.borderedProminent) .disabled(isLoading) } } }

7. Button Roles

// Destructive role Button("Delete", role: .destructive) { // Delete action } // Cancel role Button("Cancel", role: .cancel) { // Cancel action } // Trong Alert .alert("Delete?", isPresented: $showAlert) { Button("Delete", role: .destructive) { } Button("Cancel", role: .cancel) { } }

8. Disabled State

struct FormView: View { @State private var email = "" var isValid: Bool { email.contains("@") } var body: some View { VStack { TextField("Email", text: $email) .textFieldStyle(.roundedBorder) Button("Submit") { // Submit } .buttonStyle(.borderedProminent) .disabled(!isValid) } .padding() } }
// Navigation NavigationStack { NavigationLink("Go to Detail") { DetailView() } .buttonStyle(.borderedProminent) } // Button với navigation struct ContentView: View { @State private var showDetail = false var body: some View { NavigationStack { Button("Show Detail") { showDetail = true } .navigationDestination(isPresented: $showDetail) { DetailView() } } } }

📝 Tóm tắt

StyleAppearance
.automaticMặc định
.borderedViền nhẹ
.borderedProminentNền màu primary
.borderlessKhông viền
.plainText thuần

Key modifiers: .buttonStyle(), .tint(), .disabled(), .role()

Last updated on