good morning together,
i have a tableview like this:
Example: in cell one i have got an red text label on the right side. left from it i include an image like a
Apart from using an extension, you can also use @IBDesignable / @IBInspectable to create a subclass from UILabel and draw the border there. This has some advantages, because you can then use the Interface Builder to style your label and it is shown directly in the Storyboard.
@IBDesignable
class LeftBorderedLabel: UILabel {
@IBInspectable var blockColor: UIColor = UIColor.black {
didSet{
let border = CALayer()
border.frame = CGRect(x: 0, y: 0, width: 15, height: self.frame.height)
border.backgroundColor = blockColor.cgColor;
self.layer.addSublayer(border)
}
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
}
}
Example in interface builder (example is for a tableViewCell):
Swift 4 Version:
extension CALayer {
func addBorder(edge: UIRectEdge, color: UIColor, thickness: CGFloat) {
let border = CALayer()
switch edge {
case UIRectEdge.top:
border.frame = CGRect(x: 0, y: 0, width: self.bounds.width, height: thickness)
case UIRectEdge.bottom:
border.frame = CGRect(x: 0, y: self.bounds.height - thickness, width: self.bounds.width, height: thickness)
case UIRectEdge.left:
border.frame = CGRect(x: 0, y: 0, width: thickness, height: self.bounds.height)
case UIRectEdge.right:
border.frame = CGRect(x: self.bounds.width - thickness, y: 0, width: thickness, height: self.bounds.height)
default:
break
}
border.backgroundColor = color.cgColor;
self.addSublayer(border)
}
}
Swift 3 version:
extension CALayer {
func addBorder(edge: UIRectEdge, color: UIColor, thickness: CGFloat) {
let border = CALayer()
switch edge {
case UIRectEdge.top:
border.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: thickness)
break
case UIRectEdge.bottom:
border.frame = CGRect(x: 0, y: self.frame.height - thickness, width: self.frame.width, height: thickness)
break
case UIRectEdge.left:
border.frame = CGRect(x: 0, y: 0, width: thickness, height: self.frame.height)
break
case UIRectEdge.right:
border.frame = CGRect(x: self.frame.width - thickness, y: 0, width: thickness, height: self.frame.height)
break
default:
break
}
border.backgroundColor = color.cgColor;
self.addSublayer(border)
}
}
Or use IBDesignable (see answer below)
Here is an extension you can add to your project.
SWIFT 3 :-
extension CALayer {
func addBorder(edge: UIRectEdge, color: UIColor, thickness: CGFloat) {
let border = CALayer()
switch edge {
case UIRectEdge.top:
border.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: thickness)
break
case UIRectEdge.bottom:
border.frame = CGRect(x: 0, y: self.frame.height - thickness, width: self.frame.width, height: thickness)
break
case UIRectEdge.left:
border.frame = CGRect(x: 0, y: 0, width: thickness, height: self.frame.height)
break
case UIRectEdge.right:
border.frame = CGRect(x: self.frame.width - thickness, y: 0, width: thickness, height: self.frame.height)
break
default:
//For Center Line
border.frame = CGRect(x: self.frame.width/2 - thickness, y: 0, width: thickness, height: self.frame.height)
break
}
border.backgroundColor = color.cgColor;
self.addSublayer(border)
}
}
And the use it like this:
labelName.layer.addBorder(edge: UIRectEdge.right, color: UIColor.black, thickness: 1.5)
If you want to draw a line on Center, then you can set following frame in any of the scenario :-
border.frame = CGRect(x: self.frame.width/2 - thickness, y: 0, width: thickness, height: self.frame.height)
These solutions worked for me, however I was using tableview rows and the height of the row was dynamically set based on how much content was in the rows.
For the above solutions I found that if the size of the row was dynamically increased because of the content within the row, the border's size didn't increase. So I had an incomplete border on rows that were larger than normal.
I came across this solution from @Debaprio B at this link (Oct 11, 2017 post): UIView set only side borders
His solution worked for me, and the border's sized changed appropriately when my row's size increased dynamically. I'm sharing @Debaprio's answer below for brevity:
public extension UIView {
// Border type and arbitrary tag values to identify UIView borders as subviews
public enum BorderType: Int {
case left = 20000
case right = 20001
case top = 20002
case bottom = 20003
}
public func addBorder(borderType: BorderType, width: CGFloat, color: UIColor {
// figure out frame and resizing based on border type
var autoresizingMask: UIViewAutoresizing
var layerFrame: CGRect
switch borderType {
case .left:
layerFrame = CGRect(x: 0, y: 0, width: width, height: self.bounds.height)
autoresizingMask = [ .flexibleHeight, .flexibleRightMargin ]
case .right:
layerFrame = CGRect(x: self.bounds.width - width, y: 0, width: width, height: self.bounds.height)
autoresizingMask = [ .flexibleHeight, .flexibleLeftMargin ]
case .top:
layerFrame = CGRect(x: 0, y: 0, width: self.bounds.width, height: width)
autoresizingMask = [ .flexibleWidth, .flexibleBottomMargin ]
case .bottom:
layerFrame = CGRect(x: 0, y: self.bounds.height - width, width: self.bounds.width, height: width)
autoresizingMask = [ .flexibleWidth, .flexibleTopMargin ]
}
// look for the existing border in subviews
var newView: UIView?
for eachSubview in self.subviews {
if eachSubview.tag == borderType.rawValue {
newView = eachSubview
break
}
}
Here is an extension you can add to your project:
extension CALayer {
func addBorder(edge: UIRectEdge, color: UIColor, thickness: CGFloat) {
var border = CALayer()
switch edge {
case UIRectEdge.Top:
border.frame = CGRectMake(0, 0, CGRectGetHeight(self.frame), thickness)
break
case UIRectEdge.Bottom:
border.frame = CGRectMake(0, CGRectGetHeight(self.frame) - thickness, UIScreen.mainScreen().bounds.width, thickness)
break
case UIRectEdge.Left:
border.frame = CGRectMake(0, 0, thickness, CGRectGetHeight(self.frame))
break
case UIRectEdge.Right:
border.frame = CGRectMake(CGRectGetWidth(self.frame) - thickness, 0, thickness, CGRectGetHeight(self.frame))
break
default:
break
}
border.backgroundColor = color.CGColor;
self.addSublayer(border)
}
}
And the use it like this:
cell.Label.layer.addBorder(UIRectEdge.Top, color: UIColor.greenColor(), thickness: 0.5)
FOR SWIFT 3, 4 & 5:
extension CALayer {
func addBorder(edge: UIRectEdge, color: UIColor, thickness: CGFloat) {
let border = CALayer()
switch edge {
case UIRectEdge.top:
border.frame = CGRect(x: 0, y: 0, width: self.frame.height, height: thickness)
break
case UIRectEdge.bottom:
border.frame = CGRect(x: 0, y: self.frame.height - thickness, width: UIScreen.main.bounds.width, height: thickness)
break
case UIRectEdge.left:
border.frame = CGRect(x: 0, y: 0, width: thickness, height: self.frame.height)
break
case UIRectEdge.right:
border.frame = CGRect(x: self.frame.width - thickness, y: 0, width: thickness, height: self.frame.height)
break
default:
break
}
border.backgroundColor = color.cgColor;
self.addSublayer(border)
}
}