user10081458
user10081458

Reputation:

How to make a rectangle's height the same height of a VStack

I have a SwiftUI view that consists of an HStack with a rectangle and a VStack of text inside. I want to make the height of the rectangle the same as the height of the VStack. I have already tried looking through many other questions here on StackOverflow but I didn't find an answer. Can anyone help me do that?

Here is my code:

struct TodoView: View {
    @State var todos = ["feed the dog", "take the dog out for a walk", "make coffee"]
    @State var height: CGFloat = 45
    var body: some View {
        HStack{
            RoundedRectangle(cornerRadius: 2)
                .frame(width: 1)
                .foregroundColor(Color("lightGray"))
                .padding()
            VStack{
                
                Text("Todo")
                    .font(.title)
                ForEach(todos, id: \.self){ todo in
                    Text(todo)
                }
            }
            
            Spacer()

        }
    }
}

Upvotes: 1

Views: 1500

Answers (2)

andre
andre

Reputation: 883

Probably late for this, but actually, there’s no need for GeometryReader, you can do this instead:

var body: some View {
    HStack {
        RoundedRectangle(cornerRadius: 2)
            .frame(width: 1)
            .foregroundColor(Color("lightGray"))
            .padding()
            .frame(maxHeight: .infinity)

        VStack {
            Text("Todo")
                .font(.title)
            ForEach(todos, id: \.self) { todo in
                Text(todo)
            }
        }
        .frame(maxHeight: .infinity)

        Spacer()
    }
    .fixedSize(horizontal: false, vertical: true)
}

The key is to give each view infinite maximum height or width, which will automatically make it stretch to fill all the available space. You then apply fixedSize() to the container they are in, which tells SwiftUI those views should only take up the space they need.

https://www.hackingwithswift.com/quick-start/swiftui/how-to-make-two-views-the-same-width-or-height

Upvotes: 0

msk
msk

Reputation: 8905

You need to know the GeometryReader and PreferenceKey to make this possible.

struct SiblingHeightKey: PreferenceKey {
    static var defaultValue: CGSize? {
        nil
    }

    static func reduce(value: inout CGSize?, nextValue: () -> CGSize?) {
        value = value ?? nextValue()
    }
}

struct TodoView: View {
    @State var vStackSize: CGSize? = nil
    @State var todos = ["feed the dog", "take the dog out for a walk", "make coffee"]
    @State var height: CGFloat = 45
    var body: some View {
                HStack{
                    RoundedRectangle(cornerRadius: 2)
                        .foregroundColor(.gray)
                        .frame(width: self.vStackSize?.width, height: self.vStackSize?.height)
                    VStack{

                        Text("Todo")
                            .font(.title)
                        ForEach(todos, id: \.self){ todo in
                            Text(todo)
                        }
                    }.background(
                        GeometryReader { proxy in
                            Color.clear.preference(key: SiblingHeightKey.self, value: proxy.size)
                        }
                    )

                    Spacer()
                }.onPreferenceChange(SiblingHeightKey.self) {
                    self.vStackSize = $0
        }
    }
}

Upvotes: 3

Related Questions