iPadOS:当不使用指针时防止UIContextMenuInteraction触发

4

UIMenu vs UIContextMenuInteraction vs UIPointerInteraction

我试图以与Files或Pages应用程序相同的方式设置UIContextMenuInteraction

  • 在空白处进行(长时间)轻按,显示黑色水平UIMenu
  • 在空白处使用指针进行次要(右键/控制键)单击会显示上下文菜单

请参见下面附加的GIF演示。

我能够设置UIContextMenuInteraction并在其UIContextMenuInteractionDelegate中返回希望显示的项目的UIContextMenuConfiguration

对于小黑色UIMenu也是一样, 我可以使用UILongPressGestureRecognizer并使用UIMenuController.shared.showMenu来显示菜单。

但是,我无法阻止UIContextMenuInteraction触发并显示UITargetedPreview,当在视图上进行长按时似乎没有办法识别不同的UITouchType,因为这些信息提供给了UIContextMenuInteractionDelegate

我还找不到如何在没有UIContextMenuInteraction的情况下以编程方式显示上下文菜单。有没有办法这样做?

问题

Files.app是如何实现的?

Files.app ui menu and context menu interaction


提交反馈:FB7716019 - Tom Kraina
1个回答

1
没有办法通过编程触发上下文菜单,但是通过一些简单的记账,您可以在不需要时(例如当触摸在响应器上活动时)防止其显示。
要隐藏预览,请在UIContextMenuConfiguration的初始化程序中从previewProvider返回nil。
以下是以视图控制器的视图为目标的完整实现:
import UIKit

class ViewController: UIViewController {

    var touchesInSession = false

    override func viewDidLoad() {
        super.viewDidLoad()

        let interaction = UIContextMenuInteraction(delegate: self)
        view.addInteraction(interaction)

        let recognizer = UILongPressGestureRecognizer(target: self, action: #selector(longPressHandler))
        view.addGestureRecognizer(recognizer)
    }

    @objc func longPressHandler(recognizer: UILongPressGestureRecognizer) {
        guard recognizer.state == .began else { return }
        presentMenu(from: recognizer.location(in: view))
    }

    func presentMenu(from location: CGPoint) {
        view.becomeFirstResponder()
        let saveMenuItem = UIMenuItem(title: "New Folder", action: #selector(createFolder))
        let deleteMenuItem = UIMenuItem(title: "Get Info", action: #selector(getInfo))
        UIMenuController.shared.menuItems = [saveMenuItem, deleteMenuItem]
        UIMenuController.shared.showMenu(from: view, rect: .init(origin: location, size: .zero))
    }

    @objc func createFolder() {
        print("createFolder")
    }

    @objc func getInfo() {
        print("getInfo")
    }

    // MARK: UIResponder
    override var canBecomeFirstResponder: Bool { true }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        touchesInSession = true
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesEnded(touches, with: event)
        touchesInSession = false
    }

    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesCancelled(touches, with: event)
        touchesInSession = false
    }
}

extension ViewController: UIContextMenuInteractionDelegate {
    func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
        guard !touchesInSession else { return nil }
        let configuration = UIContextMenuConfiguration(identifier: "PointOnlyContextMenu" as NSCopying, previewProvider: { nil }, actionProvider: { suggestedActions in
            let newFolder = UIAction(title: "New Folder", image: UIImage(systemName: "folder.badge.plus")) { [weak self] _ in
                self?.createFolder()
            }
            let info = UIAction(title: "Get Info", image: UIImage(systemName: "info.circle")) { [weak self] _ in
                self?.getInfo()
            }
            return UIMenu(title: "", children: [newFolder, info])
        })
        return configuration
    }
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接