Implicit Alignment
Last updated
Was this helpful?
Last updated
Was this helpful?
在 HStack, VStack, ZStack 等 container 內的 view 都有預設的 alignment guide,如果 view 本身沒有直接使用 .alignmentGuide() 來設定,那麼 view 就會使用 container 所指定的 alignmenet 來對齊。
import SwiftUI
/// ⭐️ 自訂水平方向的對齊線 `.firstView`
extension HorizontalAlignment {
private struct FirstViewAlignment: AlignmentID {
static func defaultValue(in dim: ViewDimensions) -> CGFloat {
dim[.leading]
}
}
static let firstView = HorizontalAlignment(
FirstViewAlignment.self
)
}
struct ImplicitAlign: View {
@State private var alignment: HorizontalAlignment = .leading
@State private var selection: String = "leading"
let keys = ["leading", "center", "trailing"]
let alignments: [String:HorizontalAlignment] = [
"leading": .leading, "center": .center, "trailing": .trailing
]
var body: some View {
VStack {
labelViews
picker
}.frame(maxHeight: .infinity).background(Color.gray)
}
/// vertical line
var line: some View {
VLine(color: .yellow).shadow(radius: 2)
}
/// segmented control
var picker: some View {
Picker("Align", selection: $selection) {
ForEach(0..<3){ Text(keys[$0]).tag(keys[$0]) }
}
.pickerStyle(.segmented).shadow(radius: 2)
.padding()
// ⭐️ animate the change when `selection` changes
.onChange(of: selection) { newSelection in
withAnimation(.easeOut(duration: 1)) {
self.alignment = alignments[newSelection]!
}
}
}
var labelViews: some View {
// VStack 內部以 `alignment` 對齊
VStack(alignment: alignment) {
LabelView(title: "Implicit", color: .red)
// ⭐️ 將 `.firstView` 的對齊線調整成跟 `alignment` 一樣
.alignmentGuide(.firstView) { $0[alignment] }
LabelView(title: "Explicit 1", color: .green)
.alignmentGuide(.leading) { _ in 30 }
.alignmentGuide(HorizontalAlignment.center) { _ in 30 }
.alignmentGuide(.trailing) { _ in 90 }
LabelView(title: "Explicit 2", color: .blue)
.alignmentGuide(.leading) { _ in 90 }
.alignmentGuide(HorizontalAlignment.center){ _ in 30 }
.alignmentGuide(.trailing) { _ in 30 }
}.padding().overlay(line, alignment: Alignment(
// ⭐️ 垂直線 `line` 對齊 `.firstView`
horizontal: .firstView, vertical: .center
))
}
}
struct LabelView: View {
let title: String
let color: Color
var body: some View {
Text(title)
.font(.title)
.foregroundColor(.white)
.padding(10)
.frame(width: 200, height: 40)
.background(LinearGradient(
gradient: Gradient(colors: [color, .black]),
startPoint: UnitPoint(x: 0, y: 0),
endPoint: UnitPoint(x: 2, y: 1)
))
.shadow(radius: 3)
}
}
SwiftUI ⟩ View ⟩ Input and Events
onChange(of:perform:) ⭐️ - fires an action when a specific value changes.
SwiftUI Lab ⟩ Alignment Guides in SwiftUI
Hacking with Swift ⟩ How to run some code when state changes using onChange()
Developer ⟩ @State + didSet Property Observer