繁体   English   中英

在 iOS 14 中为 UICollectionView 使用 UIMenuController?

[英]Using UIMenuController in iOS 14 for UICollectionView?

有一些关于如何在UICollectionView中使用UIMenuController的教程,但在 iOS 14 中它是半弃用的:

// These methods provide support for copy/paste actions on cells.
// All three should be implemented if any are.
- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath API_DEPRECATED_WITH_REPLACEMENT("collectionView:contextMenuConfigurationForItemAtIndexPath:", ios(6.0, 13.0));
- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender API_DEPRECATED_WITH_REPLACEMENT("collectionView:contextMenuConfigurationForItemAtIndexPath:", ios(6.0, 13.0));
- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender API_DEPRECATED_WITH_REPLACEMENT("collectionView:contextMenuConfigurationForItemAtIndexPath:", ios(6.0, 13.0));

同时UIMenuController仍然存在于 iOS 14. 现在如何将它用于单元格?

UICollectionViewDelegate 不会触发您在 iOS 14 之后发布的那些方法。但是我们仍然可以从 UIView 获得 UIMenuController 需要的 FirstResponder。 命中。 UICollectionView还是UIView

完整代码:

protocol Menuable {
    func menuAction(_ sender: Any?)
}

class CustomCell: UICollectionViewCell, Menuable {
...
    func menuAction(_ sender: Any?){...}
...
}

class MenuableCollectionView: UICollectionView {
    var selectedIndexPath: IndexPath?
    
    func setupLongpress() {
        let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPressGesture(_:)))
        self.addGestureRecognizer(longPressGesture)
    }

    func setupMenu() {
        let menuItem = UIMenuItem(title: "action", action: #selector(menuAction(_:)))
        UIMenuController.shared.menuItems = [menuItem]
        UIMenuController.shared.update()
    } 
    
    @objc func handleLongPressGesture(_ sender: UILongPressGestureRecognizer) {
        let point = sender.location(in: self)
        if sender.state == .began {
            guard let indexPath = indexPathForItem(at: point) else {
                return
            }
            
            selectedIndexPath = indexPath
            becomeFirstResponder()
            
            let cell = cellForItem(at: indexPath)
            
            let x: CGFloat = cell?.frame.midX ?? point.x
            let y: CGFloat = 10
            
            let rect = CGRect(x: x, y: y, width: 10, height: 10)
            if #available(iOS 13.0, *) {
                UIMenuController.shared.showMenu(from: self, rect: rect)
            } else {
                UIMenuController.shared.setTargetRect(rect, in: self)
                UIMenuController.shared.setMenuVisible(true, animated: true)
            }
        }
    }
    
    @objc func menuAction(_ sender: Any?) {
        guard let indexPath = selectedIndexPath else {
            return
        }
        let cell = cellForItem(at: indexPath) as? Menuable
        cell?.menuAction(sender)
    }
    
    override var canBecomeFirstResponder: Bool {
        return true
    }
    
    override open func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        if action == #selector(menuAction(_:)) {
            return true
        } else {
            return false
        }
    }
}

// you should call setupLongpress() and setupMenu() after collection view init.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM