1

I have a page for forgot password. It has only a text field asking the user to fill in their email address. The Designer designed the text field with top and bottom border only. I tried answer from here UITextField Only Top And Bottom Border but in the result it only shows bottom border for the text field. enter image description here

Like in the image i would like to create a grey border for top and bottom

Joker
  • 830
  • 2
  • 14
  • 30

6 Answers6

5

To remove Fights with views you could create a tableView with a static cell that contains a TextField. Voila done... Top and bottom border comes for free and you will use standard apple stuff :)

If you really want to draw the layers than follow the steps on your linked questions:

CALayer *topBorder = [CALayer layer];
topBorder.frame = CGRectMake(0, 0, self.frame.size.width, 1);
topBorder.backgroundColor = [UIColor blackColor].CGColor;
[myTextField.layer addSublayer:topBorder];

CALayer *bottomBorder = [CALayer layer];
bottomBorder.frame = CGRectMake(0, self.frame.size.height - 1, self.frame.size.width, 1);
bottomBorder.backgroundColor = [UIColor blackColor].CGColor;
[myTextField.layer addSublayer:bottomBorder];

In Swift:

let topBorder = CALayer()
topBorder.frame = CGRectMake(0, 0, bounds.size.width, 1)
topBorder.backgroundColor = UIColor.grayColor()
textField.layer.addSublayer(topBorder)

let bottomBorder = CALayer()
bottomBorder.frame = CGRectMake(0, bounds.size.height-1, bounds.size.width, 1)
bottomBorder.backgroundColor = UIColor.grayColor()
textField.layer.addSublayer(bottomBorder)
Björn Ro
  • 780
  • 3
  • 9
2

Thanks @El Captain for the valuable comment and nice answer by @Bjorn Ro even if it was in Objective-c i think. And my answer for the question is (i'm using swift 2 Xcode 7)

Override the function viewDidLayoutSubviews() in your swift file. And the Code for the same is

override func viewDidLayoutSubviews() {
// Creates the bottom border
        let borderBottom = CALayer()
        let borderWidth = CGFloat(2.0)
        borderBottom.borderColor = UIColor.grayColor().CGColor
        borderBottom.frame = CGRect(x: 0, y: forgotPasswordEmailText.frame.height - 1.0, width: forgotPasswordEmailText.frame.width , height: forgotPasswordEmailText.frame.height - 1.0)
        borderBottom.borderWidth = borderWidth
        forgotPasswordEmailText.layer.addSublayer(borderBottom)
        forgotPasswordEmailText.layer.masksToBounds = true

// Creates the Top border
        let borderTop = CALayer()
        borderTop.borderColor = UIColor.grayColor().CGColor
        borderTop.frame = CGRect(x: 0, y: 0, width: forgotPasswordEmailText.frame.width, height: 1)
        borderTop.borderWidth = borderWidth
        forgotPasswordEmailText.layer.addSublayer(borderTop)
        forgotPasswordEmailText.layer.masksToBounds = true

    }

forgotPasswordEmailText is the text field for entering Email

The Final output looks like this... with a gray Colour border (Screen shot of iPhone 4s Simulator)enter image description here

Joker
  • 830
  • 2
  • 14
  • 30
  • right, i forgott that iam on a swift2 tag ... sorry about that :D just saw the linked post and was adapting it ;) – Björn Ro Oct 07 '15 at 06:30
  • @Björn Ro I thought about creating another layer and adding it. But as a developer from c# background and it's my first approach with Xcode and swift i was not sure about that. – Joker Oct 07 '15 at 06:35
  • Yeah, And Wish You guys will be here to answer more questions... ;) – Joker Oct 07 '15 at 06:39
0

Good suggestions for programatic solution posted so far. But I figured I'd share an Interfacebuilder solution....

1) Create view collection in your view controller

 @IBOutlet private var borderViews: [UIView]?

2) Create 2 UIViews in interface builder 1px high constrained to where you want them around the textfield

3) Connect the 2 views in interface builder to borderViews IBOutlet

4) Customise appearance of both views by using setValue forKeyPath... for example, on success you may want the border to turn green

 setValue(UIColor.green, forKeyPath: "borderViews.backgroundColor")
0

In Swift 3 use extension:

  1. Create Swift file

    import UIKit
    
    extension UITextField {
    
        func setBottomBorder() {
            self.borderStyle = .none
            self.layer.backgroundColor = UIColor.white.cgColor
            self.layer.masksToBounds = false
            self.layer.shadowColor = UIColor.gray.cgColor
            self.layer.shadowOffset = CGSize(width: 0.0, height: 1.0)
            self.layer.shadowOpacity = 1.0
            self.layer.shadowRadius = 0.0
        }
    }
    
  2. Call from anywhere:

    PasswordField.setBottomBorder();
    
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
0

Here's a nice and easy Swift 4 implementation that handles resizing views as well :)

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    viewToShadow.backgroundColor = .white
    viewToShadow.layer.masksToBounds = false

    viewToShadow.layer.sublayers?
        .filter { layer -> Bool in
            return layer.backgroundColor == UIColor.almostBlack.alpha(0.5).cgColor
        }
        .forEach { layer in
            layer.removeFromSuperlayer()
    }

    [CGRect(x: 0.0, y: 0.0, width: viewToShadow.bounds.width, height: 0.5),
     CGRect(x: 0.0, y: viewToShadow.bounds.height, width: viewToShadow.bounds.width, height: 0.5)]
        .forEach { frame in
            let layer = CALayer()
            layer.frame = frame
            layer.backgroundColor = UIColor.almostBlack.alpha(0.5).cgColor
            viewToShadow.layer.addSublayer(layer)
    }
}
Oscar Apeland
  • 6,422
  • 7
  • 44
  • 92
0

Use handy extension for it

extension UITextField {
    func addTopBorder(){
        let bottomLine = CALayer()
        bottomLine.frame = CGRect.init(x: 0, y: 0, width: self.frame.size.width, height: 1)
        bottomLine.backgroundColor = UIColor.white.cgColor
        self.borderStyle = UITextField.BorderStyle.none
        self.layer.addSublayer(bottomLine)

    }

    func addBottomBorder(){
        let bottomLine = CALayer()
        bottomLine.frame = CGRect.init(x: 0, y: self.frame.size.height - 1, width: self.frame.size.width, height: 1)
        bottomLine.backgroundColor = UIColor.white.cgColor

        self.attributedPlaceholder = NSAttributedString(string: self.placeholder ?? "-", attributes: [NSAttributedString.Key.foregroundColor : #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)])
        self.borderStyle = UITextField.BorderStyle.none
        self.layer.addSublayer(bottomLine)

    }
}

use it in you controller like this

yourTextfield.addTopBorder()
yourTextfield.addBottomBorder()

and don't forget to use it on main thread

  DispatchQueue.main.async {
            self.yourTextfield.addTopBorder()
           self.yourTextfield.addBottomBorder()
        }
NavinBagul
  • 741
  • 7
  • 24