How to create border in UIButton? - ios

I use custom button in my app named "addButton" and I want to border it with white color how can i get the white color border around my custom button?

You can set the border properties on the CALayer by accessing the layer property of the button.
First, add Quartz
#import <QuartzCore/QuartzCore.h>
Set properties:
myButton.layer.borderWidth = 2.0f;
myButton.layer.borderColor = [UIColor greenColor].CGColor;
See:
https://developer.apple.com/documentation/quartzcore/calayer#//apple_ref/occ/cl/CALayer
The CALayer in the link above allows you to set other properties like corner radius, maskToBounds etc...
Also, a good article on button fun:
https://web.archive.org/web/20161221132308/http://www.apptite.be/tutorial_custom_uibuttons.php

Its very simple, just add the quartzCore header in your file(for that you have to add the quartz framework to your project)
and then do this
[[button layer] setCornerRadius:8.0f];
[[button layer] setMasksToBounds:YES];
[[button layer] setBorderWidth:1.0f];
you can change the float values as required.
enjoy.
Here's some typical modern code ...
self.buttonTag.layer.borderWidth = 1.0f;
self.buttonCancel.layer.borderWidth = 1.0f;
self.buttonTag.layer.borderColor = [UIColor blueColor].CGColor;
self.buttonCancel.layer.borderColor = [UIColor blueColor].CGColor;
self.buttonTag.layer.cornerRadius = 4.0f;
self.buttonCancel.layer.cornerRadius = 4.0f;
that's a similar look to segmented controls.
UPDATE for Swift:
No need to add "QuartzCore"
Just do:
button.layer.cornerRadius = 8.0
button.layer.borderWidth = 1.0
button.layer.borderColor = UIColor.black.cgColor

And in swift, you don't need to import "QuartzCore/QuartzCore.h"
Just use:
button.layer.borderWidth = 0.8
button.layer.borderColor = (UIColor( red: 0.5, green: 0.5, blue:0, alpha: 1.0 )).cgColor
or
button.layer.borderWidth = 0.8
button.layer.borderColor = UIColor.grayColor().cgColor

The problem setting the layer's borderWidth and borderColor is that the when you touch the button the border doesn't animate the highlight effect.
Of course, you can observe the button's events and change the border color accordingly but that feels unnecessary.
Another option is to create a stretchable UIImage and setting it as the button's background image. You can create an Image set in your Images.xcassets like this:
Then, you set it as the button's background image:
If your image is a template image you can set tint color of the button and the border will change:
Now the border will highlight with the rest of the button when touched.

Here's an updated version (Swift 3.0.1) from Ben Packard's answer.
import UIKit
#IBDesignable class BorderedButton: UIButton {
#IBInspectable var borderColor: UIColor? {
didSet {
if let bColor = borderColor {
self.layer.borderColor = bColor.cgColor
}
}
}
#IBInspectable var borderWidth: CGFloat = 0 {
didSet {
self.layer.borderWidth = borderWidth
}
}
override var isHighlighted: Bool {
didSet {
guard let currentBorderColor = borderColor else {
return
}
let fadedColor = currentBorderColor.withAlphaComponent(0.2).cgColor
if isHighlighted {
layer.borderColor = fadedColor
} else {
self.layer.borderColor = currentBorderColor.cgColor
let animation = CABasicAnimation(keyPath: "borderColor")
animation.fromValue = fadedColor
animation.toValue = currentBorderColor.cgColor
animation.duration = 0.4
self.layer.add(animation, forKey: "")
}
}
}
}
The resulting button can be used inside your StoryBoard thanks to the #IBDesignable and #IBInspectable tags.
Also the two properties defined, allow you to set the border width and color directly on interface builder and preview the result.
Other properties could be added in a similar fashion, for border radius and highlight fading time.

To change button Radius, Color and Width I set like this:
self.myBtn.layer.cornerRadius = 10;
self.myBtn.layer.borderWidth = 1;
self.myBtn.layer.borderColor =[UIColor colorWithRed:189.0/255.0f green:189.0/255.0f blue:189.0/255.0f alpha:1.0].CGColor;

This can be achieved in various methods in Swift 3.0 Worked on Latest version August - 2017
Option 1:
Directly assign the borderWidth property values for UI Button:
btnUserButtonName.layer.borderWidth = 1.0
Set Title with Default Color values for UI Button:
btnUserButtonName.setTitleColor(UIColor.darkGray, for: .normal)
Set Border with Default Color for the border property values for UI Button:
btnUserButtonName.layer.borderColor = UIColor.red
Set user defined Color for the border property values for UI Button:
let myGrayColor = UIColor(red: 0.889415, green: 0.889436, blue:0.889424, alpha: 1.0 )
btnUserButtonName.layer.borderColor = myGrayColor.cgColor
Option 2: [Recommended]
Use the Extension method, so the Button through out the application will be looking consistent and no need to repeat multiple lines of code every where.
//Create an extension class in any of the swift file
extension UIButton {
func setBordersSettings() {
let c1GreenColor = (UIColor(red: -0.108958, green: 0.714926, blue: 0.758113, alpha: 1.0))
self.layer.borderWidth = 1.0
self.layer.cornerRadius = 5.0
self.layer.borderColor = c1GreenColor.cgColor
self.setTitleColor(c1GreenColor, for: .normal)
self.layer.masksToBounds = true
}
}
Usage in code:
//use the method and call whever the border has to be applied
btnUserButtonName.setBordersSettings()
Output of Extension method Button:

You don't need to import QuartzCore.h now. Taking iOS 8 sdk and Xcode 6.1 in referrence.
Directly use:
[[myButton layer] setBorderWidth:2.0f];
[[myButton layer] setBorderColor:[UIColor greenColor].CGColor];

Here's a UIButton subclass that supports the highlighted state animation without using images. It also updates the border color when the view's tint mode changes.
class BorderedButton: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
layer.borderColor = tintColor.cgColor
layer.borderWidth = 1
layer.cornerRadius = 5
contentEdgeInsets = UIEdgeInsets(top: 5, left: 10, bottom: 5, right: 10)
}
required init?(coder aDecoder: NSCoder) {
fatalError("NSCoding not supported")
}
override func tintColorDidChange() {
super.tintColorDidChange()
layer.borderColor = tintColor.cgColor
}
override var isHighlighted: Bool {
didSet {
let fadedColor = tintColor.withAlphaComponent(0.2).cgColor
if isHighlighted {
layer.borderColor = fadedColor
} else {
layer.borderColor = tintColor.cgColor
let animation = CABasicAnimation(keyPath: "borderColor")
animation.fromValue = fadedColor
animation.toValue = tintColor.cgColor
animation.duration = 0.4
layer.add(animation, forKey: nil)
}
}
}
}
Usage:
let button = BorderedButton(style: .System) //style .System is important
Appearance:

Swift 5
button.layer.borderWidth = 2
To change the colour of the border use
button.layer.borderColor = CGColor(srgbRed: 255/255, green: 126/255, blue: 121/255, alpha: 1)

****In Swift 3****
To create border
btnName.layer.borderWidth = 1
btnName.layer.borderColor = UIColor.black.cgColor
To make corner rounded
btnName.layer.cornerRadius = 5

Update with Swift 3
button.layer.borderWidth = 0.8
button.layer.borderColor = UIColor.blue.cgColor

Related

Shadow inside table view cell not working

The shadow in my cell is not working at all.
This is one of the view that I want to add shadow but it's not working. I added this code inside my custom cell class.
super.layoutSubviews()
UIview1.layer.cornerRadius = 7
UIview1.layer.borderWidth = 1.0
UIview1.layer.borderColor = HexColor.hexStringToUIColor(hex: "FA2537").cgColor
UIview1.layer.masksToBounds = true
UIview1.layer.shadowColor = HexColor.hexStringToUIColor(hex: "01A4B7").cgColor
UIview1.layer.shadowOpacity = 0.5
UIview1.layer.shadowOffset = CGSize.zero
UIview1.layer.shadowRadius = 5
}
For showing shadow on a view, you need to set its layer's masksToBounds property false.
or you can try this.
You can make a method like this and can use:
extension UIView {
func setShadowWith(color: UIColor = UIColor.black, shadowOpacity: Float = 0.2, radius: Float = 1.0, shadowOffSet: CGSize = CGSize(width: 0, height: 1)) {
self.layer.shadowColor = color.cgColor
self.layer.shadowOpacity = shadowOpacity
self.layer.shadowOffset = shadowOffSet
self.layer.shadowRadius = CGFloat(radius)
}
}
and can use function like:
yourContainerView.setShadowWith()
Here parameters used in functions are taking default values. you can change accordingly.
Set maskToBounds to false instead of true:
UIview1.layer.masksToBounds = false

Why masksToBounds = YES prevents CALayer shadow?

With the following snippet, I'm adding a drop shadow effect to one my UIView. Which works pretty well. But as soon as I set the view's masksToBounds property to YES. The drop shadow effect isn't rendered any more.
self.myView.layer.shadowColor = [[UIColor blackColor] CGColor];
self.myView.layer.shadowOpacity = 1.0;
self.myView.layer.shadowRadius = 10.0;
self.myView.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
self.myView.layer.cornerRadius = 5.0;
self.myView.layer.masksToBounds = YES; // <-- This is causing the Drop shadow to not be rendered
UIBezierPath *path = [UIBezierPath bezierPathWithCurvedShadowForRect:self.myView.bounds];
self.myView.layer.shadowPath = path.CGPath;
self.myView.layer.shouldRasterize = YES;
Do you have any ideas on this?
Because shadow is an effect done outside the View, and that masksToBounds set to YES will tell the UIView not to draw anything that is outside itself.
If you want a roundedCorner view with shadow I suggest you do it with 2 views:
UIView *view1 = [[UIView alloc] init];
UIView *view2 = [[UIView alloc] init];
view1.layer.cornerRadius = 5.0;
view1.layer.masksToBounds = YES;
view2.layer.cornerRadius = 5.0;
view2.layer.shadowColor = [[UIColor blackColor] CGColor];
view2.layer.shadowOpacity = 1.0;
view2.layer.shadowRadius = 10.0;
view2.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
[view2 addSubview:view1];
[view1 release];
It's iOS 6 now, things might have changed. TheSquad's answer don't work for me until I managed to add one more line view2.layer.masksToBounds = NO;, otherwise shadow doesn't show. Although documentation says masksToBounds is NO by default, my code shows the opposite.
Here is how I make a rounded corner button with shadow, which is among the most commonly used code snippet in my app.
button.layer.masksToBounds = YES;
button.layer.cornerRadius = 10.0f;
view.layer.masksToBounds = NO; // critical to add this line
view.layer.cornerRadius = 10.0f;
view.layer.shadowOpacity = 1.0f;
// set shadow path to prevent horrible performance
view.layer.shadowPath =
[UIBezierPath bezierPathWithRoundedRect:_button.bounds cornerRadius:10.0f].CGPath;
[view addSubview:button];
EDIT
If views need to be animated or scrolled, masksToBounds = YES tax performance significantly, which means animation will probably get stuttered. To get rounded corner and shadow AND smooth animation or scrolling, use following code instead:
button.backgroundColor = [UIColor clearColor];
button.layer.backgroundColor = [UIColor redColor].CGColor;
button.layer.masksToBounds = NO;
button.layer.cornerRadius = 10.0f;
view.layer.shadowOpacity = 0.5f;
view.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:_button.bounds cornerRadius:10.0f].CGPath;
view.layer.shadowOffset = CGSizeMake(0.0f, 4.0f);
view.layer.shadowRadius = 2.0f;
view.layer.masksToBounds = NO;
view.layer.cornerRadius = 10.0f;
[view addSubview:button];
Swift 3.0 version with StoryBoard
The same idea with #TheSquad. Create a new view under the actual view and add shadow to the lower view.
1. Create a view under the actual view
Drag a UIView to StoryBoard with same constraint as your target view. Check clip to bound for the target view. Also make sure the new view is listed before the target view so that the target view will cover the new view.
2. Now link the new view to your code add add shadow on it
This is just a sample. You can do whatever way you want here
shadowView.layer.masksToBounds = false
shadowView.layer.shadowColor = UIColor.red.cgColor
shadowView.layer.shadowOpacity = 0.5
shadowView.layer.shadowOffset = CGSize(width: -1, height: 1)
shadowView.layer.shadowRadius = 3
shadowView.layer.shadowPath = UIBezierPath(rect: coverImage.bounds).cgPath
shadowView.layer.shouldRasterize = true
This is the Swift 3 and IBDesignable version of the answer posted by #TheSquad.
I used the same concept while making changes in the storyboard file. First I moved my targetView (the one which requires corner radius and shadow) inside a new containerView. Then I added the following lines of code (Reference: https://stackoverflow.com/a/35372901/419192) to add some IBDesignable attributes for UIView Class:
#IBDesignable extension UIView {
/* The color of the shadow. Defaults to opaque black. Colors created
* from patterns are currently NOT supported. Animatable. */
#IBInspectable var shadowColor: UIColor? {
set {
layer.shadowColor = newValue!.cgColor
}
get {
if let color = layer.shadowColor {
return UIColor(cgColor: color)
}
else {
return nil
}
}
}
/* The opacity of the shadow. Defaults to 0. Specifying a value outside the
* [0,1] range will give undefined results. Animatable. */
#IBInspectable var shadowOpacity: Float {
set {
layer.shadowOpacity = newValue
}
get {
return layer.shadowOpacity
}
}
/* The shadow offset. Defaults to (0, -3). Animatable. */
#IBInspectable var shadowOffset: CGPoint {
set {
layer.shadowOffset = CGSize(width: newValue.x, height: newValue.y)
}
get {
return CGPoint(x: layer.shadowOffset.width, y:layer.shadowOffset.height)
}
}
/* The blur radius used to create the shadow. Defaults to 3. Animatable. */
#IBInspectable var shadowRadius: CGFloat {
set {
layer.shadowRadius = newValue
}
get {
return layer.shadowRadius
}
}
/* The corner radius of the view. */
#IBInspectable var cornerRadius: CGFloat {
set {
layer.cornerRadius = newValue
}
get {
return layer.cornerRadius
}
}
After adding this code, I went back to the storyboard and on selecting my containerView I could now find a new set of attributes in the attributes inspector:
Other than adding values for these attributes as per my choice, I also added a corner radius to my targetView and set the masksToBounds property as true.
I hope this helps :)
I also had drastic performance issues with shadows and rounded corners. Instead of using the shadowPath part, I used the following lines which perfectly solved the performance hit:
self.layer.shouldRasterize = YES;
self.layer.rasterizationScale = UIScreen.mainScreen.scale;
Here is one of the solutions:
#IBOutlet private weak var blockView: UIView! {
didSet {
blockView.backgroundColor = UIColor.white
blockView.layer.shadowColor = UIColor.black.cgColor
blockView.layer.shadowOpacity = 0.5
blockView.layer.shadowOffset = CGSize.zero
blockView.layer.cornerRadius = 10
}
}
#IBOutlet private weak var imageView: UIImageView! {
didSet {
imageView.layer.cornerRadius = 10
imageView.layer.masksToBounds = true
imageView.layer.shouldRasterize = true
}
}

Cocoa Touch: How To Change UIView's Border Color And Thickness?

I saw in the inspector that I can change the background color, but I'd like to also change the border color and thickness, is this possible?
You need to use view's layer to set border property. e.g:
#import <QuartzCore/QuartzCore.h>
...
view.layer.borderColor = [UIColor redColor].CGColor;
view.layer.borderWidth = 3.0f;
You also need to link with QuartzCore.framework to access this functionality.
Xcode 6 update
Since Xcode's newest version there is a better solution to this:
With #IBInspectable you can set Attributes directly from within the Attributes Inspector.
This sets the User Defined Runtime Attributes for you:
There are two approaches to set this up:
Option 1 (with live updating in Storyboard)
Create MyCustomView.
This inherits from UIView.
Set #IBDesignable (this makes the View update live).*
Set your Runtime Attributes (border, etc.) with #IBInspectable
Change your Views Class to MyCustomView
Edit in Attributes Panel and see changes in Storyboard :)
`
#IBDesignable
class MyCustomView: UIView {
#IBInspectable var cornerRadius: CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadius
layer.masksToBounds = cornerRadius > 0
}
}
#IBInspectable var borderWidth: CGFloat = 0 {
didSet {
layer.borderWidth = borderWidth
}
}
#IBInspectable var borderColor: UIColor? {
didSet {
layer.borderColor = borderColor?.CGColor
}
}
}
* #IBDesignable only works when set at the start of class MyCustomView
Option 2 (not working since Swift 1.2, see comments)
Extend your UIView Class:
extension UIView {
#IBInspectable var cornerRadius: CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadius
layer.masksToBounds = cornerRadius > 0
}
}
#IBInspectable var borderWidth: CGFloat = 0 {
didSet {
layer.borderWidth = borderWidth
}
}
#IBInspectable var borderColor: UIColor? {
didSet {
layer.borderColor = borderColor?.CGColor
}
}
}
This way, your default View always has those extra editable fields in Attributes Inspector. Another advantage is that you don't have to change the class to MycustomView every time.
However, one drawback to this is that you will only see your changes when you run your app.
You can also create border with the color of your wish..
view.layer.borderColor = [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1.0].CGColor;
*r,g,b are the values between 0 to 255.
Add following #IBInspectables in UIView extension
extension UIView {
#IBInspectable var borderWidth: CGFloat {
get {
return layer.borderWidth
}
set(newValue) {
layer.borderWidth = newValue
}
}
#IBInspectable var borderColor: UIColor? {
get {
if let color = layer.borderColor {
return UIColor(CGColor: color)
}
return nil
}
set(newValue) {
layer.borderColor = newValue?.CGColor
}
}
}
And then you should be able to set borderColor and borderWidth attributes directly from Attribute inspector. See attached image
Attributes Inspector
view.layer.borderWidth = 1.0
view.layer.borderColor = UIColor.lightGray.cgColor
When I use Vladimir's CALayer solution, and on top of the view I have an animation, like a modal UINavigationController dismissing, I see a lot of glitches happening and having drawing performance issues.
So, another way to achieve this, but without the glitches and performance loss, is to make a custom UIView and implement the drawRect message like so:
- (void)drawRect:(CGRect)rect
{
CGContextRef contextRef = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(contextRef, 1);
CGContextSetRGBStrokeColor(contextRef, 255.0, 255.0, 255.0, 1.0);
CGContextStrokeRect(contextRef, rect);
}
Try this code:
view.layer.borderColor = [UIColor redColor].CGColor;
view.layer.borderWidth= 2.0;
[view setClipsToBounds:YES];
I wouldn't suggest overriding the drawRect due to causing a performance hit.
Instead, I would modify the properties of the class like below (in your custom uiview):
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.layer.borderWidth = 2.f;
self.layer.borderColor = [UIColor redColor].CGColor;
}
return self;
I didn't see any glitches when taking above approach - not sure why putting in the initWithFrame stops these ;-)
I wanted to add this to #marczking's answer (Option 1) as a comment, but my lowly status on StackOverflow is preventing that.
I did a port of #marczking's answer to Objective C. Works like charm, thanks #marczking!
UIView+Border.h:
#import <UIKit/UIKit.h>
IB_DESIGNABLE
#interface UIView (Border)
-(void)setBorderColor:(UIColor *)color;
-(void)setBorderWidth:(CGFloat)width;
-(void)setCornerRadius:(CGFloat)radius;
#end
UIView+Border.m:
#import "UIView+Border.h"
#implementation UIView (Border)
// Note: cannot use synthesize in a Category
-(void)setBorderColor:(UIColor *)color
{
self.layer.borderColor = color.CGColor;
}
-(void)setBorderWidth:(CGFloat)width
{
self.layer.borderWidth = width;
}
-(void)setCornerRadius:(CGFloat)radius
{
self.layer.cornerRadius = radius;
self.layer.masksToBounds = radius > 0;
}
#end
#IBInspectable is working for me on iOS 9 , Swift 2.0
extension UIView {
#IBInspectable var borderWidth: CGFloat {
get {
return layer.borderWidth
}
set(newValue) {
layer.borderWidth = newValue
}
}
#IBInspectable var cornerRadius: CGFloat {
get {
return layer.cornerRadius
}
set(newValue) {
layer.cornerRadius = newValue
}
}
#IBInspectable var borderColor: UIColor? {
get {
if let color = layer.borderColor {
return UIColor(CGColor: color)
}
return nil
}
set(newValue) {
layer.borderColor = newValue?.CGColor
}
}
If you didn't want to edit the layer of a UIView, you could always embed the view within another view. The parent view would have its background color set to the border color. It would also be slightly larger, depending upon how wide you want the border to be.
Of course, this only works if your view isn't transparent and you only want a single border color. The OP wanted the border in the view itself, but this may be a viable alternative.
item's border color in swift 4.2:
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell_lastOrderId") as! Cell_lastOrder
cell.layer.borderWidth = 1
cell.layer.borderColor = UIColor.white.cgColor
cell.layer.cornerRadius = 10
If you want to add different border on different sides, may be add a subview with the specific style is a way easy to come up with.
[self.view.layer setBorderColor: [UIColor colorWithRed:0.265 green:0.447 blue:0.767 alpha:1.0f].CGColor];

Bordered UITextView

I want to have a thin gray border around a UITextView. I have gone through the Apple documentation but couldn't find any property there. Please help.
#import <QuartzCore/QuartzCore.h>
....
// typically inside of the -(void) viewDidLoad method
self.yourUITextView.layer.borderWidth = 5.0f;
self.yourUITextView.layer.borderColor = [[UIColor grayColor] CGColor];
Add the following for rounded corners:
self.yourUITextview.layer.cornerRadius = 8;
Here's the code I used, to add a border around my TextView control named "tbComments" :
self.tbComments.layer.borderColor = [[UIColor grayColor] CGColor];
self.tbComments.layer.borderWidth = 1.0;
self.tbComments.layer.cornerRadius = 8;
And here's what it looks like:
Easy peasy.
I add UIImageView as a subview of the UITextView. This matches the native border on a UITextField, including the gradient from top to bottom:
textView.backgroundColor = [UIColor clearColor];
UIImageView *borderView = [[UIImageView alloc] initWithFrame: CGRectMake(0, 0, textView.frame.size.width, textView.frame.size.height)];
borderView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
UIImage *textFieldImage = [[UIImage imageNamed:#"TextField.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(15, 8, 15, 8)];
borderView.image = textFieldImage;
[textField addSubview: borderView];
[textField sendSubviewToBack: borderView];
These are the png images I use, and a jpg representation:
#1x
#2x
Works great, but the color should be a CGColor, not UIColor:
view.layer.borderWidth = 5.0f;
view.layer.borderColor = [[UIColor grayColor] CGColor];
I believe the above answers are for the previous versions of Swift. I Googled a bit and the below code works for Swift 4. Just sharing it for whoever it may benefit.
self.textViewName.layer.borderColor = UIColor.lightGray.cgColor
self.textViewName.layer.borderWidth = 1.0
self.textViewName.layer.cornerRadius = 8
Happy Coding!
for Swift Programming, use this
tv_comment.layer.borderWidth = 2
tv_comment.layer.borderColor = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 1).CGColor
this is as close as I could from an original UITextField
func updateBodyTextViewUI() {
let borderColor = UIColor.init(red: 212/255, green: 212/255, blue: 212/255, alpha: 0.5)
self.bodyTextView.layer.borderColor = borderColor.CGColor
self.bodyTextView.layer.borderWidth = 0.8
self.bodyTextView.layer.cornerRadius = 5
}
you can add border to UITextView from the Storyboard - Identity Inspector - User Defined Runtime Attribute
As of iOS 8 and Xcode 6, I now find the best solution is to subclass UITextView and mark the subclass as an IB_DESIGNABLE, which will allow you to view the border in storyboard.
Header:
#import <UIKit/UIKit.h>
IB_DESIGNABLE
#interface BorderTextView : UITextView
#end
Implementation:
#import "BorderTextView.h"
#implementation BorderTextView
- (void)drawRect:(CGRect)rect
{
self.layer.borderWidth = 1.0;
self.layer.borderColor = [UIColor blackColor].CGColor;
self.layer.cornerRadius = 5.0f;
}
#end
Then just drag out your UITextView in storyboard and set its class to BorderTextView
The thing that made it work (in addition to following the answers here) is adding the borderStyle attribute:
#import <QuartzCore/QuartzCore.h>
..
phoneTextField.layer.borderWidth = 1.0f;
phoneTextField.layer.borderColor = [[UIColor blueColor] CGColor];
phoneTextField.borderStyle = UITextBorderStyleNone;
Just a small addition. If you make the border a bit wider, it will interfere with the left and right side of text. To avoid that, I added the following line:
self.someTextView.textContainerInset = UIEdgeInsetsMake(8.0, 8.0, 8.0, 8.0);
In Swift 3, you may use the following two lines:
myText.layer.borderColor = UIColor.lightGray.cgColor
myText.layer.borderWidth = 1.0
An elegant solution would be to insert a real UITextField on the bottom and prevent it to scroll with the content. This way you have even the correct dark mode borders. 🙂
class BorderedTextView: UITextView {
let textField = UITextField()
required init?(coder: NSCoder) {
super.init(coder: coder)
insertTextField()
}
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
insertTextField()
}
convenience init() {
self.init(frame: .zero, textContainer: nil)
}
private func insertTextField() {
delegate = self
textField.borderStyle = .roundedRect
insertSubview(textField, at: 0)
}
override func layoutSubviews() {
super.layoutSubviews()
textField.frame = bounds
}
}
extension BorderedTextView: UITextViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
textField.frame = bounds
}
}
I solved this problem in storyboard by putting a fully disabled UIButton behind the UITextView and making the background color of the UITextView clearColor. This works without requiring extra code or packages.

How do I create a round cornered UILabel on the iPhone?

Is there a built in way to create round-cornered UILabels? If the answer is no, how would one go about creating such an object?
iOS 3.0 and later
iPhone OS 3.0 and later supports the cornerRadius property on the CALayer class. Every view has a CALayer instance that you can manipulate. This means you can get rounded corners in one line:
view.layer.cornerRadius = 8;
You will need to #import <QuartzCore/QuartzCore.h> and link to the QuartzCore framework to get access to CALayer's headers and properties.
Before iOS 3.0
One way to do it, which I used recently, is to create a UIView subclass which simply draws a rounded rectangle, and then make the UILabel or, in my case, UITextView, a subview inside of it. Specifically:
Create a UIView subclass and name it something like RoundRectView.
In RoundRectView's drawRect: method, draw a path around the bounds of the view using Core Graphics calls like CGContextAddLineToPoint() for the edges and and CGContextAddArcToPoint() for the rounded corners.
Create a UILabel instance and make it a subview of the RoundRectView.
Set the frame of the label to be a few pixels inset of the RoundRectView's bounds. (For example, label.frame = CGRectInset(roundRectView.bounds, 8, 8);)
You can place the RoundRectView on a view using Interface Builder if you create a generic UIView and then change its class using the inspector. You won't see the rectangle until you compile and run your app, but at least you'll be able to place the subview and connect it to outlets or actions if needed.
For devices with iOS 7.1 or later, you need to add:
yourUILabel.layer.masksToBounds = YES;
yourUILabel.layer.cornerRadius = 8.0;
For Swift IOS8 onwards based on OScarsWyck answer:
yourUILabel.layer.masksToBounds = true
yourUILabel.layer.cornerRadius = 8.0
you have an UILabel called: myLabel.
in your "m" or "h" file import: #import <QuartzCore/QuartzCore.h>
in your viewDidLoad write this line: self.myLabel.layer.cornerRadius = 8;
depends on how you want you can change cornerRadius value from 8 to other number :)
Good luck
You can make rounded border with width of border of any control in this way:-
CALayer * l1 = [lblName layer];
[l1 setMasksToBounds:YES];
[l1 setCornerRadius:5.0];
// You can even add a border
[l1 setBorderWidth:5.0];
[l1 setBorderColor:[[UIColor darkGrayColor] CGColor]];
Just replace lblName with your UILabel.
Note:- Don't forget to import <QuartzCore/QuartzCore.h>
Swift 3
If you want rounded label with background color, in addition to most of the other answers, you need to set layer's background color as well. It does not work when setting view background color.
label.layer.cornerRadius = 8
label.layer.masksToBounds = true
label.layer.backgroundColor = UIColor.lightGray.cgColor
If you are using auto layout, want some padding around the label and do not want to set the size of the label manually, you can create UILabel subclass and override intrinsincContentSize property:
class LabelWithPadding: UILabel {
override var intrinsicContentSize: CGSize {
let defaultSize = super.intrinsicContentSize
return CGSize(width: defaultSize.width + 12, height: defaultSize.height + 8)
}
}
To combine the two you will also need to set label.textAlignment = center, otherwise the text would be left aligned.
I made a swift UILabel subclass to achieve this effect. In addition I automatically set the text color to either black or white for maximal contrast.
Result
Used SO-Posts:
How to draw border around a UILabel?
Add a border outside of a UIView
Check if UIColor is dark or bright?
Playground
Just paste this into an iOS Playground:
//: Playground - noun: a place where people can play
import UIKit
class PillLabel : UILabel{
#IBInspectable var color = UIColor.lightGrayColor()
#IBInspectable var cornerRadius: CGFloat = 8
#IBInspectable var labelText: String = "None"
#IBInspectable var fontSize: CGFloat = 10.5
// This has to be balanced with the number of spaces prefixed to the text
let borderWidth: CGFloat = 3
init(text: String, color: UIColor = UIColor.lightGrayColor()) {
super.init(frame: CGRectMake(0, 0, 1, 1))
labelText = text
self.color = color
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
func setup(){
// This has to be balanced with the borderWidth property
text = " \(labelText)".uppercaseString
// Credits to https://stackoverflow.com/a/33015915/784318
layer.borderWidth = borderWidth
layer.cornerRadius = cornerRadius
backgroundColor = color
layer.borderColor = color.CGColor
layer.masksToBounds = true
font = UIFont.boldSystemFontOfSize(fontSize)
textColor = color.contrastColor
sizeToFit()
// Credits to https://stackoverflow.com/a/15184257/784318
frame = CGRectInset(self.frame, -borderWidth, -borderWidth)
}
}
extension UIColor {
// Credits to https://stackoverflow.com/a/29044899/784318
func isLight() -> Bool{
var green: CGFloat = 0.0, red: CGFloat = 0.0, blue: CGFloat = 0.0, alpha: CGFloat = 0.0
self.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
let brightness = ((red * 299) + (green * 587) + (blue * 114) ) / 1000
return brightness < 0.5 ? false : true
}
var contrastColor: UIColor{
return self.isLight() ? UIColor.blackColor() : UIColor.whiteColor()
}
}
var label = PillLabel(text: "yellow", color: .yellowColor())
label = PillLabel(text: "green", color: .greenColor())
label = PillLabel(text: "white", color: .whiteColor())
label = PillLabel(text: "black", color: .blackColor())
If you want rounded corner of UI objects like (UILabel, UIView, UIButton, UIImageView) by storyboard then set clip to bounds true and set User Defined Runtime Attributes Key path as
layer.cornerRadius, type = Number and value = 9 (as your requirement)
xCode 7.3.1 iOS 9.3.2
_siteLabel.layer.masksToBounds = true;
_siteLabel.layer.cornerRadius = 8;
Another method is to place a png behind the UILabel. I have views with several labels that overlay a single background png that has all the artwork for the individual labels.
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 30)];
label.text = #"Your String.";
label.layer.cornerRadius = 8.0;
[self.view addSubview:label];
Works fine in Xcode 8.1.2 with Swift 3
.cornerRadius is the key property to set rounded edges. If you are using the same style for all labels in your application, I would recommend for an extension method.
Code:
// extension Class
extension UILabel {
// extension user defined Method
func setRoundEdge() {
let myGreenColor = (UIColor(red: -0.108958, green: 0.714926, blue: 0.758113, alpha: 1.0))
//Width of border
self.layer.borderWidth = 1.0
//How much the edge to be rounded
self.layer.cornerRadius = 5.0
// following properties are optional
//color for border
self.layer.borderColor = myGreenColor.cgColor
//color for text
self.textColor = UIColor.red
// Mask the bound
self.layer.masksToBounds = true
//clip the pixel contents
self.clipsToBounds = true
}
}
Output:
Why Extension method?
Create a Swift file and add the following code, which has the Extention method to the "UILabel" class, where this method is user defined but will work for all the label in your application and will help to maintain consistency and clean code, if you change any style in future require only in the extension method.
In Monotouch / Xamarin.iOS I solved the same problem like this:
UILabel exampleLabel = new UILabel(new CGRect(0, 0, 100, 50))
{
Text = "Hello Monotouch red label"
};
exampleLabel.Layer.MasksToBounds = true;
exampleLabel.Layer.CornerRadius = 8;
exampleLabel.Layer.BorderColor = UIColor.Red.CGColor;
exampleLabel.Layer.BorderWidth = 2;
Works perfect in Swift 2.0
#IBOutlet var theImage: UIImageView! //you can replace this with any UIObject eg: label etc
override func viewDidLoad() {
super.viewDidLoad()
//Make sure the width and height are same
self.theImage.layer.cornerRadius = self.theImage.frame.size.width / 2
self.theImage.layer.borderWidth = 2.0
self.theImage.layer.borderColor = UIColor.whiteColor().CGColor
self.theImage.clipsToBounds = true
}
Did you try using the UIButton from the Interface builder (that has rounded corners) and experimenting with the settings to make it look like a label. if all you want is to display static text within.
Depending on what exactly you are doing you could make an image and set it as the background programatically.

Resources