2013-01-03 65 views
3

隨着下面的代碼,我畫了一個圓角的矩形。它繪製了一個很好的淺灰色實心圓角矩形(大小爲「自我」)。我實際上想要繪製像素的倒數,即:不是一個實心的圓角矩形,而是一個窗口或一個圓形矩形的形狀的圓形實心淺灰色矩形。UIView drawRect:繪製倒像素,製作一個洞,一個窗口,負空間

是否有我需要使用的反向剪輯方法?或者我需要使用貝塞爾路徑嗎?請原諒,如果這是非常基本的,但不能找到信息。

感謝您的閱讀!

- (void)drawRect:(CGRect)rect 
{ 

    // get the context 
    CGContextRef context = UIGraphicsGetCurrentContext 

    CGContextSaveGState(context);  

    //draw the rounded rectangle 
    CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]); 
    CGContextSetRGBFillColor(context, 0.8, 0.8, 0.8, 1.0); 
    CGContextSetLineWidth(context, _lineWidth); 

    CGRect rrect = CGRectMake(CGRectGetMinX(rect), CGRectGetMinY(rect), CGRectGetWidth(rect), CGRectGetHeight(rect)); 
    CGFloat radius = _cornerRadius; 

    CGFloat minx = CGRectGetMinX(rrect), midx = CGRectGetMidX(rrect), maxx = CGRectGetMaxX(rrect); 
    CGFloat miny = CGRectGetMinY(rrect), midy = CGRectGetMidY(rrect), maxy = CGRectGetMaxY(rrect); 

    CGContextMoveToPoint(context, minx, midy); 
    // Add an arc through 2 to 3 
    CGContextAddArcToPoint(context, minx, miny, midx, miny, radius); 
    // Add an arc through 4 to 5 
    CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius); 
    // Add an arc through 6 to 7 
    CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius); 
    // Add an arc through 8 to 9 
    CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius); 
    // Close the path 
    CGContextClosePath(context); 

    // Fill the path 
    CGContextDrawPath(context, kCGPathFill); 

    CGContextRestoreGState(context); 

} 

回答

4

將多個子路徑添加到您的上下文中,並使用模式kCGPathEOFill進行繪製。 The Quartz 2D Programming Guide explains in more detail.

// Outer subpath: the whole rect 
CGContextAddRect(context, rrect); 

// Inner subpath: the area inside the whole rect  
CGContextMoveToPoint(context, minx, midy); 
... 
// Close the inner subpath 
CGContextClosePath(context); 

// Fill the path 
CGContextDrawPath(context, kCGPathEOFill); 
+0

感謝您的回答。 – Mrwolfy

1

另一種方法:使用UICreateGraphicsContextWithOptions(size, NO, 0)來製作一個位圖。將矩形繪製到位圖中。切換到刪除混合模式:

CGContextSetBlendMode(con, kCGBlendModeClear); 

現在繪製橢圓路徑並填充它。結果是一個帶有透明橢圓孔的矩形。現在關閉圖像圖形上下文並將圖像繪製到您的原始上下文中。

+1

這會起作用,但比起剛剛填寫正確的路徑要慢很多。另外,如果您想打印或出口到PDF,質量不會很好,並且您的PDF會比所需的大得多。 –

11

這裏的另一種方法,只用UI對象調用:

- (void)drawRect:(CGRect)rect 
{ 
    [[UIColor lightGrayColor] setFill]; 
    CGRect r2 = CGRectInset(rect, 10, 10); 
    UIBezierPath* p = [UIBezierPath bezierPathWithRoundedRect:r2 cornerRadius:15]; 
    [p appendPath: [UIBezierPath bezierPathWithRect:rect]]; 
    p.usesEvenOddFillRule = YES; 
    [p fill]; 
} 

此息率:

enter image description here

白色是窗口的背景;灰色是UIView。正如你所看到的,我們通過視圖看到它背後的任何東西,這聽起來像你所描述的。

+0

好東西。感謝您的答案。 – Mrwolfy

+1

@matt一如既往的偉大和簡單的答案。萬分感謝! –

+1

很簡單的答案。正是我需要的,謝謝! – Gottfried

4

對於插入式解決方案:

  1. 添加PortholeView.swift到Xcode 6(或更高版本)項目

    import UIKit 
    
    @IBDesignable class PortholeView: UIView { 
        @IBInspectable var innerCornerRadius: CGFloat = 10.0 
        @IBInspectable var inset: CGFloat = 20.0 
        @IBInspectable var fillColor: UIColor = UIColor.grayColor() 
        @IBInspectable var strokeWidth: CGFloat = 5.0 
        @IBInspectable var strokeColor: UIColor = UIColor.blackColor() 
    
        override func drawRect(rect: CGRect) { 
        // Prep constants 
        let roundRectWidth = rect.width - (2 * inset) 
        let roundRectHeight = rect.height - (2 * inset) 
    
        // Use EvenOdd rule to subtract portalRect from outerFill 
        // (See http://stackoverflow.com/questions/14141081/uiview-drawrect-draw-the-inverted-pixels-make-a-hole-a-window-negative-space) 
        let outterFill = UIBezierPath(rect: rect) 
        let portalRect = CGRectMake(
         rect.origin.x + inset, 
         rect.origin.y + inset, 
         roundRectWidth, 
         roundRectHeight) 
        fillColor.setFill() 
        let portal = UIBezierPath(roundedRect: portalRect, cornerRadius: innerCornerRadius) 
        outterFill.appendPath(portal) 
        outterFill.usesEvenOddFillRule = true 
        outterFill.fill() 
        strokeColor.setStroke() 
        portal.lineWidth = strokeWidth 
        portal.stroke() 
        } 
    } 
    
  2. 綁定你的目標視圖界面生成器

enter image description here

  1. 在IB中調整插頁,外部填充顏色,筆觸顏色和筆觸寬度!

enter image description here

  • 設置你的限制等意見,記住,你很可能有,如果你需要你的RECT規模以特殊的方式來修改PortholeView旋轉和什麼。在這種情況下,我在PortholeView後面有一個UIImage,用於演示圓形矩形如何通過「偶數規則」切斷周圍路徑。
  • enter image description here

    由於@馬特爲底層繪圖代碼&蘋果在界面生成器曝光IBInspectable/IBDesignable。

    P.S.這可敬的可可愛後會幫助你瞭解「偶/奇」規則,它的兄弟姐妹,「蜿蜒」的規則,以及提供一些額外的策略繪製剪影形狀。 http://www.cocoawithlove.com/2010/05/5-ways-to-draw-2d-shape-with-hole-in.html

    1

    我一直在尋找這樣一個項目,我正在努力。

    我最終做了這樣的事情。

    enter image description here

    我希望這可以幫助別人。

    斯威夫特代碼:

    import UIKit 
    
    class BarCodeReaderOverlayView: UIView { 
    
        @IBOutlet weak var viewFinderView: UIView! 
    
        // MARK: - Drawing 
    
        override func drawRect(rect: CGRect) { 
         super.drawRect(rect) 
    
         if self.viewFinderView != nil { 
          // Ensures to use the current background color to set the filling color 
          self.backgroundColor?.setFill() 
          UIRectFill(rect) 
    
          let layer = CAShapeLayer() 
          let path = CGPathCreateMutable() 
    
          // Make hole in view's overlay 
          CGPathAddRect(path, nil, self.viewFinderView.frame) 
          CGPathAddRect(path, nil, bounds) 
    
          layer.path = path 
          layer.fillRule = kCAFillRuleEvenOdd 
          self.layer.mask = layer 
         } 
        } 
    
        override func layoutSubviews() { 
         super.layoutSubviews() 
        } 
    
        // MARK: - Initialization 
    
        required init?(coder aDecoder: NSCoder) { 
         super.init(coder: aDecoder) 
        } 
    
        override init(frame: CGRect) { 
         super.init(frame: frame) 
        } 
    } 
    
    +0

    也可以在這裏找到:https://gist.github.com/aldo-jlaurenstin/2ed6569b1a3746645143 –

    相關問題