Domanda

I have the following setup.

+- XXXCustomControl : UIControl -------+
| A                                    |
|   +- ContentView -------------------+|
|   |                                 ||
|   |  B                              ||
|   |                                 ||
|   +---------------------------------+|
+--------------------------------------+ 

A XXXCustomControl that is a subclass of UIControl. It contains one subview called contentView of type UIView with size that is smaller than the Control's area.. That view has .userInteractionEnabled = YES;

I need that property to have set to YES, because horizontal scrollviews are put inside this once in a while and they need to be scrollable. If the superview (in our case content view would not allow user interaction, this is inherited y the subviews.) But at the same time this XXXCustomControl need to be tappable when it contains no scrollview in its content view not only in area A but also in area B.

So I have a "conflict of interests" here because I either

1) set the content view to userInteractionEnabled = NO, then I can tap the empty control in the content view area both in A and B, but the scrollviews I will put there won't be scrollable..

2) set the content view to userInteractionEnabled = YES but then, if the Control s empty, I can only tap area A to trigger a touch event.

One idea I came up with is that I set the property to NO by default and when I populate the contentView I set it to yes. when I clear the contentView I set the property back to no. Basically I want this to have set to yes all the time, and when it is empty ,force the contentView to pass the touchUpInside event up to its superview.

Is this possible?

È stato utile?

Soluzione

You could try overriding the pointInside:withEvent: method in your inner view. This will allow you to return NO when you want to forward touches to the superview:

-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    if( /* You have content, and you want to receive touches */){
        return YES;
    }else{
        return NO;
    }
}

Altri suggerimenti

You can subclass your subview, and implement

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if (!touchedContent) {
        [[self nextResponder] touchesBegan:touches withEvent:event];
    } else {
        [super touchesBegan:touches withEvent:event];
    }
}

You can use another UIView to "hide" the subview.

*Details : This UIView is the subview's sibling . it has the same size and position of your subview with background color of clear color.

*Explain: The new UIView will take the touch, and automatically pass it to the superview.

This way doesn't need to subclass your subview - it's a storyboard solution.
Please try this. Have fun!

Use this in super view, without changing subviews code (since subviews may be introduced from other frameworks or pods):

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView *view = [super hitTest:point withEvent:event];
    if ([view isDescendantOfView:self])
    {
        NSLog(@"touched inside");
    }
    return view;
}

- Swift

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
    if <#condition#> { return true }
    else { return false }
}

If you want to handle the event from superview(XXXCustomControl in your case) instead of inner view(ContentView in your case), you can write the following swift code in your superview:

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    guard let view = super.hitTest(point, with: event) else { return nil }
    if view.isDescendant(of: self) {
        // your custom logic
    }
    return view
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top