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

Layout is incorrect when available width changes #40

Closed
rzulkoski opened this issue Feb 10, 2023 · 1 comment · Fixed by #41
Closed

Layout is incorrect when available width changes #40

rzulkoski opened this issue Feb 10, 2023 · 1 comment · Fixed by #41
Labels
bug Something isn't working help wanted Extra attention is needed

Comments

@rzulkoski
Copy link

rzulkoski commented Feb 10, 2023

Describe the bug
The initial layout is correct, but changes to the available width do not cause the layout to update.

To Reproduce
Steps to reproduce the behavior:

  1. Create a view with a WrappingHStack containing a few dozen items.
  2. Notice the initial layout is correct.
  3. Take some action that affects the available width, such as device rotation.
  4. Notice the layout is now incorrect.

Expected behavior
When the available width changes, the layout should be recalculated correctly.

Screenshots
Correct initial layout in portrait

Incorrect layout after rotating to landscape

Incorrect layout after subsequent rotation back to portrait

Context:

  • WrappingHStack version: 2.2.9
  • Model: iPhone 14 Pro Max
  • OS: iOS 16.2

Additional context
After extensive debugging, I have determined that the issue lies with LineManager. Notice that it will only calculate the firstElementOfEachLine once with the initial width, but over time new width values are passed to InternalWrappingHStack by the GeometryReader. This will cause the InternalWrappingHStack to redraw, but it's still using stale firstItemOfEachLine values.

In my testing the InternalWrappingHStack is only redrawn when the width changes, which matches the desired lifetime of the cached firstItemOfEachLine value. I believe the fix would be to remove line manager and allow InternalWrappingHStack to own its logic once again.

Simplified Example
Paste this into ContentView.swift within a fresh project after adding WrappingHStack as an SPM dependency:

import SwiftUI
import WrappingHStack

struct ContentView: View {
    @State var itemIndexes: [Int] = Array(1...30)

    var body: some View {
        WrappingHStack(self.itemIndexes, id: \.self, lineSpacing: 8) { index in
            Text("Item: \(index)")
                .padding(3)
                .background(Rectangle().stroke())
        }
        .background(.gray.opacity(0.2))
        .padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
@rzulkoski
Copy link
Author

Here's some screenshots of the behavior after applying the fix:

Correct initial layout in portrait

Correct layout after rotating to landscape

Correct layout after subsequent rotation back to portrait

@dkk dkk closed this as completed in #41 May 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed
Projects
None yet
1 participant