4

我目前正在开发一个应用程序,向用户展示他的植物箱和一些测量值(如地面湿度、温度等)每个植物箱里面都有一些植物,这些植物正在详细视图中显示。我希望用户能够将其中一种植物拖到角落以将其移除。目前我有这个实现:

@GestureState private var dragOffset = CGSize.zero

var body: some View {

    //Plants Headline
    VStack (spacing: 5) {
        Text("Plants")
            .font(.headline)
            .fontWeight(.light)

        //HStack for Plants Images
        HStack (spacing: 10) {

            //For each that loops through all of the plants inside the plant box
            ForEach(plantBoxViewModel.plants) { plant in

                //Image of the individual plant (obtained via http request to the backend)
                Image(base64String: plant.picture)
                    .resizable()
                    .clipShape(Circle())
                    .overlay(Circle().stroke(Color.white, lineWidth: 2))
                    .offset(x: self.dragOffset.width, y: self.dragOffset.height)
                    .animation(.easeInOut)
                    .aspectRatio(contentMode: .fill)
                    .frame(width: 70, height: 70)
                    .gesture(
                           DragGesture()
                            .updating(self.$dragOffset, body: { (value, state, transaction) in
                               state = value.translation
                           })
                   )
            }
        }
    }

}

如下所示: 代码片段的屏幕截图

但是,当我开始拖动时,两个图像都会移动。我认为这是因为两个图像的偏移量都绑定到同一个变量(DragOffset)。我怎样才能做到只有一张图像在移动?

我考虑过实现某种数组,将植物的索引映射到特定的偏移量,但我不知道如何将它实现到手势中。谢谢你的帮助!

4

2 回答 2

5

这是可能的方法 - 在拖动期间保持选择。使用 Xcode 11.4 / iOS 13.4 测试。

演示

@GestureState private var dragOffset = CGSize.zero
@State private var selected: Plant? = nil // << your plant type here
var body: some View {

    //Plants Headline
    VStack (spacing: 5) {
        Text("Plants")
            .font(.headline)
            .fontWeight(.light)

        //HStack for Plants Images
        HStack (spacing: 10) {

            //For each that loops through all of the plants inside the plant box
            ForEach(plantBoxViewModel.plants) { plant in

                //Image of the individual plant (obtained via http request to the backend)
                Image(base64String: plant.picture)
                    .resizable()
                    .clipShape(Circle())
                    .overlay(Circle().stroke(Color.white, lineWidth: 2))
                    .offset(x: self.selected == plant ? self.dragOffset.width : 0,
                            y: self.selected == plant ? self.dragOffset.height : 0)
                    .animation(.easeInOut)
                    .aspectRatio(contentMode: .fill)
                    .frame(width: 70, height: 70)
                    .gesture(
                        DragGesture()
                            .updating(self.$dragOffset, body: { (value, state, transaction) in
                                if nil == self.selected {
                                    self.selected = plant
                                }
                                state = value.translation
                            }).onEnded { _ in self.selected = nil }
                )
            }
        }
    }

}
于 2020-04-19T08:44:20.567 回答
0

@Asperi 的回答完成了这项工作,但我必须为 Xcode 13 更新它,所以它不会抛出“在视图更新期间修改状态,这将导致未定义的行为”。

基本上,.updating修饰符不断更新@state var selected导致整个视图刷新,当我们试图影响它的新值时,它会抛出未定义的行为。

.gesture(
                                DragGesture()
                                    .onChanged { value in
                                        // Updated
                                        if nil == self.selected {
                                            self.selected = plant
                                        }
                                    }
                                    .updating(self.$dragOffset, body: { (value, state, transaction) in
                                        // This part is removed for causing undefined behavior
                                        // if nil == self.selected {
                                        //     self.selected = plant
                                        // }
                                        state = value.translation
                                    }).onEnded { _ in self.selected = nil }
                            )

您可以在此处阅读更多相关信息:在视图更新期间修改状态

于 2022-01-08T11:59:38.847 回答