Layout is incorrect when available width changes
rzulkoski opened this issue · comments
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:
- Create a view with a
WrappingHStack
containing a few dozen items. - Notice the initial layout is correct.
- Take some action that affects the available width, such as device rotation.
- 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()
}
}