Add a border outside of a UIView (instead of inside) Add a border outside of a UIView (instead of inside) ios ios

Add a border outside of a UIView (instead of inside)


Unfortunately, there isn't simply a little property you can set to align the border to the outside. It draws aligned to the inside because the UIViews default drawing operations draw within its bounds.

The simplest solution that comes to mind would be to expand the UIView by the size of the border width when applying the border:

CGFloat borderWidth = 2.0f;self.frame = CGRectInset(self.frame, -borderWidth, -borderWidth);self.layer.borderColor = [UIColor yellowColor].CGColor;self.layer.borderWidth = borderWidth;


Ok, there already is an accepted answer but I think there is a better way to do it, you just have to had a new layer a bit larger than your view and do not mask it to the bounds of the view's layer (which actually is the default behaviour). Here is the sample code :

CALayer * externalBorder = [CALayer layer];externalBorder.frame = CGRectMake(-1, -1, myView.frame.size.width+2, myView.frame.size.height+2);externalBorder.borderColor = [UIColor blackColor].CGColor;externalBorder.borderWidth = 1.0;[myView.layer addSublayer:externalBorder];myView.layer.masksToBounds = NO;

Of course this is if you want your border to be 1 unity large, if you want more you adapt the borderWidth and the frame of the layer accordingly.This is better than using a second view a bit larger as a CALayer is lighter than a UIView and you don't have do modify the frame of myView, which is good for instance if myView is aUIImageView

N.B : For me the result was not perfect on simulator (the layer was not exactly at the right position so the layer was thicker on one side sometimes) but was exactly what is asked for on real device.

EDIT

Actually the problem I talk about in the N.B was just because I had reduced the screen of the simulator, on normal size there is absolutely no issue

Hope it helps


With the above accepted best answer i made experiences with such not nice results and unsightly edges:

border without bezier path

So i will share my UIView Swift extension with you, that uses a UIBezierPath instead as border outline – without unsightly edges (inspired by @Fattie):

border with bezier path

//  UIView+BezierPathBorder.swiftimport UIKitextension UIView {    fileprivate var bezierPathIdentifier:String { return "bezierPathBorderLayer" }    fileprivate var bezierPathBorder:CAShapeLayer? {        return (self.layer.sublayers?.filter({ (layer) -> Bool in            return layer.name == self.bezierPathIdentifier && (layer as? CAShapeLayer) != nil        }) as? [CAShapeLayer])?.first    }    func bezierPathBorder(_ color:UIColor = .white, width:CGFloat = 1) {        var border = self.bezierPathBorder        let path = UIBezierPath(roundedRect: self.bounds, cornerRadius:self.layer.cornerRadius)        let mask = CAShapeLayer()        mask.path = path.cgPath        self.layer.mask = mask        if (border == nil) {            border = CAShapeLayer()            border!.name = self.bezierPathIdentifier            self.layer.addSublayer(border!)        }        border!.frame = self.bounds        let pathUsingCorrectInsetIfAny =            UIBezierPath(roundedRect: border!.bounds, cornerRadius:self.layer.cornerRadius)        border!.path = pathUsingCorrectInsetIfAny.cgPath        border!.fillColor = UIColor.clear.cgColor        border!.strokeColor = color.cgColor        border!.lineWidth = width * 2    }    func removeBezierPathBorder() {        self.layer.mask = nil        self.bezierPathBorder?.removeFromSuperlayer()    }}

Example:

let view = UIView(frame: CGRect(x: 20, y: 20, width: 100, height: 100))view.layer.cornerRadius = view.frame.width / 2view.backgroundColor = .red//add white 2 pixel border outlineview.bezierPathBorder(.white, width: 2)//remove border outline (optional)view.removeBezierPathBorder()