Reputation:
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
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
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