繁体   English   中英

将多个可点击的形状添加到UIView

[英]Adding multiple tappable shapes to UIView

我有很多展位的平面图。 加载UIView时,将显示UIImage和平面图,并检查数据库以获取参展商及其位置的列表。 将位置加载到阵列中,并为每个参展商创建一个UIButton ,并将其放置在其展位所在的平面图上。 点击时,此按钮将显示有关该参展商的信息。

这是平面图的屏幕截图,其中带有渲染按钮的框。

在此处输入图片说明

这很好用,但是我需要将按钮设置为不规则形状(三角形,五边形,圆形等)。 因此,我需要一种绘制这些形状并使其与按钮一样可单击的方法。

我创建了一个测试类,该类生成一个包含形状的UIView并将其添加到我的原始UIView 我感觉这可能不是正确的方法,因为我将需要在屏幕上具有许多按钮,这意味着许多视图相互堆叠。 我不知道如何检查点击的形状,因为UIViews会相互重叠。

是否可以在一个视图上绘制所有形状,然后添加视图? 最好的方法是什么?

就UI而言,最干净的方法是使用实​​际的按钮。 将其类型设置为custom,并将其image属性设置为要显示的图像。 这样,按钮可以正确处理突出显示,并像常规按钮一样管理IBAction。 您可以将所有按钮设置为指向相同的动作,并使用标签值确定哪个按钮是哪个按钮。

您可以从代码中或在IB中创建这些按钮-更好地适合您的设计。

您也可以使用自定义视图或上面带有图形的单个视图来执行此操作。 如果对每个展位使用视图,则需要在每个视图上附加一个轻击手势识别器,并将其userInteractionEnabled标志设置为YES。

如果要在整个平面图中使用图形,则需要在图形视图中添加一个轻击手势识别器,然后解释该轻敲的坐标以找出其所放到的图像。

覆盖- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event地图表示者视图的- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event方法的- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event方法。 因此,您将能够将当前触摸位置与所有形状进行比较,并计算出您的触摸点所处的形状。 对于不同的形状有不同的方法(例如,点在矩形内吗?

ole有一个很棒的项目: OBShapedButtons 他通过检查触摸像素的alpha值并覆盖-pointInside:withEvent:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 
{
    // Return NO if even super returns NO (i.e., if point lies outside our bounds)
    BOOL superResult = [super pointInside:point withEvent:event];
    if (!superResult) {
        return superResult;
    }

    // Don't check again if we just queried the same point
    // (because pointInside:withEvent: gets often called multiple times)
    if (CGPointEqualToPoint(point, self.previousTouchPoint)) {
        return self.previousTouchHitTestResponse;
    } else {
        self.previousTouchPoint = point;
    }

    BOOL response = NO;

    if (self.buttonImage == nil && self.buttonBackground == nil) {
        response = YES;
    }
    else if (self.buttonImage != nil && self.buttonBackground == nil) {
        response = [self isAlphaVisibleAtPoint:point forImage:self.buttonImage];
    }
    else if (self.buttonImage == nil && self.buttonBackground != nil) {
        response = [self isAlphaVisibleAtPoint:point forImage:self.buttonBackground];
    }
    else {
        if ([self isAlphaVisibleAtPoint:point forImage:self.buttonImage]) {
            response = YES;
        } else {
            response = [self isAlphaVisibleAtPoint:point forImage:self.buttonBackground];
        }
    }

    self.previousTouchHitTestResponse = response;
    return response;
}

另一个测试该点是否在图层蒙版中的示例代码,也许您可​​以更轻松地进行调整:

@implementation MyView
//
// ...
//
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    CGPoint p = [self convertPoint:point toView:[self superview]];
    if(self.layer.mask){
        if (CGPathContainsPoint([(CAShapeLayer *)self.layer.mask path], NULL, p, YES) )
            return YES;
    }else {
        if(CGRectContainsPoint(self.layer.frame, p))
            return YES;
    }
    return NO;
}

@end

全文: http : //blog.vikingosegundo.de/2013/10/01/hittesting-done-right/

最后,这就是我所做的:

  • 遍历我需要的所有支架形状,并创建一个字典,在平面图图像上使用其坐标的UIBezierpath和形状的standNo。
  • 然后,我将这些字典添加到数组中。
  • 轻按屏幕时,我会注意轻按位置的X和Y并遍历字典数组,并检查UIBezierpath是否包含由X和Y轻按坐标组成的点。
  • 如果找到一个在其边界内具有X和Y坐标的形状,我将使用UIBezierpath并添加fillColor绘制一个CAShapelayer,使其在地图上显示。 然后显示一个alertView,其中显示有关参展商的更多信息。

这种方法似乎比实际绘制数百个UIButton甚至CAShaplayers,甚至在平面图上具有300多个区域来检查整个过程是否立即显示都更为有效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM