2014-03-27 37 views
9

我有一个UIView作为子视图添加到我的视图控制器。在这个观点上,我绘制了一条更加缓慢的道路。我的drawRect实现低于检测贝塞尔路径内的水龙头

- (void)drawRect:(CGRect)rect 
{ 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    UIBezierPath *bpath = [UIBezierPath bezierPath]; 

    [bpath moveToPoint:CGPointMake(50, 50)]; 
    [bpath addLineToPoint:CGPointMake(100, 50)]; 
    [bpath addLineToPoint:CGPointMake(100, 100)]; 
    [bpath addLineToPoint:CGPointMake(50, 100)]; 
    [bpath closePath]; 

    CGContextAddPath(context, bpath.CGPath); 
    CGContextSetStrokeColorWithColor(context,[UIColor blackColor].CGColor); 
    CGContextSetLineWidth(context, 2.5); 
    CGContextStrokePath(context); 
    UIColor *fillColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.5 alpha:0.7]; 
    [fillColor setFill]; 
    [bpath fill]; 
} 

我要检测这种贝塞尔路径,但不点,这是UIView的内部和外部的路径里面水龙头。例如,在这种情况下,如果我的触摸坐标是(10,10),则不应该检测到它。我知道关于CGContextPathContainsPoint,但当触摸在路径中时它不起作用。有没有办法检测贝塞尔路径内的触摸事件?

+0

也许您需要添加'CGPathCloseSubpath'。我已经更新了我的答案。请检查。 – Avt

+1

“检测不在UIView内部的这个贝塞尔路径中的tap”这个贝塞尔路径是在UIView内部绘制的,所以如何在它内部但不在UIView内部的水龙头? – matt

+0

@matt:编辑问题 – blancos

回答

13

有一个功能CGPathContainsPoint()它可能对你有帮助。

另外要小心,如果你从superview得到手势点,坐标可能与你的测试不正确。你必须convertPoint的方法从或向特定视图的坐标系统:

- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view 
- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view 
+0

感谢您的开头。 –

8

尝试UIBezierPath的method

func contains(_ point: CGPoint) -> Bool 

返回一个布尔值,指示由 接收器包围的面积是否包含指定点。

+1

CGPathCloseSubpath()不接受bpath作为参数。我曾尝试bpath.CGPath也 – blancos

4

在迅速贝塞尔路径内检测自来水: -

它在最新的快捷简单,请按照下列步骤,你会得到你的UIBezierPath触摸事件。

第1步: - 初始化点击事件查看您的UIBeizerPath添加。

///Catch layer by tap detection let tapRecognizer:UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: #selector(YourClass.tapDetected(_:))) viewSlices.addGestureRecognizer(tapRecognizer)

步骤2: - 使 “tapDetected” 方法

//MARK:- Hit TAP 
public func tapDetected(tapRecognizer:UITapGestureRecognizer){ 
    let tapLocation:CGPoint = tapRecognizer.locationInView(viewSlices) 
    self.hitTest(CGPointMake(tapLocation.x, tapLocation.y)) 


} 

步骤3: - 使 “则hitTest” 最终方法

public func hitTest(tapLocation:CGPoint){ 
     let path:UIBezierPath = yourPath 
     if path.containsPoint(tapLocation){ 
      //tap detected do what ever you want ..;) 
     }else{ 
      //ooops you taped on other position in view 
     } 
    } 



更新:雨燕4

第1步: - 初始化点按事件上观看UIBeizerPath加入其中。

///Catch layer by tap detection 
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(YourClass.tapDetected(tapRecognizer:))) 
viewSlices.addGestureRecognizer(tapRecognizer) 

步骤2: - 使 “tapDetected” 方法

public func tapDetected(tapRecognizer:UITapGestureRecognizer){ 
    let tapLocation:CGPoint = tapRecognizer.location(in: viewSlices) 
    self.hitTest(tapLocation: CGPoint(x: tapLocation.x, y: tapLocation.y)) 
} 

步骤3: - 使 “则hitTest” 最终方法

private func hitTest(tapLocation:CGPoint){ 
    let path:UIBezierPath = yourPath 

    if path.contains(tapLocation){ 
     //tap detected do what ever you want ..;) 
    }else{ 
     //ooops you taped on other position in view 
    } 
} 
+0

@diogo souza感谢您的新更新! :) –

+0

没问题!谢谢你的好回答! ^^ –

1

在夫特3中的溶液。1(从苹果推荐的解决方案移植到here

func containsPoint(_ point: CGPoint, path: UIBezierPath, inFillArea: Bool) -> Bool { 

     UIGraphicsBeginImageContext(self.size) 

     let context: CGContext? = UIGraphicsGetCurrentContext() 
     let pathToTest = path.cgPath 
     var isHit = false 

     var mode: CGPathDrawingMode = CGPathDrawingMode.stroke 

     if inFillArea { 

      // check if UIBezierPath uses EO fill 
      if path.usesEvenOddFillRule { 
       mode = CGPathDrawingMode.eoFill 
      } else { 
       mode = CGPathDrawingMode.fill 
      } 
     } // else mode == stroke 

     context?.saveGState() 
     context?.addPath(pathToTest) 

     isHit = (context?.pathContains(point, mode: mode))! 
     context?.restoreGState() 

     return isHit 
     }