For the width:
They have already got the identical width, however you cant see it since you apply the peak after setting the background. So reorder the modifiers to make it seen:
struct TestViewHStack: View {
let strings = ["Short", "some long text", "short"]
var physique: some View {
HStack {
ForEach(strings, id: .self) { title in
CardView(title: title)
// .body(maxWidth: .infinity) // 👈 That is after the background framing
}
}
}
}
struct CardView: View {
let title: String
var physique: some View {
VStack(spacing: 8) {
Picture(systemName: "star.fill")
.resizable()
.body(width: 20, top: 20)
Textual content(title)
.font(.subheadline)
}
.padding(16)
.body(maxWidth: .infinity) // 👈 This does the job as anticipated
.background(Coloration.white)
.clipShape(RoundedRectangle(cornerRadius: 16))
.shadow(coloration: .grey.opacity(0.2), radius: 8, x: 0, y: 2)
}
}
Seen Equal Widths Demo:
For the peak:
In case you simply want a hard and fast top, simply add a maxHeight
to the body and management the peak of the stack.
However it looks as if you do not know the peak and also you want all objects to have the identical dimension with the tallest one. So it’s essential allow them to dimension themselves and replace anybody with the shorter top. That is the place onPreferenceChange
is available in and requires some work.
struct TestViewHStack: View {
let strings = ["Short", "some long text", "short"]
@State non-public var maxCardHeight: CGFloat = 10
var physique: some View {
HStack {
ForEach(strings, id: .self) { title in
CardView(title: title)
.fixedSize(horizontal: false, vertical: true)
.background {
GeometryReader { proxy in
Coloration.clear.choice(
key: MaxValue.self,
worth: proxy.dimension.top
)
}
}
.onPreferenceChange(MaxValue.self) {
maxCardHeight = $0
}
.body(maxWidth: .infinity, maxHeight: maxCardHeight)
.background(Coloration.white)
.clipShape(RoundedRectangle(cornerRadius: 16))
.shadow(coloration: .grey.opacity(0.2), radius: 8, x: 0, y: 2)
}
}
}
}
public enum MaxValue: PreferenceKey {
public static let defaultValue = CGFloat()
public static func scale back(worth: inout Worth, nextValue: () -> Worth) {
print("worth: (worth), subsequent: (nextValue())")
worth = max(worth, nextValue())
}
}
struct CardView: View {
let title: String
var physique: some View {
VStack(spacing: 8) {
Picture(systemName: "star.fill")
.resizable()
.body(width: 20, top: 20)
Textual content(title)
.font(.subheadline)
}
.padding(16)
}
}
Word that you will need to first dimension after which apply the background. So It’s worthwhile to rearrange your UI logic