【问题标题】:Non-rectangular 'clickable' area非矩形“可点击”区域
【发布时间】:2013-02-12 14:07:18
【问题描述】:

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

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

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


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

【问题讨论】:

    标签: objective-c xcode


    【解决方案1】:

    经过编辑以改进数据模型

    为此,您将在背景中有一个带有地图图像的 UIView。您可以使用 UIImageView 或在 drawRect 中自己渲染图像来做到这一点。

    然后您将定义几个 CGPath 引用。通过执行这样的操作为每个建筑物一个...How to create CGPathRef from Array of points 这些点将是每个建筑物的角落。

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

    我会将路径存储在 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.
            }
        }
    }
    

    【讨论】:

    • 所以你是说把我当前的 UIImageView 放在一个 UIView 里面,然后检查所有触摸的位置?
    【解决方案2】:

    我曾经实现过一个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
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-26
      • 1970-01-01
      • 2011-10-06
      • 1970-01-01
      • 2020-07-01
      • 1970-01-01
      • 2021-02-23
      • 1970-01-01
      相关资源
      最近更新 更多