UIBezierPath:如何在带圆角的视图周围添加边框?

goo*_*utt 17 uibezierpath swift

我正在使用UIBezierPath让我的imageview有圆角,但我也想为imageview添加边框.请记住,顶部是uiimage,底部是标签.

目前使用此代码生成:

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
Run Code Online (Sandbox Code Playgroud)

当前

我想为此添加绿色边框,但我无法使用

myCell2.NewFeedImageView.layer.borderWidth = 8
myCell2.NewFeedImageView.layer.borderColor = UIColor.greenColor().CGColor
Run Code Online (Sandbox Code Playgroud)

因为它会切断边框的左上角和右上角,如下图所示:

问题

有没有办法添加UIBezierPath边框以及我当前的代码?

hen*_*nes 46

您可以重用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)   
    }

}
Run Code Online (Sandbox Code Playgroud)

最终结果如下所示.

模拟器截图

请注意,只有在视图的大小固定时,这才能正常工作.当视图可以调整大小时,您需要创建自定义视图类并调整图层大小layoutSubviews.


Fat*_*tie 6

正如我上面评论的那样

实际上并不容易做到这一点绝对完美.

这是"OCD解决方案",这是完全插入代码.


这是一个完整的例子.这个

  • 正确地解决/解释了当你这样做的时候,你正在画一些边界线

  • 在autolayout中完全可用

  • 当视图大小发生变化或动画时,它会自行完全重新运行

  • 完全是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.

    }
}
Run Code Online (Sandbox Code Playgroud)

初学者帮助下面的问题......

  1. 制作一个名为"Fattie.swift"的"新Swift文件".(注意,它实际上没有区别你所谓的.如果你处于"不知道如何制作新文件"的阶段,请寻求基本的Xcode教程

  2. 将所有上述代码放入其中

  3. 您刚刚在项目中添加了一个"RoundedCornersAndTrueBorder"类

  4. 在你的故事板上.添加一个普通的UIView到你的场景.使它实际上是您喜欢的任何尺寸/形状.

  5. 身份检查器中(如果您不知道那是什么,请查找基本教程,这很简单),只需将类更改为"RoundedCornersAndTrueBorder".(一旦你开始输入"Roun ...",它就会猜出你的意思.

  6. 你完成了 - 运行项目.

请注意,您必须向UIView添加完整的约束,就像您在Xcode中所做的一样.请享用!


Cla*_*lis 0

肯定有!每个视图都有一个layer属性(您可以通过为图层设置圆角来了解该属性)。另外两个属性layerborderColorborderWidth。只需设置这些,您就可以为您的视图添加边框!(边框将遵循圆角。)请务必使用UIColor.CGColorfor borderColor,因为普通字体UIColor与类型不匹配。

  • 您是否考虑过将 UIImage 和 UILabel 添加为容器 UIView 内的子视图?这样,您可以使 UIImage 的宽度比包含视图稍小,并将标签放置在视图内部。围绕视图的角落,给它一个边框,然后就可以开始了。如果您对如何操作有疑问,请告诉我! (3认同)