swiftUI:检测嵌入在数组中的两个视图的交点并交换它们的位置
1) 同一视图的多个实例嵌入在一个数组中。主ContentView的子视图通过HStack中的ForEach显示它们。每个实例都有一个几何体读取器,用于在拖动过程中检测帧交点。目标是在检测到交叉点时交换视图在主内容视图上的位置。使用下面的代码,它根本无法检测交叉点swiftUI:检测嵌入在数组中的两个视图的交点并交换它们的位置,swift,swiftui,intersection,drag,Swift,Swiftui,Intersection,Drag,1) 同一视图的多个实例嵌入在一个数组中。主ContentView的子视图通过HStack中的ForEach显示它们。每个实例都有一个几何体读取器,用于在拖动过程中检测帧交点。目标是在检测到交叉点时交换视图在主内容视图上的位置。使用下面的代码,它根本无法检测交叉点 为什么? 是否有更好/更简单的方法(比几何体读取器)来检测视图的碰撞/交点 是否有比array+foreach更好的方法来分组和显示某个视图的动态实例数 var rects:[rect]=[rect(num:“0”)、rect(nu
- 为什么?
- 是否有更好/更简单的方法(比几何体读取器)来检测视图的碰撞/交点
- 是否有比array+foreach更好的方法来分组和显示某个视图的动态实例数
var rects:[rect]=[rect(num:“0”)、rect(num:“1”)、rect(num:“2”)] struct rect:View{ 设id=UUID() 让num:String @状态变量viewFrame:CGRect=.0 @状态变量viewOffset:CGSize=.0 var body:一些观点{ 矩形() .笔划(颜色.蓝色,线宽:4) .框架(宽度:50,高度:100) .偏移(视图偏移) .background(文本(“\(num)”) .overlay(GeometryReader{r in 颜色:红色 .不透明度(0.5) 奥纳佩尔先生{ self.viewFrame=r.frame(在:。全局中) } }) .手势(DragGesture(最小距离:0,坐标空间:。全局) .onChanged{中的值 self.viewOffset=value.translation } .onEnded{中的值 设newFrame=self.viewFrame.offsetBy(dx:self.viewOffset.width,dy:self.viewOffset.height) 如果让swap_rect=rects.first(其中:{$0.id!=self.id&&$0.viewFrame.intersects(newFrame)}){ 打印(“相交”) swapAt(rects.firstIndex(of:self),rects.firstIndex(of:swaprect)) }否则{ 打印(“否”) } self.viewOffset=.0 } ) } } 结构字段:视图{ var body:一些观点{ HStack{ ForEach(self.field\u env.rects,id:\.id){rect in 直肠 } } } } 结构ContentView:View{ var body:一些观点{ VStack{ 字段() } } }
Nathan,我不知道这会有多大帮助,但是,不管它值多少钱,你可以看看Paul Hudson创建的名为Switcheroo的Swift on Sundays项目。这是一个游戏,你可以从一个信盘中选择一个字母,然后从信盘中拖动一个字母来替换上面4个字母中的一个来生成一个新单词。我假设这是有一种可能对您有用的冲突。您可以在GiHub上找到该项目:好的,最后我成功地使它工作了。我决定采用Paul的概念,将字符串存储在数组中,而不是完整的视图,并在ForEach循环期间使用这些stri实际创建视图在那之后,交换开始正常工作(即使用适当的索引).为了提高精度,我还将.intersects替换为.contains。因此,感谢Chrispy为我指明了正确的方向!看来这次它工作正常…但是解决方案本身和开销代码量远远不够完美,不确定是否有更简单的方法-请看一看,欢迎所有想法
导入快捷界面
扩展通知。名称{
static let viewModified=Notification.Name(“视图已修改”)
}
类FieldEnv:observeObject{
@已发布的变量rect_帧:[CGRect]=[]
@已发布的变量rects:[Int]=[0,1,2]
}
struct rect:View{
@环境对象变量字段\环境:字段环境
让num:Int
@状态变量viewOffset:CGSize=.0
var body:一些观点{
矩形()
.笔划(颜色.蓝色,线宽:4)
.框架(宽度:50,高度:100)
.overlay(文本(“\(num)”)
.偏移(视图偏移)
.手势(DragGesture(最小距离:0,坐标空间:。全局)
.onChanged{拖入
self.viewOffset=拖动.translation
}
.onEnded{拖入
如果让swap_rect_i=self.field_env.rect_frames.firstIndex(其中:{$0.contains(drag.location)}){
打印(“相交”)
动画片{
self.field\u env.rects.swapAt(self.field\u env.rects.firstIndex(of:self.num)!,swap\u rect\u i)
self.viewOffset=.0
}
}否则{
打印(“否”)
self.viewOffset=.0
}
}
)
}
}
结构字段:视图{
@环境对象变量字段\环境:字段环境
设NC=NotificationCenter.default
var body:一些观点{
HStack{
法罗群岛
```swift
class FieldEnv: ObservableObject {
@Published var rect_frames: [UUID:CGRect] = [:]
@Published var rects: [rect] = [rect(num:"0"),rect(num:"1"),rect(num:"2")]
}
struct rect: View {
@EnvironmentObject var field_env: FieldEnv
let id = UUID()
let num: String
@State var viewFrame: CGRect = .zero
@State var viewOffset: CGSize = .zero
var body: some View {
Rectangle()
.stroke(Color.blue, lineWidth: 4)
.frame(width: 50, height: 100)
.offset(viewOffset)
.background(Text("\(num)"))
.overlay(GeometryReader { r in
Color.red
.opacity(0.5)
.onAppear {
self.viewFrame = r.frame(in: .global)
self.field_env.rect_frames[self.id] = r.frame(in: .global)
}
})
.gesture(DragGesture(minimumDistance: 0, coordinateSpace: .global)
.onChanged { value in
self.viewOffset = value.translation
}
.onEnded { value in
let newFrame = self.viewFrame.offsetBy(dx: self.viewOffset.width, dy: self.viewOffset.height)
if let swap_rect = self.field_env.rect_frames.first(where: {$0.key != self.id && $0.value.intersects(newFrame)}) {
print("intersects")
withAnimation {
self.field_env.rects.swapAt(self.field_env.rects.firstIndex(of: self)!, self.field_env.rects.firstIndex(where: {$0.id == swap_rect.key})!)
}
} else {
print("nope")
}
self.viewOffset = .zero
}
)
}
}
struct field: View {
let NC = NotificationCenter.default
@EnvironmentObject var field_env: FieldEnv
var body: some View {
HStack {
ForEach(self.field_env.rects, id:\.id) { rect in
rect
}
}
}
}
struct ContentView: View {
var body: some View {
VStack {
field()
}
}
}
```
```swift
struct rect: View {
@EnvironmentObject var field_env: FieldEnv
let NC = NotificationCenter.default
let id = UUID()
let num: String
@State var viewFrame: CGRect = .zero
@State var viewOffset: CGSize = .zero
var body: some View {
Rectangle()
.stroke(Color.blue, lineWidth: 4)
.frame(width: 50, height: 100)
.offset(viewOffset)
.background(Text("\(num)"))
.overlay(GeometryReader { r in
Color.red
.opacity(0.5)
.onAppear {
self.viewFrame = r.frame(in: .global)
self.field_env.rect_frames[self.id] = r.frame(in: .global)
self.NC.addObserver(forName: .cardsSwapped, object: nil, queue: nil, using: {_ in self.field_env.rect_frames[self.id] = r.frame(in: .global)})
}
})
.gesture(DragGesture(minimumDistance: 0, coordinateSpace: .global)
.onChanged { value in
self.viewOffset = value.translation
}
.onEnded { value in
let newFrame = self.viewFrame.offsetBy(dx: self.viewOffset.width, dy: self.viewOffset.height)
if let swap_rect = self.field_env.rect_frames.first(where: {$0.value.intersects(newFrame)}) {
print("intersects")
withAnimation {
self.field_env.rects.move(fromOffsets: [self.field_env.rects.firstIndex(of: self)!], toOffset: self.field_env.rects.firstIndex(where: {$0.id == swap_rect.key})!)
}
} else {
print("nope")
}
self.viewOffset = .zero
self.NC.post(name: .cardsSwapped, object: nil)
}
)
}
}
```