Building Custom SwiftUI Components
Reusable components are the foundation of great app architecture. Let’s build some custom SwiftUI views.
Reusable Button Styles
struct PrimaryButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.font(.headline)
.foregroundColor(.white)
.padding()
.background(Color.blue)
.cornerRadius(12)
.scaleEffect(configuration.isPressed ? 0.95 : 1.0)
.animation(.easeInOut(duration: 0.1), value: configuration.isPressed)
}
}
struct SecondaryButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.font(.headline)
.foregroundColor(.blue)
.padding()
.background(Color.blue.opacity(0.1))
.cornerRadius(12)
.scaleEffect(configuration.isPressed ? 0.95 : 1.0)
}
}
Custom Toggle Style
struct CustomToggleStyle: ToggleStyle {
func makeBody(configuration: Configuration) -> some View {
HStack {
configuration.label
Spacer()
RoundedRectangle(cornerRadius: 16)
.fill(configuration.isOn ? Color.green : Color.gray.opacity(0.3))
.frame(width: 50, height: 30)
.overlay(
Circle()
.fill(Color.white)
.padding(4)
.offset(x: configuration.isOn ? 10 : -10)
.animation(.spring(), value: configuration.isOn)
)
.onTapGesture {
configuration.isOn.toggle()
}
}
}
}
Loading Indicator
struct LoadingView: View {
@State private var isAnimating = false
var body: some View {
Circle()
.trim(from: 0, to: 0.7)
.stroke(Color.blue, lineWidth: 4)
.frame(width: 40, height: 40)
.rotationEffect(.degrees(isAnimating ? 360 : 0))
.animation(
.linear(duration: 1).repeatForever(autoreverses: false),
value: isAnimating
)
.onAppear {
isAnimating = true
}
}
}
Building reusable components takes time upfront but pays dividends as your app grows.