forked from Zero-zhou/iOS-Extensions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
UIView+HitTest.swift
69 lines (56 loc) · 2.03 KB
/
UIView+HitTest.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//
// UIView+HitTest.swift
//
// Created by Augus on 6/27/16.
// Copyright © 2016 iAugus. All rights reserved.
//
import UIKit
// REFERENCE: http://stackoverflow.com/a/34774177/4656574
// Handle issue when you need to receive touch on top most visible view.
extension UIView {
///
/// - parameter point: point
/// - parameter event: evet
/// - parameter invisibleOn: If you want hidden view can not be hit, set `invisibleOn` to true
///
/// - returns: UIView
func overlapHitTest(_ point: CGPoint, with event: UIEvent?, invisibleOn: Bool = false) -> UIView? {
// 1
let invisible = (isHidden || alpha == 0) && invisibleOn
if !isUserInteractionEnabled || invisible {
return nil
}
//2
var hitView: UIView? = self
if !self.point(inside: point, with: event) {
if clipsToBounds {
return nil
} else {
hitView = nil
}
}
//3
for subview in subviews.reversed() {
let insideSubview = convert(point, to: subview)
if let sview = subview.overlapHitTest(insideSubview, with: event) {
return sview
}
}
return hitView
}
}
/**
1. We should not send touch events for hidden or transparent views, or views with userInteractionEnabled set to NO;
2. If touch is inside self, self will be considered as potential result.
3. Check recursively all subviews for hit. If any, return it.
4. Else return self or nil depending on result from step 2.
Note: 'subviews.reversed()' needed to follow view hierarchy from top most to bottom. And check for clipsToBounds to ensure not to test masked subviews.
Usage:
Import category in your subclassed view.
Replace hitTest:withEvent: with this
override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
let uiview = super.hitTest(point, withEvent: event)
print(uiview)
return overlapHitTest(point, withEvent: event)
}
*/