Search code examples
swiftswiftui

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

        }
    }
}

Solution

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