1

我有三个UIViews

意见

B1并且B2是 的子视图A

B1并且B2可能有一个或多个子视图。

我希望只能同时触摸一个视图。

例如:

用户B1用第一根手指触摸(或其一个子视图),然后在不松开它的情况下,B2用第二根手指触摸(或其一个子视图)。现在,B1应该接收其范围内的所有事件,但不是B2. 反过来也是一样。

这是否可以在不继承任何这些视图的情况下完成?

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

编辑:

关于exclusiveTouchmultipleTouchEnabled

这些属性对我的问题无效。

multipleTouchEnabled:仅确定是否在同一视图中传递多点触摸事件。因此,禁用视图 A 上的多点触控(无论如何都是默认设置)不会阻止视图 B1 和 B2 同时接收触摸事件。

exclusiveTouch: 也不行。据我了解,exclusiveTouch仅适用于 view 的框架内。因此exclusiveTouch在视图 B1 和 B2 上设置无效。请参阅这两个 stackoverflows 以供参考:

为什么 UIView ExclusiveTouch 属性不阻塞?

为什么 UIView.exclusiveTouch 不起作用?

4

3 回答 3

1

尝试为 B1 和 B2 同时设置和exclusiveTouchmultipleTouchEnabledYES

编辑:我从“B1 应该接收其范围内的所有事件”的措辞中假设您希望直接在 B1 和 B2 中接收触摸,而不是它们的子视图。如果您想将触摸限制在 B1/B2 边界但在子视图中处理它们,我认为您需要将 B1 和 B2 或 A 子类化。

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

于 2012-11-01T01:16:51.207 回答
0

当触摸 B1 或 B2 时,为该视图设置exclusiveTouch为,然后在触摸结束时再次YES将其设置回。NO这意味着只有独占视图才会收到触摸。

如果您想在独占视图的范围之外进行触摸,您可以在将其设为独占 ( myExclusiveView) 时将对该视图的引用存储在某处,然后覆盖hitTest:withEvent:视图 A(或任何超级视图)并让它返回[myExclusiveView hitTest:withEvent:]

于 2012-11-01T01:33:48.167 回答
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

所以,这段代码所做的是,它存储了第一次触摸的视图。如果已经存储了一个,它会返回 nil on 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

我知道这不是一个非常优雅的解决方案,如果有人有更好的主意,我将不胜感激。

于 2012-11-06T00:24:55.283 回答