在 SwiftUI 列表中移动项目时不需要的动画

Mat*_*z K 9 ios swift swiftui swiftui-list

我有一个 SwiftUI 列表,就像下面的示例代码一样。

struct ContentView: View {
    @State var numbers = ["1", "2", "3"]
    @State var editMode = EditMode.inactive

    var body: some View {
        NavigationView {
            List {
                ForEach(numbers, id: \.self) { number in
                    Text(number)
                }
                .onMove {
                    self.numbers.move(fromOffsets: $0, toOffset: $1)
                }
            }
            .navigationBarItems(trailing: EditButton())
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当我进入编辑模式并将项目向上移动一个位置时,在我放下项目后会发生奇怪的动画(见下面的 gif)。看起来拖动的项目回到原来的位置,然后再次移动到目的地(带动画)

重新排序项目时出现奇怪的动画

有趣的是,如果您将项目向下拖动列表或向上拖动多个位置,则不会发生这种情况。

我猜这是因为当状态中的项目被重新排序时,即使它们已经通过拖放在视图端重新排序,列表也会执行动画。但显然,除了将项目向上移动一个位置之外,它在所有情况下都能很好地处理它。

关于如何解决这个问题的任何想法?或者它可能是一个已知的错误?

我使用的是 XCode 11.4.1,构建目标是 iOS 13.4

(另请注意,在“真实世界”应用程序中,我使用的是 Core Data,当移动项目时,它们的顺序会在 DB 中更新,然后状态也会更新,但动画的问题看起来完全相同。)

Asp*_*eri 5

这是解决方案(使用 Xcode 11.4 / iOS 13.4 测试)

var body: some View {
    NavigationView {
        List {
            ForEach(numbers, id: \.self) { number in
                HStack {
                    Text(number)
                }.id(UUID())        // << here !!
            }
            .onMove {
                self.numbers.move(fromOffsets: $0, toOffset: $1)
            }
        }
        .navigationBarItems(trailing: EditButton())
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,它有效!尽管看起来我已经过度简化了我的示例,但在“真实”应用程序中,它会导致更奇怪的动画(每次更改顺序时都会替换列表中的所有元素)。在我的应用程序中,我的列表项是根据“order”属性排序的。然而,它给了我一个使用 ids 的线索,并且我找到了有效的解决方案。就是使用我的“order”属性作为 id,如下所示: `ForEach(numbers, id: \.order)` 现在它可以工作了:) 仍然想知道为什么它仅在向上移动一项时不起作用以及如果它是不过 SwiftUI 的 bug...再次感谢! (3认同)