Iphone 只允许触摸一个UIView
我有三个Iphone 只允许触摸一个UIView,iphone,ios,ipad,events,uiview,Iphone,Ios,Ipad,Events,Uiview,我有三个ui视图: B1和B2是A的子视图 B1和B2可以有一个或多个子视图 我希望同时只能触摸一个视图。 例如: 用户用第一个手指触摸B1(或其子视图之一),然后在不松开它的情况下,用第二个手指触摸B2(或其子视图之一)。现在,B1应该接收其范围内的所有事件,而不是B2。反过来也是一样 这是否可以在不子类化这些视图的情况下实现 如果没有,最简单/最干净的方法是什么 编辑: 关于排他性触摸和多点触摸: 这些属性对我的问题无效 多点触控:仅确定是否在同一视图中传递多点触控事件。因此,禁用视图A上
ui视图
:
B1
和B2
是A
的子视图
B1
和B2
可以有一个或多个子视图
我希望同时只能触摸一个视图。
例如:
用户用第一个手指触摸B1
(或其子视图之一),然后在不松开它的情况下,用第二个手指触摸B2
(或其子视图之一)。现在,B1
应该接收其范围内的所有事件,而不是B2
。反过来也是一样
这是否可以在不子类化这些视图的情况下实现
如果没有,最简单/最干净的方法是什么
编辑:
关于排他性触摸
和多点触摸
:
这些属性对我的问题无效
多点触控
:仅确定是否在同一视图中传递多点触控事件。因此,禁用视图A上的多点触控(这是默认设置)不会阻止视图B1和B2同时接收触控事件
exclusiveTouch
:也不起作用。据我所知,exclusiveTouch
仅在视图框架内起作用。因此,在视图B1和B2上设置exclusiveTouch
,没有任何效果。
参考这两个StackOverflow:
尝试将B1和B2的
exclusiveTouch
和multipletouched
设置为YES
编辑:根据“B1应接收其范围内的所有事件”的措辞,我假设您希望直接在B1和B2中接收触摸,而不是它们的子视图。如果您想将接触限制为B1/B2边界,但在子视图中处理它们,我认为您需要将B1和B2子类或A子类化
编辑2:如果B1和B2的子视图是交互的,则需要在所有交互子视图上将这些属性设置为
YES
(递归)。但这也会使所有子视图在触摸时相互排斥,而不仅仅是B1和B2之间。尝试将B1和B2的exclusiveTouch
和multipletouched
设置为YES
编辑:根据“B1应接收其范围内的所有事件”的措辞,我假设您希望直接在B1和B2中接收触摸,而不是它们的子视图。如果您想将接触限制为B1/B2边界,但在子视图中处理它们,我认为您需要将B1和B2子类或A子类化
编辑2:如果B1和B2的子视图是交互的,则需要在所有交互子视图上将这些属性设置为
YES
(递归)。但这也使得所有子视图在触摸时相互排斥,而不仅仅是在B1和B2之间。当触摸B1或B2时,将该视图的exclusiveTouch
设置为YES
,然后在触摸结束时再次将其设置回NO
。这意味着只有独占视图才会收到触动
如果您想在独占视图的边界之外进行触摸,您可以在使视图成为独占视图时将对该视图的引用存储在某个位置(
myExclusiveView
),然后覆盖视图a(或任何superview)的hitTest:withEvent:
,并在触摸B1或B2时使其返回[myExclusiveView hitTest:withEvent:
,将该视图的exclusiveTouch
设置为YES
,然后在触摸结束时再次将其设置为NO
。这意味着只有独占视图才会收到触动
如果您想在独占视图的边界之外进行接触,可以在将视图设置为独占时将其引用存储在某个位置(
myExclusiveView
),然后覆盖视图a(或任何superview)的hitTest:withEvent:
,并使其返回[myExclusiveView hitTest:withEvent:]
我认为如果没有子类化,这是不可能的。如果有人能证明我错了,我很高兴看到他们的解决方案。不管怎样,我就是这样解决的:
首先,我将子类viewA
,我调用子类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
我知道这不是一个非常优雅的解决方案,如果有人有更好的想法,我将不胜感激。我相信如果没有子类化,这是不可能的。如果有人能证明我错了,我很高兴看到他们的解决方案。不管怎样,我就是这样解决的: 首先,我将子类view
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
我知道这不是一个非常优雅的解决方案,如果有人有更好的想法,我将不胜感激。禁用v上的多点触控