日々精進

新しく学んだことを書き留めていきます

親ビューからはみ出した子ビューでタッチイベントが拾えない

つまみが二つあるスライダーを自作していて、つまみがやけにつかみづらいなーと思ったら、つまみが親ビューからほとんどはみ出しているためタッチイベントがほぼ拾えないことが原因だった。。
下記サイトを参考にカスタムUIWindowを作ってsendEventメソッドを上書きしたらうまくいった!
http://d.hatena.ne.jp/alza/20120207/1328635335


参考にしたサイトのコードから変更した部分は
・はみ出した部分のタッチイベントも拾いたいViewをカスタムUIWindowに登録する
・ドラッグ中にViewのFrameの外に出たことも検知したかったのでViewの外でもイベントは拾っている
コードは以下。

EventDispatchWindow.h

#import <UIKit/UIKit.h>

@interface EventDispatchWindow : UIWindow
@property (nonatomic, retain) NSMutableArray *touchEventCaptureViews;
+ (EventDispatchWindow*)sharedWindow;
@end



EventDispatchWindow.h

#import "EventDispatchWindow.h"
#import "AppDelegate.h"

@implementation EventDispatchWindow
@synthesize touchEventCaptureViews = touchEventCaptureViews_;
static EventDispatchWindow *window;

+ (EventDispatchWindow*)sharedWindow{
    @synchronized(self){
        if (window == nil) {
            window = [[self alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
            window.touchEventCaptureViews = [NSMutableArray array];
            [window.touchEventCaptureViews retain];
        }
        return window;
    }
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)sendEvent:(UIEvent *)event {
    [super sendEvent:event];
    NSSet* touches = [event allTouches];
    for (UIView* view in window.touchEventCaptureViews) {
        for (UITouch* touch in touches) {
            if ([touch phase] == UITouchPhaseBegan) {
                [view beginTrackingWithTouch:touch withEvent:event];
            } else if ([touch phase] == UITouchPhaseMoved) {
                [view continueTrackingWithTouch:touch withEvent:event];
            } else if ([touch phase] == UITouchPhaseEnded) {
                [view endTrackingWithTouch:touch withEvent:event];
            }
        }
    }
}

@end