如何在旋转的UIView中使用CGRectContainsPoint()

时间:2012-12-25 08:01:49

标签: objective-c ios uiview rotation cgaffinetransform

我有一个UIView,用户可以点按UIView来“选择”或突出显示它所代表的应用内“内容”。我使用CGRectContainsPoint(thing.frame,tapPoint)来实现此目标,其中thing.frameUIView的框架,tapPointUITapGestureRecognizer的抽头点。这很完美。

..除非通过设置UIView属性(transform值)来轮换CGAffineTransform。当UIView像这样旋转时,frame变成一个平面正方形,用于封装旋转的视图。

以下是问题的示意图(框架属性标记为A,视觉UIView bounds标记为B):

未旋转时

+------------------+
|      A == B      |
+------------------+

旋转时

+-----------------+
|  A        .     |
|         .   .   |
|       .       . |
|     .       .   |
|   .    B  .     |
| .       .       |
|   .   .         |
|     .           |
+-----------------+

我想捕获在rect B范围内的点击(UIView的真实界限,旋转),但不是当它们只在rect A范围内时( frame的{​​{1}}属性的值,而不是UIView

我如何计算给定的抽头点是否在旋转的B的真实边界/框架/边界内?有这方便的方法吗?或者我需要使用自己的几何计算UIView的坐标和尺寸吗?

(如果是后者,请提供一个建议,以便我们尽可能完整地回答。谢谢!)

3 个答案:

答案 0 :(得分:10)

你发现了每个人第一次为框架和边界工作时所遇到的一个基本障碍。

框架是视图适合的最小可能(非旋转)矩形,考虑到变换。这意味着,如果您要测试触摸,只要它在最小的可能矩形内,您就可以登录视图周围的可用空间。

对于视觉,想象蓝色方块是转换后的UIView。视图周围的蓝色边框表示它的框架。注意,即使视图被转换,它的帧仍然是未转换的并处于标准位置。如果frame传递而不是bounds,则绿色区域代表可触摸的区域:

frame

另一方面,

Bounds表示接收器的矩形相对于自身,考虑到变换,因此通过传递边界(在-convertPoint:toView:调用之后)测试视图中的点将正确返回是否或不是给定的触摸(点)与视图相交。

答案 1 :(得分:4)

这里是代码,视图是目标视图,视图是包含该点的源视图。

if(CGRectContainsPoint(viewB.bounds, [viewA convertPoint:point toView:viewB])){
    //...
}

答案 2 :(得分:0)

我提出了这个答案,因为我想要一个完整的代码响应解释。如果有人需要代码,为了完整起见,这就是我最终计算视图(containerView)是否完全包含在另一个视图(视图)中的方式:

-(BOOL)viewIsFullyContained:(UIView*)view{
    // get the inner rectangle corners in the view coordinate system
    CGPoint upperLeft   = [self.containerView convertPoint:self.containerView.bounds.origin toView:view];
    CGPoint upperRight  = [self.containerView convertPoint:CGPointMake(self.containerView.bounds.origin.x + self.containerView.bounds.size.width,
                                                                   self.containerView.bounds.origin.y)
                                                toView:view];
    CGPoint lowerLeft   = [self.containerView convertPoint:CGPointMake(self.containerView.bounds.origin.x,
                                                                   self.containerView.bounds.origin.y + self.containerView.bounds.size.height)
                                                toView:view];
    CGPoint lowerRight  = [self.containerView convertPoint:CGPointMake(self.containerView.bounds.origin.x + self.containerView.bounds.size.width,
                                                                   self.containerView.bounds.origin.y + self.containerView.bounds.size.height)
                                                toView:view];
    // Check whether all of the corners are fully contained in the view.
    BOOL upperLeftIsContained   = CGRectContainsPoint(view.bounds, upperLeft);
    BOOL upperRightIsContained  = CGRectContainsPoint(view.bounds, upperRight);
    BOOL lowerLeftIsContained   = CGRectContainsPoint(view.bounds, lowerLeft);
    BOOL lowerRightIsContained  = CGRectContainsPoint(view.bounds, lowerRight);
    NSLog(@"Checking for (%i/%i/%i/%i)",upperLeftIsContained,upperRightIsContained,lowerLeftIsContained,lowerRightIsContained);
    return (upperRightIsContained && upperRightIsContained && lowerRightIsContained && lowerLeftIsContained);
}