Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect bounds on VFlow if using .frame(maxHeight:) #19

Open
thedruid opened this issue Aug 14, 2024 · 1 comment
Open

Incorrect bounds on VFlow if using .frame(maxHeight:) #19

thedruid opened this issue Aug 14, 2024 · 1 comment

Comments

@thedruid
Copy link

thedruid commented Aug 14, 2024

If using maxHeight instead of height on a VFlow in a ScrollView, the bounds is incorrect and the view is cut off.

    ScrollView {
        VFlow {
            ForEach(1...21, id: \.self) {
                Text("Item \($0)")
                    .padding(4)
                    .background(.orange)
            }
        }
        .frame(maxHeight: 300) 
        .padding(16)
    }

.frame(maxHeight: 300)
Screenshot 2024-08-14 at 14 38 22

.frame(height: 300)`:
Screenshot 2024-08-14 at 14 38 32

@tevelee
Copy link
Owner

tevelee commented Aug 15, 2024

Thanks @thedruid for reporting this issue. I can confirm this is a bug.

Unfortunately I haven't discovered a solution so far. Let me offer a workaround instead: .frame(maxWidth: .infinity, maxHeight: 300).

Let me describe the details so somebody might have an idea for a fix.
HFlow & VFlow has the same underlying implementation, they only differ in the axis parameter, so – I thought – their behavior should be identical in SwiftUI. However, when embedded into ScrollView, they behave differently.

SwiftUI tries various size proposals first to determine the flexibility of the view.
With the .frame(width: 300) modifier, the proposals are

  • Proposes 0.0x300.0, the layout returns 169.5x280.0
  • Proposes infx300.0, the layout returns 169.5x280.0
  • Proposes 600.0x300.0, the layout returns 169.5x280.0
  • Proposes 169.5x300.0, the layout returns 169.5x280.0
  • Eventually it settles with 169.5x300.0 when it calls placeSubviews (with bounds of size 169.5x280.0).

In the .frame(maxWidth: 300) case

  • Proposes 0.0 x unspecified, the layout returns 54.5x664.0
  • Proposes inf x unspecified, the layout returns 54.5x664.0
  • Proposes 600.0 x unspecified, the layout returns 54.5x664.0
  • Proposes 54.5 x unspecified, the layout returns 54.5x664.0
  • Proposes 54.5x300.0, the layout returns 169.5x280.0 (out of bounds, I think this is why we see the clipping behavior)
  • Eventually it settles with 54.5x300.0 for placeSubviews (with bounds of size 169.5x280.0)

What is interesting that SwiftUI probes the width but not the height, regardless of HFlow/VFlow being used. Maybe it deems that the width is not flexible enough so it stops.
The reason it returns 54 if because all subviews can fit into one column when the height is unconstrained.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants