8.2 C
New York
Tuesday, April 8, 2025

ios – Surprising ViewThatFits Habits: Why My ScrollView Isn’t Rendering for Massive Content material in SwiftUI


I need to show my content material as-is, centered vertically, if it suits throughout the display peak.

I solely need to wrap it in a ScrollView if its peak exceeds the display peak.

I am avoiding putting it in a ScrollView by default, as a result of reaching vertical centering inside a ScrollView might be tough.

I attempt to use ViewThatFits with ScrollView.

I exploit the next code to point out small peak content material.


No ScrollView is rendered (Appropriate behaviour)

import SwiftUI

struct ContentView: View {
    var largeContent: some View {
        VStack {
            Spacer()
            
            ForEach(1...20, id: .self) { i in
                Picture(systemName: "globe")
                    .imageScale(.giant)
                    .foregroundStyle(.tint)
                Textual content("(i). Massive content material!")
                    .font(.largeTitle)
            }
            
            Spacer()
        }
    }
    
    var smallContent: some View {
        VStack {
            Spacer()
            
            ForEach(1...2, id: .self) { i in
                Picture(systemName: "globe")
                    .imageScale(.giant)
                    .foregroundStyle(.tint)
                Textual content("(i). Small content material!")
                    .font(.largeTitle)
            }
            
            Spacer()
        }
    }
    
    var physique: some View {
        VStack {
            let smallContent = smallContent
            
            // The highest portion devoted to content material
            GeometryReader { x in
                ViewThatFits {
                    // Possibility 1: Content material suits with out scrolling.
                    smallContent
                        .background(Colour.yellow)
                        .body(maxHeight: x.dimension.peak)
                        .body(maxWidth: .infinity)
                    
                    // Possibility 2: Content material is just too tall, so wrap it in a ScrollView.
                    ScrollView {
                        smallContent
                            .background(Colour.crimson)
                            .body(minHeight: x.dimension.peak)
                            .body(maxWidth: .infinity)
                    }
                }
            }
            
            Textual content("Button")
                .background(Colour.blue)
                .font(.largeTitle)
        }
    }
}

enter image description here

It’s inside my expectation as a result of

  1. No ScrollView is rendered.
  2. Content material is vertical heart.

No ScrollView is rendered (Unsuitable behaviour)

import SwiftUI

struct ContentView: View {
    var largeContent: some View {
        VStack {
            Spacer()
            
            ForEach(1...20, id: .self) { i in
                Picture(systemName: "globe")
                    .imageScale(.giant)
                    .foregroundStyle(.tint)
                Textual content("(i). Massive content material!")
                    .font(.largeTitle)
            }
            
            Spacer()
        }
    }
    
    var smallContent: some View {
        VStack {
            Spacer()
            
            ForEach(1...2, id: .self) { i in
                Picture(systemName: "globe")
                    .imageScale(.giant)
                    .foregroundStyle(.tint)
                Textual content("(i). Small content material!")
                    .font(.largeTitle)
            }
            
            Spacer()
        }
    }
    
    var physique: some View {
        VStack {
            let largeContent = largeContent
            
            // The highest portion devoted to content material
            GeometryReader { x in
                ViewThatFits {
                    // Possibility 1: Content material suits with out scrolling.
                    largeContent
                        .background(Colour.yellow)
                        .body(maxHeight: x.dimension.peak)
                        .body(maxWidth: .infinity)
                    
                    // Possibility 2: Content material is just too tall, so wrap it in a ScrollView.
                    ScrollView {
                        largeContent
                            .background(Colour.crimson)
                            .body(minHeight: x.dimension.peak)
                            .body(maxWidth: .infinity)
                    }
                }
            }
            
            Textual content("Button")
                .background(Colour.blue)
                .font(.largeTitle)
        }
    }
}

#Preview {
    ContentView()
}

enter image description here

Now, I’ve swap to show “giant content material”. I’m anticipating crimson ScrollView to be rendered. Nevertheless, it’s not.

Could I do know what’s fallacious with my code? Thanks.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles