Custom Alignment within ZStack
Last updated
Last updated
💡 雖然下面的例子使用自製對齊線,但討論區裡的做法可能比較快。
/// ⭐️ 1. define custom vertical alignment (for cap height)
extension VerticalAlignment {
private struct CapHeightAlignment: AlignmentID {
static func defaultValue(in context: ViewDimensions) -> CGFloat {
context[VerticalAlignment.firstTextBaseline]
}
}
static let capHeight = VerticalAlignment(
CapHeightAlignment.self
)
}
/// ⭐️ 2. define custom horizontal alignment (for "second" leading)
extension HorizontalAlignment {
private struct SecondLeadingAlignment: AlignmentID {
static func defaultValue(in context: ViewDimensions) -> CGFloat {
context[.leading]
}
}
static let secondLeading = HorizontalAlignment(
SecondLeadingAlignment.self
)
}
struct View1: View {
/// ⭐️ Unfortunately, we still have to use `UIFont`
/// to access the `.capHeight` property.
let bigFont = UIFont.systemFont(ofSize: 70)
let smallFont = UIFont.systemFont(ofSize: 24)
var body: some View {
/// ⭐️ ZStack 內部使用自製的對齊線
ZStack(alignment: Alignment(
horizontal: .secondLeading, vertical: .capHeight
)) {
/// HStack 內部以 `.firstTextBaseline` 排版,
/// "7" 與 "kts" 底線對齊。
HStack(alignment: .firstTextBaseline, spacing: 3) {
Text("7")
.font(.system(size: 70))
.foregroundColor(Color.green)
/// ⭐️ "7" 與 ".0" 垂直方向以 `.capHeight` 對齊
.alignmentGuide(.capHeight) { dim in
// ⭐️ 但必須手動調整 `.capHeight` 對齊線的位置。
dim[.firstTextBaseline] - bigFont.capHeight
}
Text("kts")
.font(.system(size: 18))
/// ⭐️ "kts" 與 ".0" 水平方向以 `.secondLeading` 對齊
.alignmentGuide(.secondLeading) { $0[.leading] }
}.baseLine(color: .blue)
Text(".0")
.font(.system(size: 24))
.foregroundColor(Color.green)
/// ⭐️ "kts" 與 ".0" 水平方向以 `.secondLeading` 對齊
.alignmentGuide(.secondLeading){ $0[.leading] }
/// ⭐️ "7" 與 ".0" 垂直方向以 `.capHeight` 對齊
.alignmentGuide(.capHeight) { dim in
// ⭐️ 但必須手動調整 `.capHeight` 對齊線的位置。
dim[.firstTextBaseline] - smallFont.capHeight
}
}.overlay(HLine(), alignment: Alignment(
horizontal: .center, vertical: .capHeight
)).overlay(VLine(), alignment: Alignment(
horizontal: .secondLeading, vertical: .center
))
}
}