9.1 C
London
Tuesday, April 2, 2024

ios – SwiftUI HStack interior Views have fill complete width equally and have similar top, whatever the content material


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:

Demo 1

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)
    }
}

Demo 2
Word that you will need to first dimension after which apply the background. So It’s worthwhile to rearrange your UI logic

Latest news
Related news

LEAVE A REPLY

Please enter your comment!
Please enter your name here