CL So
CL So

Reputation: 3769

Border width and placeholder in custom UITextField

I want to make this TextField

enter image description here

So I write this class

class UnderLineTextField:UITextField{

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        let border = CALayer()
        let width = CGFloat(2.0)
        border.borderColor = UIColor.darkgray().cgColor
        border.frame = CGRect(x: 0, y: frame.size.height - width, width: frame.size.width, height: frame.size.height)

        textColor = UIColor.gold()
        backgroundColor = UIColor.clear

        border.borderWidth = width
        layer.addSublayer(border)
        layer.masksToBounds = true

        attributedPlaceholder = NSAttributedString(string: "",
                                                  attributes: [NSAttributedStringKey.foregroundColor: UIColor.darkgray()])}
}

But there are two problems

  1. The underline is not equal to TextField, if I add more width width: frame.size.width + 500, the problem can be fixed, but why? what is the correct value I should pass to width:?

  2. attributedPlaceholder will replace the placeholder I set in xib, how can I change placeholder without adding empty string?

enter image description here

enter image description here

Upvotes: 0

Views: 755

Answers (4)

Avadesh Yadav
Avadesh Yadav

Reputation: 31

Hey already lot of answers :), let's see if this detailed answer can help you achieve more: I prefer using extensions over inheritance if possible.

extension UITextField {

func setTextColor(_ color: UIColor, font: UIFont) {

    self.textColor = color
    self.font = font
}

func setBottomBorder(with color: UIColor, width: CGFloat) {
    self.borderStyle = .none
    self.layer.backgroundColor = UIColor.white.cgColor // bg color of your choice

    self.layer.masksToBounds = false
    self.layer.shadowColor = color.cgColor
    self.layer.shadowOffset = CGSize(width: 0.0, height: width)
    self.layer.shadowOpacity = 1.0
    self.layer.shadowRadius = 0.0
}


func setPlaceHolderAttributes(placeHolderText : String, colour : UIColor , font : UIFont){

    self.attributedPlaceholder = NSAttributedString(string:placeHolderText, attributes:[NSAttributedStringKey.foregroundColor: colour , NSAttributedStringKey.font : font])
}

}

//MARK: To give text insets

class MyTextField: UITextField {

override func textRect(forBounds bounds: CGRect) -> CGRect {
    return CGRect.init(x:10, y:2, width:bounds.width-20, height:bounds.height - 4)
}

override func editingRect(forBounds bounds: CGRect) -> CGRect {
    return textRect(forBounds: bounds)
}

}

And I prefer to configure UI from Code, it will fasten up your coding speed and achieve doing project wise change from one place, so you can do it from code like:

 let font: UIFont = UIFont.systemFont(ofSize: 14.0)
    let placeHolderTextColor: UIColor = UIColor.brown
    let textColor: UIColor = UIColor.darkText

    nameTextField.setBottomBorder(with: UIColor.darkGray, width: 1.0)
    passwordTextField.setBottomBorder(with: UIColor.darkGray, width: 1.0)

    nameTextField.setPlaceHolderAttributes(placeHolderText: "Name", colour: placeHolderTextColor, font: font)
    nameTextField.setTextColor(textColor, font: font)

    passwordTextField.setPlaceHolderAttributes(placeHolderText: "Password", colour: placeHolderTextColor, font: font)
    passwordTextField.setTextColor(textColor, font: font)

enter image description here

Hope this helps :)

Upvotes: 0

Sahil Omer
Sahil Omer

Reputation: 179

For UITextField underline use this one...

let border = CALayer()
let width = CGFloat(1.0)
border.borderColor = UIColor.gray.cgColor
border.frame = CGRect(x: 0, y: textField.frame.size.height - width, width:  textField.frame.size.width, height: textField.frame.size.height)

border.borderWidth = width
textField.layer.addSublayer(border)
textField.layer.masksToBounds = true

Upvotes: 0

guru
guru

Reputation: 2817

It seems your code is ok.

use below code for setting placeholder:

class UnderLineTextField:UITextField{

    @IBInspectable var borderColor: UIColor = UIColor.white {
        didSet {
            layer.borderColor = borderColor.cgColor

        }
    }
    @IBInspectable var placeHolderText: String = "default place holder" {
        didSet {
            attributedPlaceholder = NSAttributedString(string: placeHolderText,
                                                       attributes: [NSAttributedStringKey.foregroundColor: UIColor.darkGray])}

        }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        let border = CALayer()
        let width = CGFloat(2.0)
        border.borderColor = UIColor.darkGray.cgColor
        border.frame = CGRect(x: 0, y: frame.size.height - width, width: frame.size.width, height: frame.size.height)

        textColor = UIColor.lightGray
        backgroundColor = UIColor.clear

        border.borderWidth = width
        layer.addSublayer(border)
        layer.masksToBounds = true

        attributedPlaceholder = NSAttributedString(string: placeHolderText,
                                                   attributes: [NSAttributedStringKey.foregroundColor: UIColor.darkGray])}
}

and set your placeholder in storyboard: enter image description here

The result will look like below:

enter image description here

Upvotes: 1

Quoc Nguyen
Quoc Nguyen

Reputation: 3007

  1. The underline is not equal to TextField, if I add more width width: frame.size.width + 500, the problem can be fixed, but why? what is the correct value I should pass to width:?

You should put your draw underline code to draw(_ rect: CGRect) instead of init. Because of you using autolayout, so the width, that you got in init is difference with the width that you can see when run app.

  1. attributedPlaceholder will replace the placeholder I set in xib, how can I change placeholder without adding empty string?

You can redraw the attributedPlaceholder base on your placeholder in draw(_ rect: CGRect), too

attributedPlaceholder = NSAttributedString(
    string: self.placeholder,
    attributes: [NSAttributedStringKey.foregroundColor: UIColor.darkgray()]
)

Upvotes: 1

Related Questions