sendEvent——A trick for capturing all touch input for the duration of a touch



A trick for capturing all touch input for the duration of a touch


If you’ve ever tried to implement an interactive control that makes use of gestures within a UITableView, or tried to implement a view that you can drag around, like pins on a MKMapView, you’ll know that you’re either generally thwarted by the scroll view (and the table view will just scroll, instead of your control getting the vertical drag gesture), or as soon as the touch moves outside the bounds of your view, you’ll get no more touchesMoved events, making for a very frustrating dragging interaction.


Some platforms give you a way to capture all pointer input for a time, but this doesn’t appear to be available out of the box on the iPhone — at least, I haven’t found it.


Here’s a way to make it work:


Subclass UIWindow and replace sendEvent: with your own method
Provide a way for objects to be registered with your UIWindow subclass to gain ‘touch priority’ – either add a property that taken a UIView/UIResponder, or add a mutable array to be able to register multiple views.
When you receive a touch began event, check to see if the touch was within the bounds of any ‘priority’ views – if they are, the view subsequently gets all events until the touch ended event.


Here’s what the UIWindow subclass could look like:


 
@interface CTTouchInterceptingWindow : UIWindow {
    NSMutableArray *views;
 
    @private
    UIView *touchView;
}
 
- (void)addViewForTouchPriority:(UIView*)view;
- (void)removeViewForTouchPriority:(UIView*)view;
 
@end
 
 
@implementation CTTouchInterceptingWindow
 
- (void)dealloc {
    if ( views ) [views release];
    [super dealloc];
}
 
- (void)addViewForTouchPriority:(UIView*)view {
    if ( !views ) views = [[NSMutableArray alloc] init];
    [views addObject:view];
}
- (void)removeViewForTouchPriority:(UIView*)view {
    if ( !views ) return;
    [views removeObject:view];
}
 
- (void)sendEvent:(UIEvent *)event {
    if ( !views || [views count] == 0 ) {
        [super sendEvent:event];
        return;
    }
 
    UITouch *touch = [[event allTouches] anyObject];
 
    switch ( touch.phase ) {
        case UITouchPhaseBegan:
            for ( UIView *view in views ) {
                if ( CGRectContainsPoint([view frame], [touch locationInView:[view superview]]) ) {
                    touchView = view;
                    [touchView touchesBegan:[event allTouches] withEvent:event];
                    return;
                }
            }
            break;
        case UITouchPhaseMoved:
            if ( touchView ) {
                [touchView touchesMoved:[event allTouches] withEvent:event];
                return;
            }
            break;
        case UITouchPhaseCancelled:
            if ( touchView ) {
                [touchView touchesCancelled:[event allTouches] withEvent:event];
                return;
            }
            touchView = nil;
            break;
        case UITouchPhaseEnded:
            if ( touchView ) {
                [touchView touchesEnded:[event allTouches] withEvent:event];
                return;
            }
            touchView = nil;
            break;
    }
 
    [super sendEvent:event];
}
 
@end
Cocoa, Code, Interface, iPhone. Bookmark the permalink. Both comments and trackbacks are currently closed.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值