Skip to content

Layout is incorrect when available width changes #40

Description

@rzulkoski

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()
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghelp wantedExtra attention is needed

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions