[英]How to consistently separate elements on a HStack
I have a set of elements on a HStack
that are composed of a circle and some label text underneath it.我在HStack
上有一组元素,它们由一个圆圈和一些 label 文本组成。 These elements have a separation between them.这些元素之间有一个分隔。
Everything works as expected until one of the labels is bigger than the circle.一切都按预期工作,直到其中一个标签大于圆圈。 Then, the text increases the actual width of the element, making the visible separation between the circles, off.然后,文本增加了元素的实际宽度,使圆圈之间的可见分离关闭。
Is there any way to evenly separate the circles, ignoring the text?有什么方法可以均匀地分开圆圈,忽略文字?
struct Item: View {
let color: Color
let label: String
var body: some View {
VStack {
Circle()
.fill(color)
.frame(width: 40, height: 40)
Text(label)
}
}
}
struct ItemSeparation: View {
var body: some View {
HStack(alignment: .top, spacing: 30) {
Item(color: .yellow, label: "Berlin")
Item(color: .green, label: "Copenhagen")
Item(color: .blue, label: "Madrid")
Item(color: .purple, label: "Helsinki")
}
}
}
These two solutions have different compromises.这两种解决方案有不同的折衷方案。 You'll need to decide what happens, for example, if the views will be too wide for the parent view based on the longest label.您需要决定会发生什么,例如,如果视图对于基于最长 label 的父视图来说太宽。 Option 1 wraps the text.选项 1 换行文本。 Option 2 makes the view expand beyond its parent.选项 2 使视图扩展到其父级之外。
Option #1:选项1:
Use LazyVGrid
:使用LazyVGrid
:
struct ContentView: View {
let columns = [
GridItem(.flexible()),
GridItem(.flexible()),
GridItem(.flexible()),
GridItem(.flexible()),
]
var body: some View {
LazyVGrid(columns: columns, spacing: 30) {
Item(color: .yellow, label: "Berlin")
Item(color: .green, label: "Copenhagen")
Item(color: .blue, label: "Madrid")
Item(color: .purple, label: "Helsinki")
}
}
}
Option #2:选项#2:
Use a PreferenceKey
and a GeometryReader
to get the size of the widest View
and propagate the changes back up to the parent.使用PreferenceKey
和GeometryReader
获取最宽View
的大小并将更改传播回父级。
struct Item: View {
let color: Color
let label: String
let width: CGFloat
var body: some View {
VStack {
Circle()
.fill(color)
.frame(width: 40, height: 40)
Text(label)
}
.border(Color.blue)
.background(
GeometryReader {
Color.clear.preference(key: ViewWidthKey.self,
value: $0.size.width)
}.scaledToFill()
)
.frame(width: width)
}
}
struct ViewWidthKey: PreferenceKey {
static var defaultValue: CGFloat { 0 }
static func reduce(value: inout Value, nextValue: () -> Value) {
let nextValue = nextValue()
guard nextValue > value else { return }
value = nextValue
}
}
struct ContentView: View {
@State private var maxWidth : CGFloat = 0
var body: some View {
HStack(alignment: .top, spacing: 30) {
Item(color: .yellow, label: "Berlin", width: maxWidth)
Item(color: .green, label: "Copenhagen", width: maxWidth)
Item(color: .blue, label: "Madrid", width: maxWidth)
Item(color: .purple, label: "Helsinki", width: maxWidth)
}.onPreferenceChange(ViewWidthKey.self) { width in
self.maxWidth = width
print(width)
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.