Button
1. Button cơ bản
Phần tiêu đề “1. Button cơ bản”Button("Tap Me") { print("Button tapped!")}
// Action riêngButton(action: { print("Action executed")}) { Text("Click Here")}2. Button với Label
Phần tiêu đề “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
Phần tiêu đề “3. Button Styles”Built-in Styles
Phần tiêu đề “Built-in Styles”Button("Default") { }
Button("Bordered") { } .buttonStyle(.bordered)
Button("Bordered Prominent") { } .buttonStyle(.borderedProminent)
Button("Borderless") { } .buttonStyle(.borderless)
Button("Plain") { } .buttonStyle(.plain)Tint Color
Phần tiêu đề “Tint Color”Button("Green Button") { } .buttonStyle(.borderedProminent) .tint(.green)
Button("Red Button") { } .buttonStyle(.bordered) .tint(.red)4. Custom Button Style
Phần tiêu đề “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ụngButton("Login") { } .buttonStyle(PrimaryButtonStyle())5. Custom Styled Buttons
Phần tiêu đề “5. Custom Styled Buttons”// Pill ButtonButton { // Action} label: { Text("Subscribe") .fontWeight(.semibold) .padding(.horizontal, 24) .padding(.vertical, 12) .background(.blue) .foregroundColor(.white) .clipShape(Capsule())}
// Icon ButtonButton { // Action} label: { Image(systemName: "plus") .font(.title2) .foregroundColor(.white) .frame(width: 56, height: 56) .background(.blue) .clipShape(Circle()) .shadow(radius: 4)}
// Outline ButtonButton { // Action} label: { Text("Cancel") .padding() .frame(maxWidth: .infinity) .overlay( RoundedRectangle(cornerRadius: 12) .stroke(.blue, lineWidth: 2) )}6. Button với State
Phần tiêu đề “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
Phần tiêu đề “7. Button Roles”// Destructive roleButton("Delete", role: .destructive) { // Delete action}
// Cancel roleButton("Cancel", role: .cancel) { // Cancel action}
// Trong Alert.alert("Delete?", isPresented: $showAlert) { Button("Delete", role: .destructive) { } Button("Cancel", role: .cancel) { }}8. Disabled State
Phần tiêu đề “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() }}9. NavigationLink vs Button
Phần tiêu đề “9. NavigationLink vs Button”// NavigationNavigationStack { NavigationLink("Go to Detail") { DetailView() } .buttonStyle(.borderedProminent)}
// Button với navigationstruct 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
Phần tiêu đề “📝 Tóm tắt”| Style | Appearance |
|---|---|
.automatic |
Mặc định |
.bordered |
Viền nhẹ |
.borderedProminent |
Nền màu primary |
.borderless |
Không viền |
.plain |
Text thuần |
Key modifiers: .buttonStyle(), .tint(), .disabled(), .role()