How to draw border around a UILabel? - ios

Is there a way for UILabel to draw a border around itself? This is useful for me to debug the text placement and to see the placement and how big the label actually is.

You can set label's border via its underlying CALayer property:
#import <QuartzCore/QuartzCore.h>
myLabel.layer.borderColor = [UIColor greenColor].CGColor
myLabel.layer.borderWidth = 3.0
Swift 5:
myLabel.layer.borderColor = UIColor.darkGray.cgColor
myLabel.layer.borderWidth = 3.0

Here are some things you can do with UILabel and its borders.
Here is the code for those labels:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var label1: UILabel!
#IBOutlet weak var label2: UILabel!
#IBOutlet weak var label3: UILabel!
#IBOutlet weak var label4: UILabel!
#IBOutlet weak var label5: UILabel!
#IBOutlet weak var label6: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// label 1
label1.layer.borderWidth = 1.0
// label 2
label2.layer.borderWidth = 5.0
label2.layer.borderColor = UIColor.blue.cgColor
// label 3
label3.layer.borderWidth = 2.0
label3.layer.cornerRadius = 8
// label 4
label4.backgroundColor = UIColor.cyan
// label 5
label5.backgroundColor = UIColor.red
label5.layer.cornerRadius = 8
label5.layer.masksToBounds = true
// label 6
label6.layer.borderWidth = 2.0
label6.layer.cornerRadius = 8
label6.backgroundColor = UIColor.yellow
label6.layer.masksToBounds = true
}
}
Note that in Swift there is no need to import QuartzCore.
See also
Border, rounded corners, and shadow on a CALayer
Explanation of masksToBounds
Using a border with a Bezier path for a layer
How to do transforms on a CALayer

Swift version:
myLabel.layer.borderWidth = 0.5
myLabel.layer.borderColor = UIColor.greenColor().CGColor
For Swift 3:
myLabel.layer.borderWidth = 0.5
myLabel.layer.borderColor = UIColor.green.cgColor

Swift 3/4 with #IBDesignable
While almost all the above solutions work fine but I would suggest an #IBDesignable custom class for this.
#IBDesignable
class CustomLabel: UILabel {
/*
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
}
*/
#IBInspectable var borderColor: UIColor = UIColor.white {
didSet {
layer.borderColor = borderColor.cgColor
}
}
#IBInspectable var borderWidth: CGFloat = 2.0 {
didSet {
layer.borderWidth = borderWidth
}
}
#IBInspectable var cornerRadius: CGFloat = 0.0 {
didSet {
layer.cornerRadius = cornerRadius
}
}
}

UILabel properties borderColor,borderWidth,cornerRadius in Swift 4
#IBOutlet weak var anyLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
anyLabel.layer.borderColor = UIColor.black.cgColor
anyLabel.layer.borderWidth = 2
anyLabel.layer.cornerRadius = 5
anyLabel.layer.masksToBounds = true
}

You can use this repo: GSBorderLabel
It's quite simple:
GSBorderLabel *myLabel = [[GSBorderLabel alloc] initWithTextColor:aColor
andBorderColor:anotherColor
andBorderWidth:2];

Solution for Swift 4:
yourLabel.layer.borderColor = UIColor.green.cgColor

it really depends on how many boarder use in your view , sometimes , just add a UIVIEW which the size is a bit bigger to create the border . the method is faster than produce a view

Using an NSAttributedString string for your labels attributedText is probably your best bet. Check out this example.

Related

How to animate the shadow border of an UIView at the same time its content grows

I am working on a project which has all views embedded in a view container like this:
Today, I have to make one of these containers grow vertically in a animatable way when a stack view is showing its arranged subviews. So, the first problem was that the shadow border of this container is not being animated and I realized that the shadow path should be animated in another way and not just in a UIView.animate block.
I have isolated the problem in a small project:
As you can see, I am trying to deploy/undeploy the container view depending on the inner stackview arranged subviews. The problem is the shadow path, which I am already trying to understand how it works.
Can you help me to understand how to manage a UIView shadow layer when you need to update the height of an UIView in an animation block?
Container Shadow view code:
import UIKit
#IBDesignable final class ShadowView: UIView {
#IBInspectable var cornerRadius: CGFloat = 0.0 {
didSet {
setNeedsLayout()
}
}
#IBInspectable var shadowColor: UIColor = UIColor.darkGray {
didSet {
setNeedsLayout()
}
}
#IBInspectable var shadowOffsetWidth: CGFloat = 0.0 {
didSet {
setNeedsLayout()
}
}
#IBInspectable var shadowOffsetHeight: CGFloat = 1.8 {
didSet {
setNeedsLayout()
}
}
#IBInspectable var shadowOpacity: Float = 0.30 {
didSet {
setNeedsLayout()
}
}
#IBInspectable var shadowRadius: CGFloat = 3.0 {
didSet {
setNeedsLayout()
}
}
#IBInspectable var isAnimatable: Bool = false
private var shadowLayer: CAShapeLayer = CAShapeLayer() {
didSet {
setNeedsLayout()
}
}
private var previousPat: CGPath = CGPath(rect: CGRect(x: 0, y: 0, width: 0, height: 0), transform: .none)
override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = cornerRadius
shadowLayer.path = UIBezierPath(roundedRect: bounds,
cornerRadius: cornerRadius).cgPath
shadowLayer.fillColor = backgroundColor?.cgColor
shadowLayer.shadowColor = shadowColor.cgColor
shadowLayer.shadowPath = shadowLayer.path
shadowLayer.shadowOffset = CGSize(width: shadowOffsetWidth,
height: shadowOffsetHeight)
shadowLayer.shadowOpacity = shadowOpacity
shadowLayer.shadowRadius = shadowRadius
if isAnimatable {
let animation = CABasicAnimation(keyPath: "shadowPath")
animation.fromValue = previousPat
animation.toValue = shadowLayer.path
animation.autoreverses = false
animation.duration = 0.8
shadowLayer.add(animation, forKey: "pathAnimation")
}
layer.insertSublayer(shadowLayer, at: 0)
previousPat = shadowLayer.path!
}
}
Main ViewController code:
final class ViewController: UIViewController {
#IBOutlet weak var stack: UIStackView!
#IBOutlet weak var redContainerLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func animateAction(_ sender: Any) {
UIView.animate(withDuration: 0.8) {
self.redContainerLabel.alpha = self.redContainerLabel.alpha == 0 ? 1 : 0
self.stack.arrangedSubviews.forEach {
$0.isHidden.toggle()
}
}
}
}
View structure:
I was looking for an answer to exactly this problem and encountered this post here, which I believe is what you're looking for:
Animating CALayer shadow simultaneously as UITableviewCell height animates
The solution is a bit verbose (I'm surprised the use-case is so rare as to not prompt apple to fix(?) it) and a few years old at this point, but the most recent I could find. Ultimately I decided to work around it by fading out my shadows before resizing, but you might find it useful!
A couple of other, older posts I've found appear to corroborated the level of effort required for this effect (again, Apple's got a weird list of things it decides are your problem), so that first post is probably your best bet.
https://petosoft.wordpress.com/2012/10/24/shadowpath-not-animating-with-standard-uiview-animations-on-ipad/
Smoothly rotate and change size of UIView with shadow
UIView: How to animate CALayer frame with shadow?
If you've managed to find a more straightforward solution, by all means let me know; in the mean-time I hope this helps.

Swift - Image not coming out round

My image is not coming out as a circle for some reason. What I did is defining the corner radius as half of the image width. Does this have to do something with the constraints I set for the image?
Image circle code:
profileImage.layer.cornerRadius = profileImage.layer.frame.width / 2
profileImage.clipsToBounds = true
profileImage.layer.borderWidth = 3.0
profileImage.layer.borderColor = UIColor.white.cgColor
What it looks like on storyboard:
What it looks like on iPhone:
swift 4:
#IBOutlet weak var photoImage: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
photoImage.layer.borderWidth = 1
photoImage.layer.masksToBounds = false
photoImage.layer.borderColor = UIColor.black.cgColor
photoImage.layer.cornerRadius = photoImage.frame.height/2
photoImage.clipsToBounds = true
}

UIView not shows round

For making a circular UIView I am using the cornerRadius property.
I have a UIView with dimension 79*158.
redView.layer.cornerRadius = redView.frame.size.height/2
redView.layer.masksToBounds = true
It shows elipse instead of circle:
Any workaround or does it only work with square type (eg. UIView(100*100))?
I am ok if it resizes dynamically.
use this...
func makeCircle (view: UIView) {
view.clipsToBounds = true
let height = view.frame.size.height
let width = view.frame.size.width
let newHeight = min(height, width) // use "max" if you want big circle
var rectFrame = view.frame
rectFrame.size.height = newHeight
rectFrame.size.width = newHeight
view.frame = rectFrame
view.layer.cornerRadius = newHeight/2
}
use like this:
#IBOutlet var rectView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
makeCircle(view: rectView)
}
You have a UIView with dimension 79*158.So that is wrong. You should have exactly same height and width for rounding exact a view to circle shape.
E.g.
redView.frame.size.height = 79.0
redView.frame.size.width = 79.0
or
redView.frame.size.height = 158.0
redView.frame.size.width = 158.0
And apply corner radius like:
redView.clipsToBounds = true
redView.layer.cornerRadius = redView.frame.size.height / 2.0
Result:
Note: Check your constrains also If you are using Auto Layout. Be sure view frame doesn't change.
If you are using constraints then changing the frame/bounds of the view is not a good idea. Instead you should do the following.
If the view is contained in a UIViewController then set the cornerRadius in viewDidLayoutSubviews method
And if the view is itself a subclass of UIView the set the cornerRadius in layoutSubviews method
Only Squire view make a perfect circle. For example, if your view size is (10*10),(50*50),(100*100), etc. then your view becomes perfect squire else not.
Using IBDesignable, you can display without project run in storyboard ox .XIB #simple way
Step 1. Subclass UIView:
#IBDesignable class RoundedCornerView: UIView {
#IBInspectable var borderWidth:CGFloat = 2 {
didSet {
layer.borderWidth = borderWidth
}
}
#IBInspectable var borderColor:UIColor = UIColor.orangeGradientLight {
didSet {
layer.borderColor = borderColor.cgColor
}
}
override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = frame.height/2
layer.masksToBounds = true
layer.borderColor = borderColor.cgColor
layer.borderWidth = borderWidth
}
}
Step 2. Set custom class in identity inspector:
can't.
Try resize UIView to square: 79*79 OR 158*158
And set:
redView.layer.cornerRadius = redView.frame.size.height/2

Image View Double Border

I'm calling a function that sets up a UIImageView:
func setupImageView(_ imageView: UIImageView) {}
I want to give that UIImageView an image, round its corners, and give it two different borders.
Here is what I am currently doing:
imageView.image = imageConstants.imageThatIsWanted
imageView.clipsToBounds = true
imageView.layer.cornerRadius = imageView.frame.height / 2
imageView.layer.borderWidth = 3.0
imageView.layer.borderColor = UIColor.white.cgColor
What is the best way to apply a second borderColor of color blue around the white border?
I tried creating a sublayer as a CALayer and giving it a blue border, but this goes behind the image, and also inside of the white border. I also tried drawing a UIBezierPath, but that stays inside of the white border as well.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var secondView: UIView!
#IBOutlet weak var imgView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
imgView.layer.cornerRadius = imgView.frame.size.height/2
secondView.layer.cornerRadius = secondView.frame.size.height/2
imgView.layer.borderWidth = 5.0
imgView.layer.borderColor = UIColor.red.cgColor
imgView.clipsToBounds = true
secondView.clipsToBounds = true
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
You can add UIlabel or UIImageview at back of your image view having size little bit larger than your image view and applying corner radius, if you want to reduce line of your code (Please check below code)
imgview.layer.masksToBounds = true
imgview.layer.cornerRadius = imgview.frame.size.width/2
imgview.layer.borderWidth = 5
imgview.layer.borderColor = UIColor.white.cgColor
Add new image view programatically at back side of image view already taken
let img = UIImageView(frame: CGRect(x: imgview.frame.origin.x - 2, y: imgview.frame.origin.y - 2, width: imgview.frame.size.width + 4, height: imgview.frame.size.height + 4))
img.layer.masksToBounds = true
img.layer.cornerRadius = img.frame.size.width/2
//img.backgroundColor = UIColor.blue // You can also use background color instead of border
img.layer.borderWidth = 5
img.layer.borderColor = UIColor.blue.cgColor
self.view.addSubview(img)
self.view.sendSubview(toBack: img)
I know its not proper solution but we can use this to reduce lines of code
Hope it will helps you

How set swift 3 UITextField border color?

Hello i have working no error codes for UITextfield border color change but when using it in Swift 3 dont change textfield border color and dont gives error. I need your help my codes under below.
#IBOutlet weak var email: UITextField!
#IBOutlet weak var pass: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
let myColor : UIColor = UIColor.white()
email.layer.borderColor = myColor.cgColor
pass.layer.borderColor = myColor.cgColor
}
Thank you !
You also need to set border width, because your border color is set already but your default border width is 0.0 so you can't see it.
So, set border width something like,
email.layer.borderWidth = 1.0
Update :
Your code should be like,
#IBOutlet weak var email: UITextField!
#IBOutlet weak var pass: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
let myColor = UIColor.white
email.layer.borderColor = myColor.cgColor
pass.layer.borderColor = myColor.cgColor
email.layer.borderWidth = 1.0
pass.layer.borderWidth = 1.0
}
Use the below code in swift 3:
in view did load
outer_line.layer.borderWidth = 1
outer_line.layer.borderColor = UIColor.lightGray.cgColor
Try to use this,
It might be helpful to you
let myColor : UIColor = UIColor( red: 0.5, green: 0.5, blue:0, alpha: 1.0 )
myTextField.layer.masksToBounds = true
myTextField.layer.borderColor = myColor.CGColor
myTextField.layer.borderWidth = 2.0
I think you should first provide a borderWidth
#IBOutlet weak var email: UITextField!
#IBOutlet weak var pass: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
let myColor : UIColor = UIColor.white()
email.layer.borderWidth = 1
email.layer.borderColor = myColor.cgColor
pass.layer.borderColor = myColor.cgColor
}
and then set a color :)
Updated Swift 3 :
if you want to set the bottom border to UITextField, used below lines of code :
// function defination :
func setBottomBorderToTextFields() {
let bottomLine = CALayer()
bottomLine.frame = CGRect(x: 0, y: yourTextFieldName.frame.height - 1, width: yourTextFieldName.frame.width, height: 1)
bottomLine.backgroundColor = UIColor.gray.cgColor // background color
yourTextFieldName.borderStyle = UITextBorderStyle.none // border style
yourTextFieldName.layer.addSublayer(bottomLine)
}
// In ViewDidLoad() :
self.setBottomBorderToTextFields()
You need to set the borderWidth from the UITextField's layer property.
Like: email.layer.borderWidth = 1.
Also, if you frequently need to set borders to your views, you can make an extension like this:
extension UIView {
func addBorderAndColor(color: UIColor, width: CGFloat, corner_radius: CGFloat = 0, clipsToBounds: Bool = false) {
self.layer.borderWidth = width
self.layer.borderColor = color.cgColor
self.layer.cornerRadius = corner_radius
self.clipsToBounds = clipsToBounds
}
}
Call this like:
email.addBorderAndColor(color: UIColor.white, width: 0.5, corner_radius: 5, clipsToBounds: true)
Since this method sets the borderWidth, it will also solve your problem.
It is working.
give border width
and after give bgcolor.
txtemail.layer.borderWidth = 1.0
txtemail.layer.borderColor = UIColor.blue.cgColor
It definitely works

Resources