Reputation: 960
I have a VStack with three children. Each of those children have an HStack with some text and an empty space on the left. Here is a screenshot of the preview with a highlighted border around a VStack child, and one with a highlighted border around each HStack.
How do I set each VStack child to shrink to the height of the HStack and get rid of the empty space on the bottom? Right now the problem seems to be caused by the VStack by default filling the entire screen and setting each child to equal height.
Current Code:
import Foundation
import SwiftUI
struct NameAndConnection: View {
var body: some View {
VStack(alignment: .leading) {
Text(data.name)
.font(.headline)
.fontWeight(.semibold)
.foregroundColor(Color.black)
.frame(alignment: .leading)
Text(data.connection)
.font(.callout)
.fontWeight(.medium)
.foregroundColor(Color.gray)
.frame(alignment: .leading)
}
}
}
struct Description: View {
var body: some View {
Text(data.description)
}
}
struct Post: View {
var body: some View {
GeometryReader { geo in
HStack(alignment: .top, spacing: 0) {
Spacer()
VStack(alignment: .leading) {
NameAndConnection()
Description()
.padding(.top, 1.0)
}
.frame(width: geo.size.width * 0.75)
}
}
}
}
struct PostView: View {
var body: some View {
GeometryReader { geo in
VStack() {
Post()
Post()
Post()
}
}
}
}
Upvotes: 0
Views: 2340
Reputation: 52505
GeometryReader
will take up all available space. In general, it's widely considered good practice to try to use GeometryReader
sparingly and come up with other more flexible solutions for different screen sizes.
When you do have to use it, often it's helpful to measure the background of a View
-- that way, the View
itself won't grow as it would if the GeometryReader
were in the foreground. I've borrowed the GeometryReader
from: https://stackoverflow.com/a/59733037/560942
After you've removed the GeometryReader
s, you can use a Spacer
to push the other VStack
s to the top of the screen.
struct GeometryGetter: View {
@Binding var rect: CGRect
var body: some View {
GeometryReader { (g) -> Path in
print("width: \(g.size.width), height: \(g.size.height)")
DispatchQueue.main.async {
self.rect = g.frame(in: .global)
}
return Path() // could be some other dummy view
}
}
}
struct Post: View {
@State private var rect1: CGRect = CGRect()
var body: some View {
HStack(alignment: .top, spacing: 0) {
Spacer()
VStack(alignment: .leading) {
NameAndConnection()
Description()
.padding(.top, 1.0)
}.frame(width: rect1.width * 0.75)
}
.background(GeometryGetter(rect: $rect1))
.border(Color.green)
}
}
struct ContentView: View {
var body: some View {
VStack() {
Post()
Post()
Post()
Spacer()
}
}
}
Upvotes: 2