I'm wondering what the easiest way to reordering a view in a stack is whilst maintaining structural identity, so that it animates/transitions correctly + state is maintained.
Ideally if in a LazyVStack it would maintain the laziness too.
Think of a stack where if a normal ForEach was used the view may end up being a switch over up to 20 different types of views.
I know custom Layouts can be used but they currently cannot be lazy and it seems like a fair bit of work for something that seems fairly simple.
Can the below approach be optimised?
import SwiftUI
struct GroupDemoView: View {
@State private var animatesChanges = false
@State private var shouldReorder = false
private let reorderAnimation = Animation.spring(duration: 3, bounce: 0.5)
var body: some View {
VStack(spacing: 28) {
VStack(spacing: 12) {
Toggle("Animate changes", isOn: $animatesChanges)
Toggle("Reorder subviews", isOn: animatesChanges ? $shouldReorder.animation(reorderAnimation) : $shouldReorder)
}
.frame(maxWidth: 240)
ScrollView {
ReorderingVStack(shouldReorder: shouldReorder) {
Text("A")
SimpleCard(name: "Card B")
Text("B")
Text("C")
Text("D")
Text("E")
Text("F")
Text("G")
Text("H")
Text("I")
Text("J")
Text("K")
}
}
.font(.title3.weight(.semibold))
}
.padding()
}
}
private struct ReorderingVStack<Content: View>: View {
let shouldReorder: Bool
let content: Content
init(
shouldReorder: Bool,
@ViewBuilder content: () -> Content
) {
self.shouldReorder = shouldReorder
self.content = content()
}
var body: some View {
Group(subviews: content) { subviews in
VStack(spacing: 12) {
ForEach(rearranged(subviews)) { subview in
subview
}
}
}
}
private func rearranged(_ subviews: SubviewsCollection) -> [Subview] {
var subviews = Array(subviews)
if shouldReorder {
subviews.insert(subviews.remove(at: 1), at: 9)
}
return subviews
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
2
0
83