如何在触摸位置获取层次结构中的所有视图 - Swift

时间:2018-03-05 13:56:28

标签: ios swift uikit

如何在我的触摸位置获得所有UIViews?

在下图中,我需要用黄线接触所有UIViews。

来自UI层次结构的

代码段

enter image description here

我在寻找与SpriteKit类似的功能,我们用它来获取所有节点

self.nodes(at: touch.location(in: self))

5 个答案:

答案 0 :(得分:3)

您必须遍历层次结构中的所有视图,如:

extension UIView {
    func allViews(for touch: UITouch) -> [UIView] {
        return self.allViews(at: touch.location(in: self))
    }

    func allViews(at point: CGPoint) -> [UIView] {
        var stack = [UIView]()
        var result = [UIView]()

        stack.append(self)
        while let view = stack.popLast() {
            let localPoint = view.convert(point, from: self)

            if view.bounds.contains(localPoint) {
                result.append(view)
            }
            stack.append(contentsOf: view.subviews)
        }
        return result
    }
}

您可以从任何包含所有适当视图的超级视图(例如视图控制器的视图)或窗口开始。第二种方法的要点必须相对于由self表示的视图边界。

答案 1 :(得分:0)

在UIKit中,响应者链的工作方式与this类似,我认为没有办法获取所有列表,因为触摸“触发”直到响应者捕获它而不是进一步。

答案 2 :(得分:0)

func subviewsThatContain(point: CGPoint, in view: UIView) -> [UIView] {
    var views = [UIView]()

    for subview in view.subviews {
        if subview.frame.contains(subview.convert(point, from: self.view)) {
            views.append(subview)
        }

        views += subviewsThatContain(point: point, in: subview)
    }

    return views
}

和函数调用看起来像这样

var allViews = [self.view] + subviewsThatContain(in: self.view, point: touch.location(in: self.view))

答案 3 :(得分:0)

这可以通过两个步骤实现:

  1. 从某个视图开始获取所有视图

    func descendants(of view: UIView) -> [UIView] {
        return view.subviews + view.subviews.flatMap(descendants(of:))
    }
    
  2. 过滤包含触摸点的视图:

    let touchLocation = touchGesture.location(in: nil)
    let matchingViews = descendants(of: UIApplication.shared.keyWindow!)
        .filter { $0.convert($0.bounds, to: nil).contains(touchLocation) }
    

答案 4 :(得分:-2)

您可以使用hittest检查所有视图层次结构

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        guard let point = targetPoint,
            var view = super.hitTest(point, with: event) else {
                return
        }
        var views: [UIView] = [view]
        while view != nil {
            view = view.hitTest(point, with: event)
            if view != nil {
                views.append(view!)
            }
        }
    }