2014-03-27 39 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 
     }