2015-08-16 115 views
11

我使用UIBezierPath讓我的imageview有圓角,但我也想添加一個邊框到imageview。請記住,頂部是一個uiimage,底部是一個標籤。UIBezierPath:如何在帶圓角的視圖周圍添加邊框?

目前使用此代碼生成:

let rectShape = CAShapeLayer() 
rectShape.bounds = myCell2.NewFeedImageView.frame 
rectShape.position = myCell2.NewFeedImageView.center 
rectShape.path = UIBezierPath(roundedRect: myCell2.NewFeedImageView.bounds, 
    byRoundingCorners: .TopRight | .TopLeft, 
    cornerRadii: CGSize(width: 25, height: 25)).CGPath 
myCell2.NewFeedImageView.layer.mask = rectShape 

current

我想綠色邊框添加到這一點,但我不能使用

myCell2.NewFeedImageView.layer.borderWidth = 8 
myCell2.NewFeedImageView.layer.borderColor = UIColor.greenColor().CGColor 

,因爲它切斷左上角和在此圖像中看到的邊框的右上角:

issue

有沒有辦法在我的當前代碼中添加與UIBezierPath的邊界?

+0

這真的不是那麼容易做到這一點 - 在我的回答下面,我試圖解決涉及不幸的微妙之處 – Fattie

回答

0

確實有!每個視圖都有一個layer屬性(通過給出圖層的圓角可以知道)。 layer上的另外兩個屬性是borderColorborderWidth。只需設置那些你可以添加邊框到你的視圖! (邊框將沿着圓角。)請務必使用UIColor.CGColor作爲borderColor,因爲UIColor與本類型不匹配。

+0

如何將它添加到代碼?我一直在拉我的頭髮試圖弄清楚。 – gooberboobbutt

+1

我知道這是怎麼回事!rectShape.borderWidth = 3和rectShape.borderColor = UI Color.greenColor()。CGColor這應該做到這一點! –

+1

但我看到你已經這麼做了。一個簡單的解決辦法是讓綠卡內的圖像稍小一些。 –

28

您可以重複使用UIBezierPath路徑並將形狀圖層添加到視圖中。這是一個視圖控制器內的例子。

class ViewController: UIViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // Create a view with red background for demonstration 
     let v = UIView(frame: CGRectMake(0, 0, 100, 100)) 
     v.center = view.center 
     v.backgroundColor = UIColor.redColor() 
     view.addSubview(v) 

     // Add rounded corners 
     let maskLayer = CAShapeLayer() 
     maskLayer.frame = v.bounds 
     maskLayer.path = UIBezierPath(roundedRect: v.bounds, byRoundingCorners: .TopRight | .TopLeft, cornerRadii: CGSize(width: 25, height: 25)).CGPath 
     v.layer.mask = maskLayer 

     // Add border 
     let borderLayer = CAShapeLayer() 
     borderLayer.path = maskLayer.path // Reuse the Bezier path 
     borderLayer.fillColor = UIColor.clearColor().CGColor 
     borderLayer.strokeColor = UIColor.greenColor().CGColor 
     borderLayer.lineWidth = 5 
     borderLayer.frame = v.bounds 
     v.layer.addSublayer(borderLayer) 
    } 

} 

最終結果如下所示。

Simulator screenshot

注意,當視圖的大小是固定的預期這僅適用。當視圖可以調整大小時,您需要創建自定義視圖類並調整layoutSubviews中的圖層大小。

+0

'''path = UIBezierPath(roundedRect:view.bounds,byRoundingCorners:[.TopRight,.TopLeft],cornerRadii:CGSize(width:25,height:25))。CGPath '''' –

+0

這不是真的正確的細節:***你只看到邊界的一半***。 – Fattie

+0

@JoeBlow:公平點! – hennes

5

正如我上面評論,它是

實際上不容易做到這一點絕對完美。

下面是「OCD解決方案」,這是完全嵌入式代碼。


這裏是一個完整的,總的例子。這

  • 正確地址/解釋說,當你做到這一點,您繪製邊框線的一半的問題

  • 是在自動佈局完全可用

  • 完全重新作品本身時,視圖尺寸變化或動畫

  • 完全是IBDesignable - 您可以在故事板中實時看到它

2017 ...

@IBDesignable 
class RoundedCornersAndTrueBorder: UIView { 
    @IBInspectable var cornerRadius: CGFloat = 10 { 
     didSet { setup() } 
    } 
    @IBInspectable var borderColor: UIColor = UIColor.black { 
     didSet { setup() } 
    } 
    @IBInspectable var trueBorderWidth: CGFloat = 2.0 { 
     didSet { setup() } 
    } 

    override func layoutSubviews() { 
     setup() 
    } 

    var border:CAShapeLayer? = nil 

    func setup() { 
     // make a path with round corners 
     let path = UIBezierPath(roundedRect: self.bounds, cornerRadius:cornerRadius) 

     // note that it is >exactly< the size of the whole view 

     // mask the whole view to that shape 
     // note that you will ALSO be masking the border we'll draw below 
     let mask = CAShapeLayer() 
     mask.path = path.cgPath 
     self.layer.mask = mask 

     // add another layer, which will be the border as such 

     if (border == nil) { 
      border = CAShapeLayer() 
      self.layer.addSublayer(border!) 
     } 
     // IN SOME APPROACHES YOU would INSET THE FRAME 
     // of the border-drawing layer by the width of the border 
     // border.frame = bounds.insetBy(dx: borderWidth, dy: borderWidth) 
     // so that when you draw the line, ALL of the WIDTH of the line 
     // DOES fall within the actual mask. 

     // here, we will draw the border-line LITERALLY ON THE EDGE 
     // of the path. that means >HALF< THE LINE will be INSIDE 
     // the path and HALF THE LINE WILL BE OUTSIDE the path 
     border!.frame = bounds 
     let pathUsingCorrectInsetIfAny = 
      UIBezierPath(roundedRect: border!.bounds, cornerRadius:cornerRadius) 

     border!.path = pathUsingCorrectInsetIfAny.cgPath 
     border!.fillColor = UIColor.clear.cgColor 

     // the following is not what you want: 
     // it results in "half-missing corners" 
     // (note however, sometimes you do use this approach): 
     //border.borderColor = borderColor.cgColor 
     //border.borderWidth = borderWidth 

     // this approach will indeed be "inside" the path: 
     border!.strokeColor = borderColor.cgColor 
     border!.lineWidth = trueBorderWidth * 2.0 
     // HALF THE LINE will be INSIDE the path and HALF THE LINE 
     // WILL BE OUTSIDE the path. so MAKE IT >>TWICE AS THICK<< 
     // as requested by the consumer class. 

    } 
} 

新手幫助下面的問題...

  1. 做一個 「新雨燕文件」 名爲 「Fattie.swift」。 (注意,如果你處於「不知道如何製作一個新文件」的階段,尋找基本的Xcode教程

  2. 把上面所有的代碼放在裏面

  3. 你只是增加了一個類「RoundedCornersAndTrueBorder」到您的項目

  4. 在你的故事板。一個普通UIView的添加到您的場景。讓它實際上任何大小/形狀你喜歡。

  5. 身份檢查員(如果你不知道這是什麼,這很簡單),只需將類更改爲「RoundedCornersAndTrueBorder」。 (一旦你開始輸入「圓鋼......」它會猜測你的意思是哪一類

  6. 大功告成 - 運行項目

注意,你必須這樣做,當然要加。完全限制UIView,就像你在Xcode中做的任何事情一樣。享受!

+0

我們如何使用它來創建邊框?對不起,如果我的問題太天真了。 : -/ – Shyam

+0

嗨@Fattie,非常感謝你的詳細解釋。那麼,我比這稍微好點。但是,再次感謝您花時間幫助我。當然,這會對更多人有所幫助。但是,我尋找的原因是不同的。我有一個UITextView,我需要一個邊框,但我不想使用可用的方法。那可能嗎? – Shyam

+0

我想這是經驗!我試圖做一個解決方法,你就像「只要做到這一點」。真棒!謝謝。但是,我會用我的解決方案。給我一種特殊的感覺。但是,再次感謝! – Shyam