禁用滑动删除后,进入编辑模式时列表出现动画异常问题
禁用滑动删除后,进入编辑模式时列表出现动画异常问题
我懂你的需求——想通过顶部的编辑按钮实现批量删除,同时不想在编辑模式下显示每行左侧的红色删除控件,但添加deleteDisabled(editMode?.wrappedValue.isEditing == true)后,进入编辑模式时列表出现了奇怪的弹跳动画。下面来分析问题并给出解决方案:
问题原因
这个动画异常是因为deleteDisabled的状态会随着编辑模式的切换动态变化,SwiftUI在处理这种状态切换时,没协调好列表布局的过渡动画,导致出现了弹跳效果。本质上是动态切换删除禁用状态触发了不必要的布局重绘。
解决方案
其实你完全不需要依赖deleteDisabled来隐藏编辑模式下的单行删除控件,因为你的删除逻辑是基于批量选择实现的,和单行删除(onDelete)没关系。直接移除onDelete修饰符就行,这样无论是滑动删除还是编辑模式下的红色删除按钮都不会出现,同时也能避免动画问题。
修改后的完整代码如下:
import SwiftUI struct ContentView: View { @State private var items = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"] @State private var selection: Set<String> = [] var body: some View { NavigationStack { List(selection: $selection) { ItemsList(items: $items) } .toolbar { ToolbarItem(placement: .topBarLeading) { EditButton() } ToolbarItem(placement: .topBarTrailing) { if !selection.isEmpty { Button("Delete", role: .destructive) { items.removeAll { selection.contains($0) } selection.removeAll() } } } } } } } private struct ItemsList: View { @Binding var items: [String] @Environment(\.editMode) private var editMode var body: some View { ForEach(items, id: \.self) { item in Text(item) } // 移除onDelete修饰符,同时也不需要deleteDisabled了 } } #Preview { ContentView() }
补充方案(如果需要保留非编辑模式的滑动删除)
要是你还想保留非编辑模式下的滑动删除功能,只是在编辑模式下隐藏单行删除控件,可以通过条件渲染来控制onDelete的启用,避免动态切换deleteDisabled的状态:
private struct ItemsList: View { @Binding var items: [String] @Environment(\.editMode) private var editMode var body: some View { let listContent = ForEach(items, id: \.self) { item in Text(item) } if editMode?.wrappedValue.isEditing == false { listContent .onDelete { offsets in items.remove(atOffsets: offsets) } } else { listContent } } }
这种方式通过条件渲染来控制单行删除的启用状态,状态切换更稳定,不会触发异常的布局动画。
备注:内容来源于stack exchange,提问作者Edward
相关产品推荐
相关产品推荐

