Is it possible to set UIView border properties from interface builder?
Asked Answered
W

9

201

Is it possible to control UIView border properties (color, thickness, etc...) directly from interface builder or I can only do it programmatically?

Warnerwarning answered 6/9, 2012 at 13:31 Comment(2)
Check this https://mcmap.net/q/129549/-change-uibutton-bordercolor-in-storyboardSpice
Just in case anyone comes from Google like I did. To see those changes reflect in IB you just need to create a subclass of UIView and assign it to whatever View you want to manipulate in IB.Ie
S
405

Actually you can set some properties of a view's layer through interface builder. I know that I can set a layer's borderWidth and cornerRadius through xcode. borderColor doesn't work, probably because the layer wants a CGColor instead of a UIColor.

You might have to use Strings instead of numbers, but it works!

layer.cornerRadius
layer.borderWidth
layer.borderColor

Update: layer.masksToBounds = true

example

Update: select appropriate Type for Keypath:

enter image description here

Salba answered 5/4, 2013 at 17:28 Comment(14)
To you and Peter DeWeese: I use Xcode 4.6.3 and I can set keypath type to "Color" without impleting a CALayer interfaceBraddock
Thanks for the heads up! They must have fixed that in a newer version of xcode than I had at the timeSalba
Unfortunately layer.borderColor can't be set this way. It's a CGColorRef, but that IB Color value type is a UIColor.Dottie
Make sure you have included the QuartzCore framework or it won't work.Gerdes
So THIS is what the user defined runtime attributes does! Haha, been writing for iOS since 2011 and I never learned what those fields were for. Thanks for this awesome answer.Jacklynjackman
layer.borderColor does not seem to work in IB (Xcode 6). Again guessing that its because its a UIColor not a CGColor.Shoer
Number types for cornerRadius, borderWidth works fine. layer.borderColor does not work because it is not CGColor.Brandnew
Here is my solution from within IB in storyboard, all working (even Color) :) stackoverflow.com/a/29074130Pearlpearla
Nice, but you have to set the correct type for each property. The Type for e. g. "layer.cornerRadius" has to be set to "Number" instead of "String"!Nester
If it does not work, make sure you don't have layer.borderColor or borderColor under User Defined Runtime AttributesDrislane
I came here looking for why my corners wouldn't bend, only to find out I had misspelled cornerRadius in the inspector :)Ducan
Hi everyone - just wanted to point out that this answer is only valid in conjunction with the answer from @Peter DeWeeseMcbryde
Also, don't forget to check the "clip to bounds" checkbox to have the cornerRadius working.Crespi
Should be layer.borderUIColorClassy
C
191

Rich86Man's answer is correct, but you can use categories to proxy properties such as layer.borderColor. (From the ConventionalC CocoaPod)

CALayer+XibConfiguration.h:

#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>

@interface CALayer(XibConfiguration)

// This assigns a CGColor to borderColor.
@property(nonatomic, assign) UIColor* borderUIColor;

@end

CALayer+XibConfiguration.m:

#import "CALayer+XibConfiguration.h"

@implementation CALayer(XibConfiguration)

-(void)setBorderUIColor:(UIColor*)color
{
    self.borderColor = color.CGColor;
}

-(UIColor*)borderUIColor
{
    return [UIColor colorWithCGColor:self.borderColor];
}

@end

Interface Builder

layer.borderUIColor

The result will be apparent during runtime, not in Xcode.

Edit: You also need to set layer.borderWidth to at least 1 to see the border with the chosen color.

In Swift 2.0:

extension CALayer {
    @objc var borderUIColor: UIColor {
        set {
            self.borderColor = newValue.CGColor
        }
    
        get {
            return UIColor(CGColor: self.borderColor!)
        }
    }
}

In Swift 3.0:

extension CALayer {
    @objc var borderUIColor: UIColor {
        set {
            self.borderColor = newValue.cgColor
        }
    
        get {
            return UIColor(cgColor: self.borderColor!)
        }
    }
}
Craigie answered 1/8, 2013 at 12:19 Comment(12)
I can't get this to work for me. The .m file moans about borderColor having to be borderUIColor and to fix it, after doing so it still shows warnings and the border color doesnt render at runtime. The bit that is different on mine is I have @ implementation NameOfFile, not @ implementation CALayer(NameOfFile), I dont understand the CALayer part, could you explain that more pleasePossess
CALayer(myCategory) is a category, that is, it adds its methods to an existing class that is implemented elsewhere. In this case CALayer is included with the framework and I am just adding the borderUIColor property to it. Your way of implementing this will not work, although I suppose that you could add the property to your view controller and have it update the layer instead.Craigie
To get it work you should set borderWidth type to String, not Number. Pretty confusing.Ervinervine
You actually can use Number with borderWidth and accept an NSNumber. It works fine.Craigie
We cannot add variable in category. I am not getting how this whole thing is working? Can you please explain, I am confused?Conias
@Nuzhat Zari, The variable already exists in CALayer, and this is simply adding a wrapper around it. No variable is created by the category!Craigie
I have applied layer.borderUIColor in User defined runtime attributes...it's not working in runtime also.Gambier
@Singapore, try setting breakpoints in your category methods to make sure it is calling them. As a note, you can simply proxy it from UIView instead of CALayer.Craigie
This is definitely the best solution in my opinion to solve the issue of BorderColor. Fantastic use of categories!Koloski
If anyone's wondering about the Swift solutions, it works! 01. Create a Cocoa Touch Class file: UIButton. 02. Associate the IB Button with your newly created class in IB. 03. Add the extension to the newly created class (above code).Consecution
Worked in Swift !Baalbeer
In case if swift doesn't work for someone, try this https://mcmap.net/q/129550/-xcode-9-bordercolor-doesn-39-t-work-in-user-defined-runtime-attributesLevania
T
95

Similar answer to iHulk's one, but in Swift

Add a file named UIView.swift in your project (or just paste this in any file) :

import UIKit

@IBDesignable extension UIView {
    @IBInspectable var borderColor: UIColor? {
        set {
            layer.borderColor = newValue?.cgColor
        }
        get {
            guard let color = layer.borderColor else {
                return nil
            }
            return UIColor(cgColor: color)
        }
    }
    @IBInspectable var borderWidth: CGFloat {
        set {
            layer.borderWidth = newValue
        }
        get {
            return layer.borderWidth
        }
    }
    @IBInspectable var cornerRadius: CGFloat {
        set {
            layer.cornerRadius = newValue
            clipsToBounds = newValue > 0
        }
        get {
            return layer.cornerRadius
        }
    }
}

Then this will be available in Interface Builder for every button, imageView, label, etc. in the Utilities Panel > Attributes Inspector :

Attributes Inspector

Note: the border will only appear at runtime.

Trichosis answered 12/2, 2016 at 21:38 Comment(13)
@Gaurav What error do you see ? On which component (UIButton, UILabel, etc.) are you using it ?Trichosis
I can't help you without more details :(Trichosis
can you explain problem in this code : @IBInspectable var borderColor: UIColor? { get { if let color = layer.borderColor { return UIColor(CGColor: color) } return nil } set(newValue) { layer.borderColor = newValue?.CGColor } }Triceps
You are not making it easy for me, this code is a simple getter/setter and works fine with xCode 7.2.1. (Swift 2.1 if I'm not mistaken) Maybe you use a different version of Swift ? What error do you experience ? I can't guess ...Trichosis
please check may last comment . i have post my code can you please explain my mistakeTriceps
I was getting Interface Builder crashes with this approach until I removed @IBDesignable from the beginning of the extension.Devy
That is amazing... Thanks! I'm using XCode 8.2.1Feuilleton
Very handy and neat! Thanks!Devotee
I would add that newValue!.CGColor should be newValue!.cgColor now.Divulsion
@AndrewWhite Yes, I updated my answer with the Swift 3 syntax. Thank you !Trichosis
I added the code and got the settings in the attribute inspector. but when i select a border colour and run the app there is no error but the border colour does not change. I have created a separate file to add the above swift 3 code.Sarcous
@AxelGuilmin is there anything I can do in adaptive layout for corner radius?Photogenic
@MihirOza no idea sorryTrichosis
W
58

You can make a category of UIView and add this in .h file of category

@property (nonatomic) IBInspectable UIColor *borderColor;
@property (nonatomic) IBInspectable CGFloat borderWidth;
@property (nonatomic) IBInspectable CGFloat cornerRadius;

Now add this in .m file

@dynamic borderColor,borderWidth,cornerRadius;

and this as well in . m file

-(void)setBorderColor:(UIColor *)borderColor{
    [self.layer setBorderColor:borderColor.CGColor];
}

-(void)setBorderWidth:(CGFloat)borderWidth{
    [self.layer setBorderWidth:borderWidth];
}

-(void)setCornerRadius:(CGFloat)cornerRadius{
    [self.layer setCornerRadius:cornerRadius];
}

now you will see this in your storyboard for all UIView subclasses (UILabel, UITextField, UIImageView etc)

enter image description here

Thats it.. No Need to import category anywhere, just add the category's files in the project and see these properties in the storyboard.

Wickiup answered 20/5, 2015 at 11:13 Comment(3)
Complement it with IB_DESIGNABLE to make IB redraw your custom view using the drawRect: method developer.apple.com/library/ios/recipes/…Residuary
Thats great, If you write IB_DESIGNABLE in the .h file before the interface line, you dont need to add @dynamic line in .mSwound
@user1618612 it has nothing to do with the resolution, it is just setting normal layer properties.Wickiup
P
13

For Swift 3 and 4, if you're willing to use IBInspectables, there's this:

@IBDesignable extension UIView {
    @IBInspectable var borderColor:UIColor? {
        set {
            layer.borderColor = newValue!.cgColor
        }
        get {
            if let color = layer.borderColor {
                return UIColor(cgColor: color)
            }
            else {
                return nil
            }
        }
    }
    @IBInspectable var borderWidth:CGFloat {
        set {
            layer.borderWidth = newValue
        }
        get {
            return layer.borderWidth
        }
    }
    @IBInspectable var cornerRadius:CGFloat {
        set {
            layer.cornerRadius = newValue
            clipsToBounds = newValue > 0
        }
        get {
            return layer.cornerRadius
        }
    }
}
Pursuance answered 15/7, 2017 at 13:2 Comment(2)
This is a best solution for meForeground
Great Solution , Thank uMcdowell
A
7

while this might set the properties, it doesnt actually reflect in IB. So if you're essentially writing code in IB, you might as well then do it in your source code

Athenian answered 28/5, 2013 at 8:6 Comment(3)
Welcome to MVC! You view properties should never be in code!Oversoul
^ This is not what MVC is.Stridor
Considering that 95% of the time this code goes in the controller, it is also MVC, of course should you properly subclass or extend your view then its just configuration over coding :-)Clingfish
U
0

Its absolutely possible only when you set layer.masksToBounds = true and do you rest stuff.

Unjust answered 12/10, 2018 at 6:0 Comment(0)
K
-1

Storyboard doesn't work for me all the time even after trying all the solution here

So it is always perfect answer is using the code, Just create IBOutlet instance of the UIView and add the properties

Short answer :

layer.cornerRadius = 10
layer.borderWidth = 1
layer.borderColor = UIColor.blue.cgColor

Long answer :

Rounded Corners of UIView/UIButton etc

customUIView.layer.cornerRadius = 10

Border Thickness

pcustomUIView.layer.borderWidth = 2

Border Color

customUIView.layer.borderColor = UIColor.blue.cgColor
Knur answered 12/6, 2019 at 9:28 Comment(1)
The question is very specific and ask how to do it from the Interface Builder. Your answer is irrelevant.Raconteur
G
-5

Please add these 2 simple line of code:

self.YourViewName.layer.cornerRadius = 15
self.YourViewName.layer.masksToBounds = true

It will work fine.

Guimar answered 6/2, 2018 at 6:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.