Trombone0904
Trombone0904

Reputation: 4268

swift label only border left

good morning together,

i have a tableview like this: enter image description here

Example: in cell one i have got an red text label on the right side. left from it i include an image like a grey line.

with this code i can set a complete green border:

    cell.Label.layer.borderWidth = 0.5
    cell.Label.layer.borderColor = UIColor.greenColor().CGColor

can i set only a border on the left side from this text label? i use swift ios8 - so, i need a swift solution

Upvotes: 9

Views: 22063

Answers (6)

Maysam
Maysam

Reputation: 7367

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)
    }

}

Upvotes: 42

Tom
Tom

Reputation: 966

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)

Upvotes: 18

Kunal Shah
Kunal Shah

Reputation: 1121

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)
    }
}

Upvotes: 3

Andrew
Andrew

Reputation: 637

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
    }
}

Upvotes: 1

Meet Doshi
Meet Doshi

Reputation: 4259

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)

Upvotes: -1

Tom
Tom

Reputation: 966

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):

Interface builder example

Upvotes: 0

Related Questions