これは、サブクラス化なしでは不可能だと思います。誰かが私が間違っていることを証明できるなら、彼らの解決策を喜んで見てみたい. とにかく、これは私がそれを解決した方法です:
まず、ビューをサブクラス化A
し、サブクラスを呼び出しますParentView
。B1
ParentView にはおよびへのポインタが必要B2
です。また、現在選択されているビューを保存するために後で使用する追加のポインターも追加します。次に、オーバーライドしますhitTest
:
@interface ParentView : UIView
@property (nonatomic, strong) UIView* viewB1;
@property (nonatomic, strong) UIView* viewB2;
@property (nonatomic, strong) UIView* currentlyTouchedView;
@end
@implementation ParentView
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if (self.currentlyTouchedView == nil) {
if (CGRectContainsPoint(self.viewB1.frame, point)) {
self.currentlyTouchedView = viewB1;
}else if(CGRectContainsPoint(self.viewB2.frame, point)) {
self.currentlyTouchedView = viewB2;
}
}else {
if (!CGRectContainsPoint(self.currentlyTouchedView.frame, point)) {
return nil;
}
}
return [super hitTest:point withEvent:event];
}
@end
つまり、このコードが行うことは、最初に触れたビューを保存することです。すでに格納されている場合は nil on を返しhitTest
、追加のタッチ イベントを使い果たします。
では、どこでcurrentlyTouchedView
nil に設定を戻すのでしょうか? そのために、サブクラス化UIWindow
してオーバーライドsendEvent
し、すべてのタッチが終了したかどうかを確認します。
@implementation EventOverrideWindow
- (void)sendEvent:(UIEvent *)event {
[super sendEvent:event];
BOOL allTouchesEnded = YES;
for (UITouch* touch in event.allTouches) {
if (touch.phase != UITouchPhaseCancelled && touch.phase != UITouchPhaseEnded) {
allTouchesEnded = NO;
break;
}
}
if (allTouchesEnded) {
ParentView* parentView = ((AppDelegate*)[UIApplication sharedApplication].delegate).parentView;
parentView.currentlyTouchedView = nil;
}
}
@end
これは非常にエレガントな解決策ではないことはわかっています。誰かがより良いアイデアを持っていれば幸いです。