我有三个UIViews
:
B1
和B2
是A
的子视图。
B1
和B2
可能有一个或多个子视图。
我希望同时只能触摸一个视图。
例如:
用户用第一根手指触摸B1
(或其中一个子视图),然后在不释放的情况下,用第二根手指触摸B2
(或其中一个子视图)。现在,B1
应该接收其范围内的所有事件,但不是B2
。反之亦然。
这可以完成而无需继承任何这些视图吗?
如果没有,最简单/最干净的方法是什么?
修改
关于exclusiveTouch
和multipleTouchEnabled
:
这些属性对我的问题无效。
multipleTouchEnabled
:仅确定是否在同一视图中传递多点触控事件。因此,禁用视图A上的多点触控(无论如何都是默认设置)不会阻止视图B1和B2同时接收触摸事件。
exclusiveTouch
:也不起作用。据我所知,exclusiveTouch
仅在视图框架内工作。因此,在视图B1和B2上设置exclusiveTouch
无效。
请参阅以下两个stackoverflow以供参考:
答案 0 :(得分:1)
尝试为B1和B2设置exclusiveTouch
和multipleTouchEnabled
至YES
。
编辑:我假设“B1应该接收其范围内的所有事件”这一措辞,您希望直接在B1& B2,不是他们的子视图。如果你想限制接触B1 / B2边界但是在子视图中处理它们我认为你需要子类B1和B2,或者A。
编辑2 :如果是B1和B2的子视图是交互式的,则需要在所有交互式子视图(递归)上将这些属性设置为YES
。但这也使所有子视图互相排斥,而不仅仅是B1和B2之间。
答案 1 :(得分:0)
触摸B1或B2时,请为该视图将exclusiveTouch
设置为YES
,然后在触摸结束时再将其设置回NO
。这意味着只有独家视图才会收到触摸。
如果您希望在独占视图范围之外进行触摸,则可以在将视图设为独占视图(myExclusiveView
)时存储对该视图的引用,然后对视图A(或任何超级视图)覆盖hitTest:withEvent:
并让它返回[myExclusiveView hitTest:withEvent:]
。
答案 2 :(得分:0)
我相信如果没有子类化,就不可能。如果有人能证明我错了,我很乐意看到他们的解决方案。无论如何,这就是我解决它的方式:
首先,我将视图A
子类化,我调用子类ParentView
。 ParentView需要指向B1
和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
所以,这段代码的作用是,它存储了第一个被触摸的视图。如果已经存储了一个,则会在hitTest
上返回nil,这会占用任何其他触摸事件。
现在,currentlyTouchedView
在哪里被设置为零?为此,我将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
我知道这不是一个非常优雅的解决方案,如果有人有更好的想法,我会很感激。