Shapes trong SwiftUI
1. Các Shape cơ bản
// Rectangle
Rectangle()
.fill(.blue)
.frame(width: 100, height: 100)
// Rounded Rectangle
RoundedRectangle(cornerRadius: 16)
.fill(.green)
.frame(width: 150, height: 100)
// Circle
Circle()
.fill(.red)
.frame(width: 100, height: 100)
// Ellipse
Ellipse()
.fill(.orange)
.frame(width: 150, height: 100)
// Capsule
Capsule()
.fill(.purple)
.frame(width: 150, height: 50)2. Fill và Stroke
// Fill
Circle()
.fill(.blue)
.frame(width: 100, height: 100)
// Stroke (viền)
Circle()
.stroke(.blue, lineWidth: 4)
.frame(width: 100, height: 100)
// Stroke style
Circle()
.stroke(.red, style: StrokeStyle(
lineWidth: 4,
lineCap: .round,
lineJoin: .round,
dash: [10, 5] // Dashed line
))
.frame(width: 100, height: 100)
// Fill + Stroke
ZStack {
Circle()
.fill(.blue.opacity(0.3))
Circle()
.stroke(.blue, lineWidth: 3)
}
.frame(width: 100, height: 100)3. Gradient Fills
// Linear Gradient
Rectangle()
.fill(
LinearGradient(
colors: [.blue, .purple],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
)
.frame(width: 200, height: 100)
// Radial Gradient
Circle()
.fill(
RadialGradient(
colors: [.yellow, .orange, .red],
center: .center,
startRadius: 0,
endRadius: 100
)
)
.frame(width: 200, height: 200)
// Angular Gradient
Circle()
.fill(
AngularGradient(
colors: [.red, .orange, .yellow, .green, .blue, .purple, .red],
center: .center
)
)
.frame(width: 200, height: 200)4. Custom Shapes
struct Triangle: Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to: CGPoint(x: rect.midX, y: rect.minY))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.closeSubpath()
return path
}
}
// Sử dụng
Triangle()
.fill(.orange)
.frame(width: 100, height: 100)Star Shape
struct Star: Shape {
let points: Int
let innerRatio: CGFloat
func path(in rect: CGRect) -> Path {
let center = CGPoint(x: rect.midX, y: rect.midY)
let outerRadius = min(rect.width, rect.height) / 2
let innerRadius = outerRadius * innerRatio
var path = Path()
let angleIncrement = .pi * 2 / CGFloat(points * 2)
for i in 0..<(points * 2) {
let radius = i.isMultiple(of: 2) ? outerRadius : innerRadius
let angle = CGFloat(i) * angleIncrement - .pi / 2
let point = CGPoint(
x: center.x + cos(angle) * radius,
y: center.y + sin(angle) * radius
)
if i == 0 {
path.move(to: point)
} else {
path.addLine(to: point)
}
}
path.closeSubpath()
return path
}
}
Star(points: 5, innerRatio: 0.4)
.fill(.yellow)
.frame(width: 100, height: 100)5. clipShape
// Clip image thành hình tròn
Image("avatar")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 100, height: 100)
.clipShape(Circle())
// Clip với RoundedRectangle
Image("banner")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 300, height: 200)
.clipShape(RoundedRectangle(cornerRadius: 20))6. Overlay và Background
// Badge
Text("5")
.font(.caption)
.foregroundColor(.white)
.padding(8)
.background(Circle().fill(.red))
// Card với shadow
VStack {
Text("Card Content")
}
.padding()
.background(
RoundedRectangle(cornerRadius: 16)
.fill(.white)
.shadow(color: .black.opacity(0.1), radius: 8, x: 0, y: 4)
)
// Outlined shape
Circle()
.fill(.blue.opacity(0.1))
.overlay(
Circle()
.stroke(.blue, lineWidth: 2)
)
.frame(width: 100, height: 100)7. Shapes với Animation
struct AnimatedCircle: View {
@State private var isAnimating = false
var body: some View {
Circle()
.stroke(
LinearGradient(
colors: [.blue, .purple],
startPoint: .topLeading,
endPoint: .bottomTrailing
),
lineWidth: 8
)
.frame(width: 100, height: 100)
.rotationEffect(.degrees(isAnimating ? 360 : 0))
.animation(
.linear(duration: 2).repeatForever(autoreverses: false),
value: isAnimating
)
.onAppear {
isAnimating = true
}
}
}8. Progress Indicators
struct CircularProgress: View {
var progress: Double // 0.0 - 1.0
var body: some View {
ZStack {
// Background circle
Circle()
.stroke(.gray.opacity(0.2), lineWidth: 10)
// Progress circle
Circle()
.trim(from: 0, to: progress)
.stroke(
.blue,
style: StrokeStyle(lineWidth: 10, lineCap: .round)
)
.rotationEffect(.degrees(-90))
// Text
Text("\(Int(progress * 100))%")
.font(.title2.bold())
}
.frame(width: 100, height: 100)
}
}
CircularProgress(progress: 0.75)📝 Tóm tắt
| Shape | Mô tả |
|---|---|
Rectangle | Hình chữ nhật |
RoundedRectangle | HCN bo góc |
Circle | Hình tròn |
Ellipse | Hình elip |
Capsule | Hình viên thuốc |
Key modifiers: .fill(), .stroke(), .clipShape(), .overlay()
Last updated on