1

I am trying to fit the size of a sheet to its content. There is another question on StackOverflow addressing this topic.

However the problem is that GeometryReader does not seem to work properly when used inside a sheet, combined with the usage of multiline text.

This is a simple example demonstrating the issue.

struct DemoView: View {
    
    @State
    var isSheetShown = false
    
    let longText = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua."
    
    var content: some View {
        Text(longText)
    }
    
    @State
    private var sheetHeight: CGFloat = 0
    
    var body: some View {
        VStack(spacing: 20) {
            
            Button("Show sheet") {
                isSheetShown.toggle()
            }
            .sheet(isPresented: $isSheetShown) {
                self.content
                    .overlay {
                        GeometryReader { geometry in
                            let _ = print("Sheet height \(geometry.size.height)")
                            Color.clear.preference(key: InnerHeightPreferenceKey.self, value: geometry.size.height)
                        }
                    }
                    .onPreferenceChange(InnerHeightPreferenceKey.self) { newHeight in
                        self.sheetHeight = newHeight
                    }
                    .presentationDetents(
                        [.height(self.sheetHeight)]
                    )
            }
        }
    }
}

// MARK: - Preference Key

private struct InnerHeightPreferenceKey: PreferenceKey {
    
    static var defaultValue: CGFloat = .zero
    
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
        value = nextValue()
    }
}

When it is run, you will see in the console, that the body is rendered twice. In the first pass, the correct sheet height is calculated but then it's re-rendered and it seems to be adjusted to a smaller height, which leads to the text being cut of after one line.

Console output:

Sheet height 86.33333333333333
Sheet height 20.333333333333332

Incorrect sheet height

NOTE: When adding .lineLimit(nil) to Text(longText) doesn't change the behavior.

Strangely however, I can then also drag the sheet up, which leads to the desired sheet height being used, and the following additional console output:

Sheet height 42.33333333333333
Sheet height 64.33333333333333
Sheet height 86.33333333333333

Correct sheet height

Codey
  • 1,131
  • 2
  • 15
  • 34

0 Answers0