多个 UIView 的重叠

Posted

技术标签:

【中文标题】多个 UIView 的重叠【英文标题】:Multiple UIView's overlapping 【发布时间】:2012-07-13 15:07:23 【问题描述】:

我正在自定义UIView 中创建多个自定义UIView's。自定义子视图的创建是好的。它们看起来像这样:

draw 方法很简单:

[[UIColor brownColor] set];

CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(ctx,
                      5.0f);
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, 0.0f, 0.0f);
CGContextAddLineToPoint(ctx, 100.0f, 0.0);
CGContextAddLineToPoint(ctx, 130.0f, 25.0f);
CGContextAddLineToPoint(ctx, 100.0f, 50.0f);
CGContextAddLineToPoint(ctx, 0.0f, 50.0f);
CGContextClosePath(ctx);
CGContextStrokePath(ctx);
[super drawRect:rect];

将其添加到超级视图中也很简单:

    ITContextFigure *view = [[ITContextFigure alloc] initWithFrame:CGRectMake(location.x, location.y, 135.0f, 50.0f)];
    [view setBackgroundColor:[UIColor yellowColor]];
    [self addSubview:view];

所以我的问题是:

1) 如何检测一个与另一个重叠的时间?

我看到了这个解决方案:

if (CGRectContainsRect([myImageView1 frame], [myImageView2 frame])) 
        NSLog(@"Overlaped, it's working!");

但如果我有多个UIViews,在super view 上执行for 并检查每个子视图对我来说似乎不是一个好的解决方案。

2) 在这种情况下,可以做什么?

我的主要目标是检测何时发生这种情况:


更新 1.0

将尝试here 显示的内容,因为没有更优雅的方法。如果我能够实现它,我会将代码发布到 Github 上,如果有人需要的话。

【问题讨论】:

我想你可能想搜索算法来检测相交的多边形(这涉及暴力每对线段和线段相交)。 我猜你在 2) 中的情况是边界矩形重叠,但视图的主要内容没有? @nhahtdh 并不总是蛮力,您可以使用分离轴定理来检测任意(凸)多边形上的交点 @DanF 是的。 nhahtdh 这就是我要避免的。 @DanF:我同意这可能会有所帮助,但在这种情况下它会比蛮力更好吗? 【参考方案1】:

您可以通过巧妙地对数据进行排序(这些称为扫描线或渗线算法)来显着减少需要执行的碰撞​​检测次数。下面概述了如何将此技术应用于您的情况。

将您的子视图排序到按 y 升序排序的数组中。如果两个子视图共享相同的 y,则按升序排列它们。这是您的非活动列表,它构成了算法的主要输入。

算法如下进行。

    虽然有不活动的子视图,请选择active_y。这是非活动列表中第一个子视图的 y 坐标。

    将原点位于active_y 行的所有子视图移至工作列表,按 x 升序排序。这是活动列表。

    通过活动列表碰撞测试每个子视图与列表中的后续子视图。您可以使用列表中的两个索引来执行此操作(我们称它们为leftright)。只要您看到无法与left 相交的right 子视图,您就可以推进left 索引。

    在进行碰撞检测时,您还可以检查子视图现在是否完全位于active_y 下方。一旦出现,您应该将其从活动列表中删除。

当非活动列表上的所有子视图都被消耗完并且通过活动列表的最终运行完成时,算法完成。

该算法大大减少了您需要执行的碰撞​​检测次数,大约为 O(n log n),但它也可以简化碰撞检测本身。

由于活动列表是从左到右排序的,因此您在执行检测例程时始终知道哪个在左侧,哪个在右侧。因此,例如,在比较示例中的箭头形状时,您只需要检查右侧形状的最左侧两个顶点是否落在左侧形状内。您可能会发现CGPathContainsPoint 很有用。

如果您要处理的不同形状的数量增加,那么您可能需要考虑将碰撞检测推入扫描线算法本身。这有点棘手,但基本上不是保存子视图指针的列表,而是保存构成形状的线段(不包括水平线段)。

【讨论】:

idz 可以去掉多余的黄色部分吗? 是的,不用设置背景色,用黄色填充路径,然后用棕色描边。将UIView 的背景颜色设置为clearColor,并确保视图的opaque 属性为NO。结帐CGContextFillPath,您可能还需要CGContextSetRGBFillColor(我不记得通过UIColor 设置是否也设置了填充颜色)。

以上是关于多个 UIView 的重叠的主要内容,如果未能解决你的问题,请参考以下文章

UIPanGestureRecognizer 与 UISwipeGestureRecognizer 重叠

重叠的透明 UIView

防止 UIView 重叠

与其他 UIView 边框线重叠时的 UIView 边框线粗细

带有自定义 UIView 的 Tableview,添加标签重叠

重叠的 UIView - 如何接收触摸?