1

我有一张包含许多不同形状建筑物的 3D 地图。我希望用户单击地图上的建筑物,这将充当新视图的转场。

我计划通过创建与建筑物形状相同的不可见按钮来解决此问题,然后将它们放置在 imageview(保存地图)的顶部。

在做了一些阅读之后,我发现创建自定义按钮并不像我想象的那么简单(我认为我将不得不做很多子类化和自定义,当我有 50 多个不同形状的按钮时,这似乎不合理制作),所以我想知道是否有另一种方法可以用来解决这个问题。


编辑:我现在应该补充一点,所有功能都可以正常工作,但我必须使用默认的矩形按钮,alpha 设置为 0.1。

4

2 回答 2

3

编辑以改进数据模型

为此,您将在背景中有一个带有地图图像的 UIView。您可以使用 UIImageView 或在 drawRect 中自己渲染图像来执行此操作。

然后,您将定义几个 CGPath 引用。通过执行这样的操作为每个建筑物创建一个...如何从点数组创建 CGPathRef 点将是每个建筑物的角。

现在以某种方式将这些路径存储在一个数组中。每个“可点击”建筑都需要一条路径。

我会将路径存储在 Building 对象或其他东西中......

@interface Building : NSObject

@property (nonatomic) CGPath path;

@end

现在在您覆盖的 UIView 子类中- (void)touchesBegan...。然后,您可以获取接触点并遍历您的路径以找到被触摸的那个...

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];

    CGPoint touchPoint = [touch locationInView:self];

    for (Building *building in self.buildings) {
        if (CGPathContainsPoint(building.path, CGAffineTransformIdentity, touchPoint, YES)) {
            //the touch was inside this building!
            //now do something with this knowledge.
        }
    }
}
于 2013-02-12T14:12:25.930 回答
1

我曾经实现过一个meteo 应用程序。我们做了一张地图——有几个可点击的区域。定义这些非矩形区域的最简单方法是将它们定义为UIBezierPath,并使用UITapGestureRecognizer UIBezierPath 使用 CGPath,但它是纯 Objective-C。CGPath 的其他优势,您可以轻松地填充/描边这些路径 - 使用随机颜色 - 在调试时可以很好地看到它们

所以

//in you .h, or in class extension

//an array of UIBezierPath you create
// each bezierPath represent an area.
@property (nonatomic, strong) NSArray *myShapes;

//in your .m

- (void)viewDidLoad
{
    [super viewDidLoad];
    //load stuff
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
    [self.view addGesture:tap];

    // ...
}

- (void)handleTap:(UITapGestureRecognizer *)tap
{
    UIBezierPath *recognizedArea = nil;
    //if your shapes are defined in self.view coordinates : 
    CGPoint hitPoint = [tap locationInView:self.view];
    for(UIBezierPath *regionPath in self.myShapes){
        if([regionPath containsPoint:tap]){
            recognizedArea = regionPath;
            break;
        }
    }
    //handle touch for THIS specific area when recognizedArea isn't nil
    if(recognizedArea){
        //YOUR CODE HERE
    }
    // you might also iterate with a normal integer increment
    // and use the path index to retrieve region-specific-data from another array

}
于 2013-02-12T15:03:41.260 回答