Swift:在另一个 UIView 下的 UIView 的 hitTest

Posted

技术标签:

【中文标题】Swift:在另一个 UIView 下的 UIView 的 hitTest【英文标题】:Swift: hitTest for UIView underneath another UIView 【发布时间】:2015-03-17 19:18:29 【问题描述】:

我在 RedOrGreenUIView 之上有 TransparentUIView。 TransparentUIView 附加了一个 UILongPressGestureRecognizer 。一旦用户开始长按它,我会检查这个 LongPressGesture 的 .Changed 状态,并在 hitTest 下面执行:

var p:CGPoint = rec.locationInView(self.view)
var selectedView = view.hitTest(p, withEvent: nil)
if selectedView != nil 
   if selectedView == TransparentUIView 
       println("TransparentUIView is being touched")
   

我将 TransparentView 作为 selectedView 很好。但是我需要能够同时在 RedOrGreenUIView 上进行 hitTest,它位于 TransparentUIView 下方。我无法解决这个问题。请帮忙。

【问题讨论】:

【参考方案1】:

为您的容器创建一个自定义视图并覆盖 pointInside: 消息以在该点不在符合条件的子视图中时返回 NO,如下所示:

@interface PassthroughView : UIView
@end

@implementation PassthroughView
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 
    for (UIView *view in self.subviews) 
        if (!view.hidden && view.alpha > 0 && view.userInteractionEnabled && [view pointInside:[self convertPoint:point toView:view] withEvent:event])
            return YES;
    
    return NO;

@end

快捷版

class PassThroughView: UIView 

     override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool 
            for subview in subviews as [UIView] 
                if !subview.hidden && subview.alpha > 0 && subview.userInteractionEnabled && subview.pointInside(convertPoint(point, toView: subview), withEvent: event) 
                    return true
                
            
            return false
        
    

【讨论】:

在通过 UIView 的过程中,有一个 stackView 与按钮在一个网格中,按钮之间的间隙是 stackView 间距。 stackView 间距不会将触摸传递给下面的视图。请问如何通过stackView间距传递触摸?【参考方案2】:

Swift 4 版本:

 override func point(inside point: CGPoint, with event: UIEvent?) -> Bool 
        for subview in YourView.subviews as [UIView] 

            if !subview.isHidden && subview.alpha > 0 && subview.isUserInteractionEnabled && subview.point(inside:point, with: event) 
                return true
            
        

    return false
 

【讨论】:

当你继承 UIView 时,重写上面的方法。【参考方案3】:

如果一个 UIView 被触摸,那么下面的其他 UIView 就什么也得不到。

因此,您可以有一个中心类将触摸传递给两个 UIView 对象,或者第一个 UIView(位于顶部的那个)将其 UITouch 对象传递给下面的 UIView 并执行 hitTest。

【讨论】:

或者,我可以建议使用方法 swizzling 来获取触摸并将它们发布到任何地方,但是让我们在跑步之前先走,好吗? :) 我喜欢第二个选项。你能告诉我如何将 UITouch 对象传递给另一个视图吗?我用谷歌搜索的所有帮助都在我不理解的 ObjC 中。 @TPos 在你的 UIView 中实现方法 touchesBegan、touchesMoved 和 touchesEnded。这将在此视图中为您提供 UITouch 对象。获得它们后,您可以将它们用于 hitTest 或将这些对象发送到下面的视图。为此,您在下面的视图中编写一个函数并将 UITouch 对象作为参数传递。【参考方案4】:

我目前正在为 ios 应用程序制作透明的帮助叠加层,并且我自己也在寻找一个好的答案。

我真的找不到任何东西,所以决定再看看。 hitTest 上的苹果文档说它不包括透明度

最后一个给了我一个想法,它似乎工作得很好。

尝试以下(我还需要进一步测试,但似乎没问题):

var p:CGPoint = rec.locationInView(self.view)

TransparentUIView.isUserInteractionEnabled = false

var selectedView = view.hitTest(p, withEvent: nil)

TransparentUIView.isUserInteractionEnabled = true

if selectedView != nil 
    if selectedView == TransparentUIView 
        println("TransparentUIView is being touched")
    

【讨论】:

以上是关于Swift:在另一个 UIView 下的 UIView 的 hitTest的主要内容,如果未能解决你的问题,请参考以下文章

UIView iOS Swift下的多个阴影

Swift - UIView.text 显示为 Nil

在 Swift 中将 UIView 保存和检索为 NSData

需要帮助创建复杂的 UIView - Swift xCode [关闭]

swift 3 layoutIfneeded 无法正常工作

一个 UIView Swift 中的多个 TableViews - 如何同时显示