diff --git a/README.md b/README.md index daa3a96..d688f5b 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,6 @@ For even more convenience and flexibility, `WrappingHSTack` offers the parameter ## Known Issues * [Issue #15](https://github.com/dkk/WrappingHStack/issues/15): Item sizes are calculated incorrectly when WrappingHStack has modifiers that change the size of its elements. -* [Issue #17](https://github.com/dkk/WrappingHStack/issues/17): Spacing always applied around conditional views, even when they're missing. * [Issue #16](https://github.com/dkk/WrappingHStack/issues/26): Workaround needed when using `WrappingHStack` in a `NavigationLink` (iOS16 only). * [Issue #10](https://github.com/dkk/WrappingHStack/issues/10): SPM cannot resolve the dependency (Xcode 11.3.1 only). diff --git a/Sources/WrappingHStack/InternalWrappingHStack.swift b/Sources/WrappingHStack/InternalWrappingHStack.swift index b3b5d13..2d01759 100644 --- a/Sources/WrappingHStack/InternalWrappingHStack.swift +++ b/Sources/WrappingHStack/InternalWrappingHStack.swift @@ -24,15 +24,14 @@ struct InternalWrappingHStack: View { switch contentIterator.element { case .newLine: return (firstItemOfEachLane + [contentIterator.offset], width) - case .any(let anyView): - #if os(iOS) + case .any(let anyView) where Self.isVisible(view: anyView): +#if os(iOS) let hostingController = UIHostingController(rootView: HStack(spacing: spacing.estimatedSpacing) { anyView }) - #else +#else let hostingController = NSHostingController(rootView: HStack(spacing: spacing.estimatedSpacing) { anyView }) - #endif - +#endif let itemWidth = hostingController.sizeThatFits(in: CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)).width - + if result.currentLineWidth + itemWidth + spacing.estimatedSpacing > width { currentLineWidth = itemWidth firstItemOfEachLane.append(contentIterator.offset) @@ -40,6 +39,8 @@ struct InternalWrappingHStack: View { currentLineWidth += itemWidth + spacing.estimatedSpacing } return (firstItemOfEachLane, currentLineWidth) + default: + return result } }.0 } @@ -69,6 +70,14 @@ struct InternalWrappingHStack: View { } return false } + + @inline(__always) static func isVisible(view: AnyView) -> Bool { +#if os(iOS) + return UIHostingController(rootView: view).sizeThatFits(in: CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)).width > 0 +#else + return NSHostingController(rootView: anyView).sizeThatFits(in: CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)).width > 0 +#endif + } var body: some View { VStack(alignment: alignment, spacing: lineSpacing) { @@ -85,17 +94,19 @@ struct InternalWrappingHStack: View { Spacer(minLength: spacing.estimatedSpacing) } - if case .any(let anyView) = content[$0] { + if case .any(let anyView) = content[$0], Self.isVisible(view: anyView) { anyView } if endOf(lane: laneIndex) != $0 { - if case .constant(let exactSpacing) = spacing { - Spacer(minLength: 0) - .frame(width: exactSpacing) - } else { - Spacer(minLength: spacing.estimatedSpacing) - } + if case .any(let anyView) = content[$0], !Self.isVisible(view: anyView) { } else { + if case .constant(let exactSpacing) = spacing { + Spacer(minLength: 0) + .frame(width: exactSpacing) + } else { + Spacer(minLength: spacing.estimatedSpacing) + } + } } else if case .dynamicIncludingBorders = spacing { Spacer(minLength: spacing.estimatedSpacing) } diff --git a/WrappingHStackExample/WrappingHStackExample/ContentView.swift b/WrappingHStackExample/WrappingHStackExample/ContentView.swift index 4b32c26..3315c0c 100644 --- a/WrappingHStackExample/WrappingHStackExample/ContentView.swift +++ b/WrappingHStackExample/WrappingHStackExample/ContentView.swift @@ -29,9 +29,11 @@ struct ExampleView: View { .font(.title) WrappingHStack(1...9, id:\.self, alignment: alignment, spacing: spacing) { - Text("Item: \($0)") - .padding(.all, 12) - .background(RoundedRectangle(cornerRadius: 10).stroke()) + if $0 != 2 { + Text("Item: \($0)") + .padding(.all, 12) + .background(RoundedRectangle(cornerRadius: 10).stroke()) + } }.frame(width: 380) Text("1234567898")