How to ignore touch events in the highest uiview when it is clear and another uiview can handle them

I have a clear UIView to which gesture recognizers are attached.

This transparent uiview covers the entire superview, allowing you to call gestures from anywhere on it.

This comprehensible UIView uses various components, such as tables, buttons, collection, etc.

A clear UIView does not know what is under it at any time.

What I want is if the view under the clear uiview can handle the touch event (or any type of gesture) - the clear view should ignore this event - and the event will go to the main view that it can handle.

I tried

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event

but I don’t know how to make sure that the basic view can handle this.

+1
source share
4 answers

I used some of these suggestions and used the following solution:

I added a gesture recognizer to the lowest most in the hierarchy (and not at the very top)

Then in this class over rid

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView *v = [super hitTest:point withEvent:event];

    // if v is nil then touch wasn't in this view or its subviews
    if (v == nil)
    {
        return nil;
    }

    // in any case if the topview was hidden than return the default value
    if (self.myTopView.hidden)
    {
        return v;
    }

    // if the view isn't hidden but the touch returned a control - than we can pass the touch to the control
    if ([v isKindOfClass:[UIControl class]])
    {
        return v;
    }

    // decide on what threshold to decide is a touch

    CGFloat threshHold = 40;

    // if the touch wasn't on a control but could initiate a gesture than that view should get the touch
    if (v.gestureRecognizers)
    {
        threshHold = 30;
//        return v;
    }

// check if the threshold should be bigger
    if ([self someCondition])
    {
        threshHold = 100;
    }

// threshold according to its position - this is the dynamic part
    if (point.y > (self.myTopView.frame.origin.y - threshold))
    {
        return self.handleBarView;
    }
    return v;
}
0
source

You can override the method pointInside: withEvent:. This method returns a boolean value indicating whether the receiver contains the specified point. Therefore, if we return NO, your upper clear view will become transparent to touch events, and they will be transferred to the main views.

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {

// Clear UIView will now respond to touch events if return NO:
 return NO;
}
+1
source
-(id)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    id hitView = [super hitTest:point withEvent:event];
    if (hitView == self)
    {
            return nil;
    }
    else
    {
        return hitView;
    }
}

.

.

0

use the code below for your case β†’

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    UIView *hitTestView = [super hitTest:point withEvent:event];

    if(hitTestView!=nil){
        //check for gesture
        if([hitTestView.gestureRecognizers count]>0)
            return hitTestView;
        //if it is subclass of UIControl like UIButton etc
        else if([hitTestView isKindOfClass:[UIControl class]])
            return hitTestView;
        //if can handle touches
        else if([hitTestView respondsToSelector:@selector(touchesBegan:withEvent:)])
            return hitTestView;
        else
            return nil;
    }

   else{
       return self;
   }
}

In the above code, if the subView, which is hitView, can handle the touch anyway, we return this object to handle that touch. If there is no such hitTest, then we return the view.

0
source

Source: https://habr.com/ru/post/1528164/


All Articles