I have two windows -- a front one, and a back one. The front one is used to overlay some stuff on top of the back one. I want to be able to capture touches on some parts of the front window, but not others; I want the front window to receive touches in some areas, but pass them through to the back window in others.
Any ideas as to how I'd do this?
Ok, here's what I did: I created two views in the front window. The first view covered the area where I wanted to catch the touches; the second, where I wanted the touches to pass through. I sub-classed UIWindow and overrode the hitTest:withEvent method like so:
- (UIView *) hitTest:(CGPoint)point withEvent:(UIEvent *)event {
// See if the hit is anywhere in our view hierarchy
UIView *hitTestResult = [super hitTest:point withEvent:event];
// ABKSlideupHostOverlay view covers the pass-through touch area. It's recognized
// by class, here, because the window doesn't have a pointer to the actual view object.
if ([hitTestResult isKindOfClass:[ABKSlideupHostOverlayView class]]) {
// Returning nil means this window's hierachy doesn't handle this event. Consequently,
// the event will be passed to the host window.
return nil;
}
return hitTestResult;
}
And in the class which creates the front window, I used a gesture recognizer to catch touches on the first view.
Same in 2017 code:
class PassView: UIView {}
class UIHigherWindow: UIWindow {
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let hitView = super.hitTest(point, with: event)
if hitView!.isKind(of: PassView.self) {
return nil
}
return hitView
}
}
Your "uber" window will be some view controller, UberVc.
Just make the main view (that is to say, simply the background .view) of UberVc be a PassView.
Then add say buttons etc. on the UberVc.
The above code results in any clicks on the buttons going to UberVc, and any clicks not on the buttons (ie, on the "background") going through to your regular window/VCs.
If you simply want to pass everything through (so, the over-window is perhaps a message only or some sort of temporary thing), it's simply
class PassTroughWindow: UIWindow {
override func hitTest(_ p: CGPoint, with e: UIEvent?) -> UIView? {
return nil
}
}
and you're done.