You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

禁用滑动删除后,进入编辑模式时列表出现动画异常问题

禁用滑动删除后,进入编辑模式时列表出现动画异常问题

我懂你的需求——想通过顶部的编辑按钮实现批量删除,同时不想在编辑模式下显示每行左侧的红色删除控件,但添加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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 17:54:39