在SwiftUI中的ForEach中向图像添加拖动手势 [英] Adding Drag Gesture to image inside a ForEach in SwiftUI

查看:90
本文介绍了在SwiftUI中的ForEach中向图像添加拖动手势的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  @GestureState私有var dragOffset = CGSize.zerovar body:some View {//植物标题VStack(间距:5){文字(植物").font(.headline).fontWeight(.light)//HStack for Plants图片HStack(间距:10){//对于遍历植物框内所有植物的每个植物ForEach(plantBoxViewModel.plants){植物在//单个工厂的图像(通过对后端的http请求获得)图像(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(宽度:70,高度:70).手势(DragGesture().updating(self.$ dragOffset,body:{(value,state,transaction)in状态= value.translation}))}}}} 

如下所示:

  @GestureState私有var dragOffset = CGSize.zero@State私人var选择:植物?= nil//<<你这里的植物类型var body:some View {//植物标题VStack(间距:5){文字(植物").font(.headline).fontWeight(.light)//HStack for Plants图片HStack(间距:10){//对于遍历植物框内所有植物的每个植物ForEach(plantBoxViewModel.plants){植物在//单个工厂的图像(通过对后端的http请求获得)图像(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(宽度:70,高度:70).手势(DragGesture().updating(self.$ dragOffset,body:{(value,state,transaction)in如果nil == self.selected {自选=植物}状态= value.translation}).onEnded {_ in self.selected = nil})}}}} 

I am currently developing an App shows a user his plant boxes and some measurements (like ground humidity, temperature etc) Each plant box has some plants inside it, which are being displayed in a detail view. I want the user to be able to drag one of the plants to a corner in order to remove it. Currently I have this implementation:

@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
                           })
                   )
            }
        }
    }

}

It looks like the following: Screenshot of Code Snippet

However, when I start dragging, both images move. I think it is because the offset of both images gets bound to the same variable (DragOffset). How can I accomplish that only 1 image is moving?

I thought about implementing some sort of array that maps the index of the plant to a specific offset but I wouldn't know how to implement it into the gesture. Thanks for any help!

解决方案

Here is possible approach - to keep selection during drag. Tested with 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 }
                )
            }
        }
    }

}

这篇关于在SwiftUI中的ForEach中向图像添加拖动手势的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆