2015-08-16 158 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