I have a very complex app with lots of stacked views which contain lots of buttons ,drawing areas and other custom touch handling . I am displaying a draggable helper view which can be on top of all the other views . I need to dismiss this view if the user taps anywhere outside the helper view . I have tried using multiple UIWindows and adding Gesture recognizers to the UIWindow .
A easy is to add a transparent button which bounds is equal the superview's bounds. And the superview insert the transparent button below your helper view.
The transparent button add a click event which can dismiss the helper view and the transparent button it self.
For example :
UIButton *transparencyButton = [[UIButton alloc] initWithFrame:superview.bounds];
transparencyButton.backgroundColor = [UIColor clearColor];
[superview insertSubview:transparencyButton belowSubview:helperView];
[transparencyButton addTarget:self action:@selector(dismissHelper:) forControlEvents:UIControlEventTouchUpInside];
and the dismissHelper:
method can do this :
- (void)dismissHelper:(UIButton *)sender
{
[helperView dismiss];
sender.hidden = YES;
// or [sender removeFromSuperview]
}
You can check the view being touched by going through the touches and looking at the .view property of the touch. It reflects the view from where the view actually originates.
Assuming that you keep a reference to your view (either via an IBOutlet or otherwise) to your view called "myView" the below works.
In your .m file. The touchesBegan: function is triggered every time the user touches a finger down. We loop through the touches to see if the originating view of the touch is NOT equal to "myView". This comparison could also be done via checking the class, tag or any other property you use to identify your view. Examples given below.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"touches began");
UITouch *touch = [touches anyObject];
if(touch.view!=myView){
myView.hidden = YES;
}
}
Or in case of using a tag:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"touches began");
UITouch *touch = [touches anyObject];
if(touch.view.tag!=23){
myView.hidden = YES;
}
}
create an hittestintercept view. this can make the view below handle events like before.
@protocol HitTestInterceptViewDelegate <NSObject>
- (BOOL)interceptHitTest:(CGPoint)point withEvent:(UIEvent *)event;
@end
@interface HitTestInterceptView : UIView
@property(nonatomic, weak) id<HitTestInterceptViewDelegate> hitTestInterceptDelegate;
@end
HtiTestInterceptView.m
#import "HitTestInterceptView.h"
@implementation HitTestInterceptView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if ([_hitTestInterceptDelegate interceptHitTest:point withEvent:event] == NO) {
return [super hitTest:point withEvent:event];
}
return nil;
}
@end
then use it in the toast view
- (void)dismissIfTouchOutsideInView:(UIView *)view {
if (_interceptView != nil) return;
_interceptView = [[HitTestInterceptView alloc] initWithFrame:view.bounds];
_interceptView.backgroundColor = [UIColor clearColor];
_interceptView.hitTestInterceptDelegate = self;
[view insertSubview:_interceptView belowSubview:self];
}
- (BOOL)interceptHitTest:(CGPoint)point withEvent:(UIEvent *)event {
dispatch_async(dispatch_get_main_queue(), ^{
// [self dismiss];
});
return YES;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With