简体   繁体   中英

Detect touch down & touch up in a view containing UIControls

I'm trying to detect when a user touches down and up in a view. The view contains some buttons and other UIKit controls. I would like to detect these touch events but not consume them.

I've tried two approaches, but neither has been sufficient:

First I added a transparent overlay overriding -touchesBegan:withEvent: and -touchesEnded:withEvent: and forward the event to the next responder with

[self.nextResponder touchesBegan:touches withEvent:event]

However, it seems that UIKit objects ignore all forwarded events.

Next, I tried overriding -pointInside:withEvent: and -hitTest:withEvent: . This worked great to detect touch down events, but pointInside:: and hitTest:: are not called on touch up (ie [[[event allTouches] anyObject] phase] is never equal to UITouchPhaseEnded ).

What's the best way to detect both touch down and touch up events without disturbing interaction with the underlying UIControls?

according to the Event Handling Guide for iOS you have 3 options:

1) subclassing UIWindow to override sendEvent:

2) using an overlay view

3) designing so that you don't have to do that... so really more like 2 options.

Here is a simplification of apples example, using UIWindow subclass;

1) change the class of your window in the NIB to your subclass of UIWindow. 2) put this method in the .m file.

- (void)sendEvent:(UIEvent *)event
{
    NSSet * allTouches = [event allTouches];

    NSMutableSet *began = nil;
    NSMutableSet *moved = nil;
    NSMutableSet *ended = nil;
    NSMutableSet *cancelled = nil;

    // sort the touches by phase so we can handle them similarly to normal event dispatch
    for(UITouch *touch in allTouches) {
        switch ([touch phase]) {
            case UITouchPhaseBegan:
                if (!began) began = [NSMutableSet set];
                [began addObject:touch];
                break;
            case UITouchPhaseMoved:
                if (!moved) moved = [NSMutableSet set];
                [moved addObject:touch];
                break;
            case UITouchPhaseEnded:
                if (!ended) ended = [NSMutableSet set];
                [ended addObject:touch];
                break;
            case UITouchPhaseCancelled:
                if (!cancelled) cancelled = [NSMutableSet set];
                [cancelled addObject:touch];
                break;
            default:
                break;
        }

        // call our methods to handle the touches
        if (began)
        {
            NSLog(@"the following touches began: %@", began);
        };
        if (moved)
        {
            NSLog(@"the following touches were moved: %@", moved);
        };
        if (ended)
        {
             NSLog(@"the following touches were ended: %@", ended);
        };
        if (cancelled) 
        {
             NSLog(@"the following touches were cancelled: %@", cancelled);
        };
    }
    [super sendEvent:event];
}

It has way too much output, but you will get the idea... and can make your logic fit where you want it to.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM