draw only top, right, and bottom border around a uilabel
Asked Answered
H

9

18

i try to add border for a uilabel, but i only want to have top, right, and bottom border.

like this

           ----------------
                          |
            I am a label  |
                          |
           ----------------

I try to use these codes, but it adds all 4 sides by default

    myLabel.layer.borderWidth = 1;
    myLabel.layer.borderColor = [UIColor blackColor];

Is that anyway i can only add 3 sides, or even 1 or 2 sides?

Thanks!

Heartburn answered 5/2, 2014 at 18:57 Comment(1)
Honestly, there's nothing wrong with adding three thin, black UIView - it is very easy with autolayout.Squinty
I
28

You can use a mask. This is the code I used to test the theory, and it works well:

// Define the border width in a variable, we'll be using it elsewhere
CGFloat borderWidth = 1.0;

// This creates a testing view to test the theory, in your case this will be your UILabel
UIView* view = [[UIView alloc] initWithFrame:CGRectMake(20, 60, 250, 100)];
view.layer.borderColor = [UIColor blackColor].CGColor;
view.layer.borderWidth = borderWidth;
[self.view addSubview:view];

// Create the mask to cover the area of the view you want to **show**
// Here, we create a mask that covers most of the view, except the left edge
// The mask needs to be coloured in black, as black acts as transparent, whereas white is opaque in mask parlance
UIView* mask = [[UIView alloc] initWithFrame:CGRectMake(borderWidth, 0, view.frame.size.width - borderWidth, view.frame.size.height)];
mask.backgroundColor = [UIColor blackColor];
view.layer.mask = mask.layer;

You can adjust the size and position of the mask (given the borderWidth) to show/hide the border edges you're interested in. The example above hides the left edge.

Inconsistent answered 5/2, 2014 at 19:12 Comment(6)
This looks great to me, Thank you. I would love to vote you up if i have 15 reputations..Heartburn
@Heartburn It's better than other solutions listed as this leaves the border drawing to the CoreGraphics framework, and doesn't pollute your view hierarchy with other views. The mask is optimised, and hence will get better performance. (So not sure why is no longer the accepted answer...)Inconsistent
Oh, i am so sorry,i am very new to Stackoverflow, i thought i could accept both your answer and Mikael's answer. Your answer is better. maybe i should just vote up if i have enough reputation...Heartburn
How do I implement this in Swift?Betseybetsy
In Swift use this: let view = UIView(frame: CGRectMake(20,60 , 250, 100)) view.layer.borderColor = UIColor.blueColor().CGColor; view.layer.borderWidth = borderWidth; self.view.addSubview(view) let mask = UIView(frame: CGRectMake(borderWidth, 0, view.frame.size.width - borderWidth, view.frame.size.height)) // mask.backgroundColor = UIColor.blackColor() view.layer.mask = mask.layer;Agitprop
#19891456Agitprop
L
7

You'll have to adjust sizes but this is the gist of it. (might be some typos)

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 35)];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 15, 320, 20)];

CALayer *bottomBorder = [CALayer layer];
bottomBorder.frame = CGRectMake(0, 40, 320, .5);

CALayer *rightBorder = [CALayer layer];
rightBorder.frame = CGRectMake(320, 0, 40, .5);

CALayer *topBorder = [CALayer layer];
topBorder.frame = CGRectMake(0, 0, 320, .5);

[view.layer addSublayer:bottomBorder];
[view.layer addSublayer:topBorder];
[view.layer addSublayer:rightBorder];
[view.layer addSublayer:label];
Lao answered 5/2, 2014 at 19:9 Comment(2)
I think i only want to have it on my label, since i have about 6 on one view controller. in your code, i might have to create another 6 uiviews, but thank you for your idea.Heartburn
Just remove the view it's the same. I just think it's neater with the view.Lao
C
7

You can draw your three sides with one line by creating a CALayer that uses a UIBezierPath. With all of the examples, include the QuartzCore framework as part of your project.

Following your original code as a starting point:

// at the top of the file with this code, include:
#import <QuartzCore/QuartzCore.h>

CGRect rect = myLabel.frame;

UIBezierPath * linePath = [UIBezierPath bezierPath];

// start at top left corner
[linePath moveToPoint:CGPointMake(0,0);
// draw top line across
[linePath addLineToPoint:CGPointMake(rect.size.width, 0);
// draw right vertical side
[linePath addLineToPoint:CGPointMake(rect.size.width, rect.size.height);
// draw left vertical side
[linePath addLineToPoint:CGPointMake(0, rect.size.height);

// draw from bottom right corner back to bottom left corner
[linePath addLineToPoint:CGPointMake(0, rect.size.height);

// create a layer that uses your defined path
CAShapeLayer * lineLayer = [CAShapeLayer layer];
lineLayer.lineWidth = 1.0;
lineLayer.strokeColor = [UIColor blackColor].CGColor;

lineLayer.fillColor = nil;
lineLayer.path = linePath.CGPath;

[myLabel.layer addSublayer:lineLayer];
Checkroom answered 17/3, 2014 at 4:35 Comment(0)
A
6

I'm using Swift 3.

// myLabel is a UILabel
let frame = myLabel.frame //Frame of label

// Bottom Layer
let bottomLayer = CALayer()
bottomLayer.frame = CGRect(x: 0, y: frame.height - 1, width: frame.width, height: 1)
bottomLayer.backgroundColor = UIColor.black.cgColor
myLabel.layer.addSublayer(bottomLayer)

// Top Layer
let topLayer = CALayer()
topLayer.frame = CGRect(x: 0, y: 0, width: frame.width, height: 1)
topLayer.backgroundColor = UIColor.black.cgColor
myLabel.layer.addSublayer(topLayer)

Similarly:

// Right Layer
let rightLayer = CALayer()
rightLayer.frame = CGRect(x: frame.width - 1, y: 0, width: 1, height: frame.height)
rightLayer.backgroundColor = UIColor.black.cgColor
myLabel.layer.addSublayer(rightLayer)

Where 1 is the width of the border.

Atheist answered 13/6, 2017 at 9:57 Comment(0)
C
1

Here you guys go! Hope this helps, Add this inside UItextfield override class

UIView *view = [[UIView alloc] init];
view.translatesAutoresizingMaskIntoConstraints = NO;
view.layer.borderWidth = 1;
view.backgroundColor = [UIColor blackColor];
[self addSubview:view];

[self addConstraint:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]];
[self addConstraint:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0]];
[self addConstraint:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeHeight multiplier:1.0 constant:1.0]];
[self addConstraint:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:1.0]];
Catalyst answered 6/4, 2016 at 1:12 Comment(0)
R
1

Thanks @jaiswal, i used your code and created a function, because i had more than 10 UILabels. I have put it here for reference.

 func buttomBoarder(label: UILabel) -> UILabel {
    let frame = label.frame

    let bottomLayer = CALayer()
    bottomLayer.frame = CGRect(x: 0, y: frame.height - 1, width: frame.width, height: 1)
    bottomLayer.backgroundColor = UIColor.black.cgColor
    label.layer.addSublayer(bottomLayer)

    return label

}

Called using

labelName = buttomBoarder(label: labelName)
Reddin answered 15/3, 2018 at 8:10 Comment(0)
L
0

You can subclass UILabel and override drawRect: to do that.

Or you could just make 3 UIView's with black background as subviews of this label. If you set autoresizingMask on them properly they will adjust to changes in the size of the label. Top border should have flexible width and flexible bottom margin, bottom border should have flexible width and flexible top margin, right border should have flexible height and flexible left margin.

Lynellelynett answered 5/2, 2014 at 19:5 Comment(1)
Maybe some codes would be helpful. But Thank you for your ideas.Heartburn
I
0

You can do it with multiple ways: 1st one is the easiest one just find a image that looks like your border strokes. Then add it an UIImageView back of your UILabel. 2nd way is override UILabel drawRect: then draw the stoke according to your needs.

Interchangeable answered 5/2, 2014 at 19:19 Comment(0)
P
0

Simple extension on uilabel can solve the issue import UIKit

extension UILabel {
    
    func bottomBorder(with borderColor: UIColor, and borderWidth: CGFloat = 1.0){
        let bottomBorder = CALayer()
        bottomBorder.frame = CGRect(x: 0, y: self.frame.size.height - borderWidth, width: self.frame.size.width, height:borderWidth)
        bottomBorder.backgroundColor = borderColor.cgColor
        self.layer.addSublayer(bottomBorder)
    }
}
Partner answered 5/3, 2023 at 7:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.