![](/img/trans.png)
[英]Multiple NavigationLinks used within Lists not working in SwiftUI
[英]SwiftUI multiple vertical lists row animations not working
突然间,我发现其中没有一个没有自动动画:
没有用于插入、删除、重新排序等的动画。 ☹️ Id
在转换之间是唯一且持久的
我怎样才能让它们按预期工作?
问题2
有没有一种简单的方法来制作动画来查看列表之间的转换? 就像在单个列表的部分之间移动一行。
假设我有三个列表,它们对单个数组的元素的不同状态进行分组:
extension Call {
enum State: Equatable {
case inProgress
case accepted
case rejected
}
}
可观察的:
class CallManager: ObservableObject {
@Published var calls: [Call]
init(visits: [Call] = []) { self.calls = visits }
}
而 Call 是一个简单的 Identifiable:
struct Call: Identifiable & Equatable & Hashable {
let id = UUID()
var state: State
}
通过进行这些绑定,我已将所有列表绑定到核心calls
数组:
extension CallManager {
func bindingCalls(for state: Call.State) -> Binding<[Call]> {
Binding<[Call]>(
get: { self.calls.filter { $0.state == state } },
set: { // TODO: Find a better way for this
self.calls.removeAll(where: { $0.state == state })
self.calls.append(contentsOf: $0)
}
)
}
var inProgress: Binding<[Call]> { bindingCalls(for: .inProgress) }
var accepted: Binding<[Call]> { bindingCalls(for: .accepted) }
var rejected: Binding<[Call]> { bindingCalls(for: .rejected) }
}
这是查看代码:
struct ContentView: View {
@StateObject var visitManager = CallManager(visits: [
Call(state: .inProgress),
Call(state: .accepted),
Call(state: .accepted),
Call(state: .inProgress),
Call(state: .inProgress),
Call(state: .rejected)
])
var body: some View {
HStack {
List(visitManager.inProgress) { $call in
CallView(call: $call)
}
List(visitManager.accepted) { $call in
CallView(call: $call)
}
List(visitManager.rejected) { $call in
CallView(call: $call)
}
}
}
}
struct CallView: View & Identifiable {
@Binding var call: Call
var id: UUID { call.id }
var body: some View {
Text(call.id.uuidString.prefix(15))
.foregroundColor(call.state.color)
.onTapGesture(count: 2) { call.state = .rejected }
.onTapGesture { call.state = .accepted }
}
}
extension Call.State {
var color: Color {
switch self {
case .inProgress: return .blue
case .rejected: return .red
case .accepted: return .green
}
}
}
您可以在列表视图上启用动画:
List(visitManager.inProgress) { $call in
CallView(call: $call)
}
.animation(.default)
或者将更改包装在 withAnimation 块中:
.onTapGesture { withAnimation { call.state = .accepted } }
至于列之间的动画,您可以使用.matchedGeometryEffect
获得类似的.matchedGeometryEffect
。 afaik 它在 List 之间看起来总是有点易碎,为了使它看起来不错,你需要使用VStack
(但随后失去了 List 视图的所有舒适性)。 例如:
import SwiftUI
extension Call {
enum State: Equatable, CaseIterable {
case inProgress
case accepted
case rejected
}
}
class CallManager: ObservableObject {
@Published var calls: [Call]
init(visits: [Call] = []) { calls = visits }
}
struct Call: Identifiable & Equatable & Hashable {
let id = UUID()
var state: State
}
struct ContentView: View {
@Namespace var items
@StateObject var visitManager = CallManager(visits: [
Call(state: .inProgress),
Call(state: .accepted),
Call(state: .accepted),
Call(state: .inProgress),
Call(state: .inProgress),
Call(state: .rejected),
])
var body: some View {
HStack(alignment: .top) {
ForEach(Call.State.allCases, id: \.self) { state in
VStack {
List(visitManager.calls.filter { $0.state == state }) { call in
CallView(call: call)
.id(call.id)
.matchedGeometryEffect(id: call.id, in: items)
.onTapGesture {
if let idx = visitManager.calls.firstIndex(where: { $0.id == call.id }) {
withAnimation {
visitManager.calls[idx].state = .rejected
}
}
}
}
}
}
}
}
}
struct CallView: View & Identifiable {
var call: Call
var id: UUID { call.id }
var body: some View {
Text(call.id.uuidString.prefix(15))
.foregroundColor(call.state.color)
}
}
extension Call.State {
var color: Color {
switch self {
case .inProgress: return .blue
case .rejected: return .red
case .accepted: return .green
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.