SwiftUI:如何使项目的拖放重新排序有效?

时间:2020-07-03 06:21:11

标签: ios swift swiftui scrollview gesture

我有以下SwiftUI视图:

struct ContentView: View {
    @State var model: Model
    
    var body: some View {
        ScrollView {
            LazyVGrid(columns: columns, spacing: 10) {
                ForEach(model.events, id: \.self) { event in
                    CardView(event: event)
                }
                .onMove { indices, newOffset in
                    model.events.move(fromOffsets: indices, toOffset: newOffset)
                }
            }
        }
    }
}

但是,似乎没有执行onMove关闭。我相信这是因为所有手势都只提供给ScrollView,因此内部视图不会收到手势。

我曾尝试将此视图转换为List,但是我不希望使用行分隔符,在iOS 14中我认为无法隐藏行分隔符。

因此,我想知道我需要进行哪些更改才能使它允许用户拖放CardView来重新排序。谢谢!

2 个答案:

答案 0 :(得分:1)

根据Apple在Drag and Drop to reorder Items using the new LazyGrids?中的回复

尽管您可以使用View.onDrag(_ :)和 View.onDrop(...)添加对拖放的手动支持。

如果您希望看到内置的重新排序,请提交反馈请求 支持。谢谢!

因此,我在https://stackoverflow.com/a/63438481/12299030中实际重复的问题的答案中提供了使用.onDrag和.onDrop的解决方案

主要思想是通过网格卡视图跟踪药品和投药并在投药委托中重新排序模型,因此LazyVGrid可以对子视图进行动画处理:

   LazyVGrid(columns: model.columns, spacing: 32) {
        ForEach(model.data) { d in
            GridItemView(d: d)
                .overlay(dragging?.id == d.id ? Color.white.opacity(0.8) : Color.clear)
                .onDrag {
                    self.dragging = d
                    return NSItemProvider(object: String(d.id) as NSString)
                }
                .onDrop(of: [UTType.text], delegate: DragRelocateDelegate(item: d, listData: $model.data, current: $dragging))
        }
    }.animation(.default, value: model.data)

...

    func dropEntered(info: DropInfo) {
        if item != current {
            let from = listData.firstIndex(of: current!)!
            let to = listData.firstIndex(of: item)!
            if listData[to].id != current!.id {
                listData.move(fromOffsets: IndexSet(integer: from),
                    toOffset: to > from ? to + 1 : to)
            }
        }
    }

答案 1 :(得分:-3)

您可以使用列表并隐藏分隔符。

.onAppear {
 UITableView.appearance().separatorStyle = .none
}