SwiftUI 上下文菜单错误的位置

SwiftUI contextmenu wrong location

我正在尝试向我显示的图像添加上下文菜单,但是当我长按时,上下文菜单在错误的位置打开(见图)

我使用的代码是:

ForEach(self.document.instruments) { instrument in
    Image(instrument.text)
        .resizable()
        .frame(width: 140, height: 70)
        .position(self.position(for: instrument, in: geometry.size))
        .gesture(self.singleTapForSelection(for: instrument))
        .gesture(self.dragSelectionInstrument(for: instrument))
        .shadow(color: self.isInstrumentSelected(instrument) ? .blue : .clear, radius: 10 * self.zoomScale(for: instrument))
        .contextMenu {
            Button {
                print("Deleted selected")
            } label: {
                Label("Delete", systemImage: "trash")
            }
        }
}

问题更新

我仍然面临的问题(作为我最后的评论)是,当我拖动图像时,似乎有延迟,因为图像会在其位置停留一小会儿,然后移动到拖动的位置.我已经发现,当我在代码中有 contextMenu 时,会发生延迟拖动,当注释掉时,它工作正常。

这是我的代码:

ForEach(self.document.instruments) { instrument in
    Image(instrument.text)
        .resizable()
        .frame(width: 140, height: 70)
        .contextMenu {
            Button {
                print("Deleted selected")
            } label: {
                Label("Delete", systemImage: "trash")
            }
        }
        .position(self.position(for: instrument, in: geometry.size))
        .shadow(color: self.isInstrumentSelected(instrument) ? .blue : .clear, radius: 10 * self.zoomScale(for: instrument))
        .gesture(self.singleTapForSelection(for: instrument))
        .gesture(self.dragSelectionInstrument(for: instrument))
}

我什至尝试将手势移动到上下文菜单上方,但没有成功。

请帮忙

最新更新

Nm,它只在模拟器上,在我的身体上iPad它工作正常

问题是您的代码在 position 修饰符之后应用了 contextMenu 修饰符。

让我们考虑这个稍微修改过的例子:

ZStack {
    GeometryReader { geometry in
        ForEach(self.document.instruments, id: \.id) { instrument in
            Image(instrument.text)
                .frame(width: 140, height: 70)
                .position(self.position(for: instrument, in: geometry.size))
                .contextMenu { ... }
        }
    }
}

在 SwiftUI 布局系统中,parent 视图负责为其 child 视图分配位置。视图修饰符充当它所修改的视图的 parent。所以在示例代码中:

  • ZStackGeometryReader 的 parent。
  • GeometryReaderForEach 的 parent。
  • ForEachcontextMenu 的 parent。
  • contextMenuposition 的 parent。
  • positionframe 的 parent。
  • frameImage 的 parent。
  • Image 不是 parent。它没有children.

(有时 parent 称为“超级视图”,child 称为“子视图”。)

contextMenu 需要知道在屏幕上的什么位置绘制菜单时,它会查看其 parent 给它的位置,ForEach,它从GeometryReader,它从 ZStack.

中获取

Image 需要知道在屏幕上的何处绘制像素时,它会查看其 parent 给它的位置,即 frame 修饰符,并且frame 修饰符从 position 修饰符获取位置,而 position 修饰符修改 contextMenu.

赋予它的位置

这意味着 position 修饰符 不会 影响 contextMenu 绘制菜单的位置。

现在让我们重新排列代码,使 contextMenu 成为 position 的 child:

ZStack {
    GeometryReader { geometry in
        ForEach(self.document.instruments, id: \.id) { instrument in
            Image(instrument.text)
                .frame(width: 140, height: 70)
                .contextMenu { ... }
                .position(self.position(for: instrument, in: geometry.size))
        }
    }
}

现在 contextMenuposition 修饰符获取它的位置,修饰符修改 ForEach 给它的位置。因此,在这种情况下,position 修饰符 影响 contextMenu 绘制菜单的位置。