2012-11-01 37 views
1

我有三个UIViews只允许一个UIView的被感动

views

B1B2A子视图。

B1B2可能有一个或多个子视图。

我希望只有一个视图可以在同一时间触及。

例如:

用户触摸B1(或它的子视图中的一个)与所述第一手指,然后,不释放它,倒是B2(或它的子视图中的一个)与第二手指。现在,B1应该接收所有事件的边界,但不是B2。反过来也是如此。

这可能完成没有任何这些视图的子类

如果不是,最简单/最干净的方法是什么?

编辑:

关于exclusiveTouchmultipleTouchEnabled

这些属性不适用于我的问题。

multipleTouchEnabled:仅确定是否在相同视图中传递多点触摸事件。因此,禁止在视图A上进行多点触摸(反正是默认设置)不会阻止视图B1和B2同时接收触摸事件。

exclusiveTouch:也不管用。据我所知,exclusiveTouch只能在的框架内工作。因此,在视图B1和B2上设置exclusiveTouch不起作用。 看到这两个stackoverflows供参考:

Why is UIView exclusiveTouch property not blocking?

Why doesn't UIView.exclusiveTouch work?

+0

对视图禁用多点触控:) – deanWombourne

回答

0

我相信这是不可能没有子类。如果有人能证明我错了,我很乐意看到他们的解决方案。无论如何,这是我如何解决它:

首先,我的子类视图A,我称之为子类ParentView。 ParentView需要指向B1B2。我还添加了一个稍后用于存储当前选定视图的额外指针。然后,我重写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 hitTest,这会消耗任何其他触摸事件。

现在,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 

我知道这是不是一个非常优雅的解决方案,如果有人有更好的想法,我会很感激。

1

尝试为B1和B2同时设置exclusiveTouchmultipleTouchEnabledYES

编辑:我是从措辞假设“B1应接收所有事件在其边界”要收到触摸直接在B1 B2 &,而不是他们的子视图。如果你想限制接触到B1/B2界限,但我认为你需要继承B1和B2,或A的子视图处理它们

编辑2:如果是B1和B2的子视图是是交互式的,您需要在所有交互式子视图(递归)上将这些属性设置为YES。但是这也使得所有的子视图都是互斥的,而不仅仅是在B1和B2之间。

+0

请参阅我对“exclusiveTouch”和“multipleTouchEnabled”的编辑。关于您的编辑:我希望触摸可以正常处理。所以说有一个tableView作为视图B1的子视图,我希望能够正常地与它交互。但是当我第一次触摸B2时,我不希望用户能够与B1中的tableView交互。 – avf

+0

@megamer'exclusiveTouch'意味着视图只会触及_window_,因此如果B1和B2是您想要专门接收触摸的视图,则这些设置将起作用。但是,由于看起来您希望他们的子视图能够接收触摸,所以无法使用。您可以在B1和B2的每个子视图中将这些属性设置为YES(如果它们还有子视图,则递归),但这也会触及多个子视图互斥。 – Arkku

+0

edit2:是的,这将是一个选项,但它不是我想要的 - 每次添加新的子视图时,我都必须考虑这一点。我想找到一个对于视图B1和B2中的任何子视图永久/有效的解决方案。 – avf

0

当触摸B1或B2时,为该视图设置exclusiveTouchYES,然后在触摸结束时再次将其设置为NO。这意味着只有独家观点才会受到欢迎。

如果你想获得独家视图的边界之外倒是可以存储视图的参考的地方,当你把它独占(myExclusiveView),然后覆盖hitTest:withEvent:的视图A(或任何上海华),并使其返回[myExclusiveView hitTest:withEvent:]