1

First off, I'm trying to learn SwiftUI so I may not have a full understanding of how it works.

I have an array of sentences that I use in a ForEach loop, that creates a GeometryReader with a Text view for each sentence.

The length of each sentence might not be the same, therefore the Text view may have multiple lines so the entire sentence fits. This means I need each GeometryReader to set its height according to the height of its child view (the Text view) so they don't overlap and get as much space as they need.

I found someone here on stackoverflow with the same problem and tried to do the same in my code. Unfortunately, it gets only the first GeometryReader's height and uses it on all of them. So those GeometryReader's that should have a smaller height than the first, are getting the same amount.

It should be said the reason I use GeometryReader, is to get each Text view to change based on their location on screen. I have not reached that point in my development yet, though, but I'm going to use it later. Right now I'm stuck at setting each GeometryReader's height as they need to be.

Here's my code and how it looks on Preview:

struct ContentView: View {
    
    @State var sentences: [String] = ["Lorem ipsum dolor sit amet, consectetur adipiscing elit.", "Lorem ipsum dolor", "Praesent in ligula in libero ullamcorper finibus.", "Etiam tortor orci", "Morbi porttitor vehicula tincidunt."]
    @State private var fitHeight = CGFloat(0)
    
    var body: some View {
        ScrollView{
            ForEach(sentences, id: \.self) { sentence in
                GeometryReader { geo in
                    Text(sentence)
                        .font(.title.bold())
                        .fixedSize(horizontal: false, vertical: true)
                        .multilineTextAlignment(.leading)
                        .background(
                            GeometryReader { proxy in
                                Color.clear.preference(key: ViewHeightKey.self, value: proxy.frame(in: .local).size.height)
                            }
                        )
                        .padding()
                        
                }
                .onPreferenceChange(ViewHeightKey.self) { self.fitHeight = $0 }
                .frame(height: fitHeight)
            }
        }
    }
}

struct ViewHeightKey: PreferenceKey {
    typealias Value = CGFloat
    static var defaultValue = CGFloat.zero
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value += nextValue()
    }
}

This is how my code looks on the simulator

As you can see, the first GeometryReader sets its own height at what its Text views height is. Great!

Then the next GeometryReader's Text view is only one line high so it does not need to be as high as the first, but for some reason, it sets it height to the same as the first GeometryReader. Notice the white space between the "Lorem ipsum dolor" Text view and the "Praesent in ligula in libero ullamcorper finibus". That happens because the second GeometryReader's height is more than it needs.

It's almost like fitHeight does not get updated between the creation of each GeometryReader.

Try to change the Color.clear to something like Color.gray to see how big the Text views render themselves.

How do I make it so each GeometryReader sets its own height based on the height of its child view?

Thanks in advance!

Holger
  • 69
  • 1
  • 4
  • Does this answer your question? [How to add a modifier to any specific buttons inside a ForEach loop for an array of buttons in SwiftUI?](https://stackoverflow.com/questions/70139071/how-to-add-a-modifier-to-any-specific-buttons-inside-a-foreach-loop-for-an-array) – lorem ipsum Mar 27 '22 at 12:08
  • I don't understand the goal of GeometryReader/s here. Text is capable to layout multiline strings by itself in such scenarios, so ... ? – Asperi Mar 27 '22 at 12:09
  • @Asperi I’m going to use GeometryReader to get the position of each text view to change a modifier on the text view later on. – Holger Mar 27 '22 at 15:48
  • @loremipsum no, that doesn’t seem to help. Thanks though! – Holger Mar 27 '22 at 15:50

0 Answers0