swift自定义上下文菜单previewprovider不能点击里面的任何视图(使用tapgesture)

Posted

技术标签:

【中文标题】swift自定义上下文菜单previewprovider不能点击里面的任何视图(使用tapgesture)【英文标题】:swift custom context menu previewprovider can not click any view inside(using tapgesture) 【发布时间】:2021-03-15 03:27:07 【问题描述】:

我正在处理类似消息的反应,这就是我所做的(使用 contextMenu 中的 customProvider)

以下是我将表情符号操作添加到 customProvider 控制器时的代码

private func addReactionList(_ items : [Reaction]) -> UIView
        let reactionView = UIView()
      
        
        var arrangedSubviews: [UIView] = []
        
        for reaction in items 
            let imgView = UIImageView(image: AppUtils.reactionToImage(reaction: reaction))
            imgView.isUserInteractionEnabled = true
            imgView.frame = CGRect(x: 0, y: 0, width: iconHeight, height: iconHeight)
            imgView.layer.cornerRadius = (imgView.frame.height) / 2
            imgView.layer.masksToBounds = true
            imgView.layer.borderColor = UIColor.clear.cgColor
            imgView.layer.borderWidth = 0
            imgView.contentMode = .scaleAspectFit
            imgView.restorationIdentifier = reaction.Type
            
            
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(_:)))
            tapGesture.delegate = self
            tapGesture.numberOfTapsRequired = 1
            tapGesture.delaysTouchesBegan = true
            tapGesture.cancelsTouchesInView = false
            imgView.isUserInteractionEnabled = true
            imgView.addGestureRecognizer(tapGesture)
            
            arrangedSubviews.append(imgView)
        
        
        let stackView = UIStackView(arrangedSubviews: arrangedSubviews)
        stackView.distribution = .fillEqually
        stackView.spacing = padding
        stackView.layoutMargins = UIEdgeInsets(top: padding, left: padding, bottom: padding, right: padding)
        stackView.isLayoutMarginsRelativeArrangement = true
        
        let width = (CGFloat(items.count) * iconHeight) + (CGFloat(items.count+1) * padding)
        reactionView.frame = CGRect(x: 0, y: 0, width: width, height: iconHeight + 2 * padding)
        reactionView.layer.cornerRadius = 12
        reactionView.addSubview(stackView)
        stackView.frame = reactionView.frame
        stackView.isUserInteractionEnabled = false
        reactionView.isUserInteractionEnabled = false
        
        return reactionView
    

然后我将此添加到自定义提供程序 vc:

let actionsReacts = addReactionList(likeReactions)
        let emojiReacts = addReactionList(emojiReactions)
        if let snap = customView.snapshotView(afterScreenUpdates: true) as UIView?
            view.addSubview(snap)
            view.addSubview(actionsReacts)
            view.addSubview(emojiReacts)
            
            let maxWidth = snap.frame.size.width >= actionsReacts.frame.size.width ? snap.frame.size.width : actionsReacts.frame.size.width
            
            var currentSnapFrame = snap.frame
            currentSnapFrame = CGRect(Int((maxWidth - snap.frame.size.width)) / 2, 0 , Int(snap.frame.size.width), Int(snap.frame.size.height))
            snap.frame = currentSnapFrame
            
            var currentActionsReactFrame = actionsReacts.frame
            currentActionsReactFrame = CGRect(0, Int(snap.frame.size.height), Int(actionsReacts.frame.size.width), Int(actionsReacts.frame.size.height))
            actionsReacts.frame = currentActionsReactFrame
            
            var currentEmojiReactFrame = actionsReacts.frame
            currentEmojiReactFrame = CGRect(0, Int(snap.frame.size.height) + Int(emojiReacts.frame.size.height), Int(emojiReacts.frame.size.width), Int(emojiReacts.frame.size.height))
            emojiReacts.frame = currentEmojiReactFrame
            
            
            preferredContentSize = CGSize(width: maxWidth, height: snap.frame.size.height + actionsReacts.frame.size.height + emojiReacts.frame.size.height)
        

但手势无法触发,我尝试将img更改为按钮,但仍然无法点击

@objc func handleTapGesture(_ sender : UITapGestureRecognizer)
        let tappedImage = sender.view as! UIImageView
        let reactionType = tappedImage.restorationIdentifier ?? ""
        onSelectedReaction?(reactionType)
    
    
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool 
        return true
    
    
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool 
        return true
    

我不知道为什么我不能点击任何地方,即使我尝试将手势点击添加到 viewcontroller 视图。谁能解释一下?提前致谢

【问题讨论】:

嗨,谁能帮忙 你能上传一个demo吗?让我看看 我做到了,先生,谢谢 @famfamfam 你是怎么解决这个问题的? 我正在使用具有透明 + 模糊背景和英雄动画的新 VC 【参考方案1】:

我换了一个新的VC,有英雄动画,很无聊,但这是我现在最好的选择

【讨论】:

【参考方案2】:

我试图根据您提供的内容重建您的演示应用程序,但我仍然不清楚您的代码是什么或它的行为方式。

我注意到你正在创建n 手势识别器并将每个连接到图像视图。 尝试使用 1 个手势识别器。将其连接到您的父视图,并在点击事件时,获取被点击的子视图。

一些代码:

 let tap = UITapGestureRecognizer(target: self, action: #selector(self.onViewTap))
 parentView.addGestureRecognizer(tap)
@objc func onViewTap(_ sender: UITapGestureRecognizer) 
    let point = sender.location(in: containerView)
    if let hitSubview = parentView.hitTest(point, with: nil) 
 // check which subview (imageView) is being hit by checking its tag or similar

【讨论】:

你得到了我的 100 分,即使在视图层次结构中调试时也无济于事,我发现我的 previewProvider 低于 Apple 为处理 panGesture 和 tapGesture 而设计的 1 个滚动视图。 如果你使用 iPhone,你可以看到 Message 应用程序的反应,这就是我想说的

以上是关于swift自定义上下文菜单previewprovider不能点击里面的任何视图(使用tapgesture)的主要内容,如果未能解决你的问题,请参考以下文章

Swift:处理自定义幻灯片菜单中的快速滑动

如何自定义 PDFView 的上下文菜单?

如何像默认上下文菜单一样为 ScrollBar 的自定义上下文菜单获取默认本地化?

为啥这个自定义 nemo 操作没有出现在上下文菜单中?

通过上下文菜单删除后刷新自定义列表视图

从flex3中的自定义按钮调用放大和缩小上下文菜单