I've added this image, I hope you can see it, of a user interface login. Notice the text field is transparent with the exception of the line at the bottom. What code do I put in to get that affect? Can I put the necessary information in the "user defined runtime attributes"?
Create a subclass of UITextField as below, And simply set this class in your storyboard to UITextField
Swift 5 Support With #IBInspectable
import UIKit
class HSUnderLineTextField: UITextField , UITextFieldDelegate {
let border = CALayer()
#IBInspectable open var lineColor : UIColor = UIColor.black {
didSet{
border.borderColor = lineColor.cgColor
}
}
#IBInspectable open var selectedLineColor : UIColor = UIColor.black {
didSet{
}
}
#IBInspectable open var lineHeight : CGFloat = CGFloat(1.0) {
didSet{
border.frame = CGRect(x: 0, y: self.frame.size.height - lineHeight, width: self.frame.size.width, height: self.frame.size.height)
}
}
required init?(coder aDecoder: (NSCoder?)) {
super.init(coder: aDecoder!)
self.delegate=self;
border.borderColor = lineColor.cgColor
self.attributedPlaceholder = NSAttributedString(string: self.placeholder ?? "",
attributes: [NSAttributedString.Key.foregroundColor: UIColor.white])
border.frame = CGRect(x: 0, y: self.frame.size.height - lineHeight, width: self.frame.size.width, height: self.frame.size.height)
border.borderWidth = lineHeight
self.layer.addSublayer(border)
self.layer.masksToBounds = true
}
override func draw(_ rect: CGRect) {
border.frame = CGRect(x: 0, y: self.frame.size.height - lineHeight, width: self.frame.size.width, height: self.frame.size.height)
}
override func awakeFromNib() {
super.awakeFromNib()
border.frame = CGRect(x: 0, y: self.frame.size.height - lineHeight, width: self.frame.size.width, height: self.frame.size.height)
self.delegate = self
}
func textFieldDidBeginEditing(_ textField: UITextField) {
border.borderColor = selectedLineColor.cgColor
}
func textFieldDidEndEditing(_ textField: UITextField) {
border.borderColor = lineColor.cgColor
}
}
Set lineColor and selectedLineColor from the storyboard and run your project.
Related
I am trying to create an underlined text field with placeholder text, I got the following extension to help out.
extension UITextField {
func setBottomLine(borderColor: UIColor) {
borderStyle = .none
backgroundColor = .clear
let borderLine = CALayer()
borderLine.frame = CGRect(x: 0, y: frame.height - 2, width: frame.width, height: 2)
layer.addSublayer(borderLine)
}
I call this extension in layout subviews of my view controller, and whenever I assign placeholder text nothing shows up. I am very confused on what the problem is. Thanks!
extension UITextField {
func setUnderLine() {
let border = CALayer()
let width = CGFloat(0.5)
border.borderColor = UIColor.darkGray.cgColor
border.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width - 10, height: self.frame.size.height)
border.borderWidth = width
self.layer.addSublayer(border)
self.layer.masksToBounds = true
}
}
override func viewDidLoad() {
super.viewDidLoad()
mytextField.setUnderLine()
}
Check this out.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var yourTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
yourTextField.textFieldUnderscoreAndPlaceholder()
}
}
extension UITextField {
//MARK: Text underscore with placeholder
func textFieldUnderscoreAndPlaceholder() {
//Underscore
let textFieldUnderscore = CALayer()
textFieldUnderscore.frame = CGRect(x: 0.0, y: frame.height - 1, width: frame.width, height: 1.0)
bounds = bounds.insetBy(dx: 0, dy: -2)
textFieldUnderscore.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1).cgColor
layer.addSublayer(textFieldUnderscore)
//Placeholder
placeholder = "Type some text here..."
}
}
Im very new to programming and am making a project that will have many UITextFields. I want to have the text fields only have a border on the bottom for a cleaner look, and I found some code here that is supposed to make that happen.
let border = CALayer()
let width = CGFloat(2.0)
border.borderColor = UIColor.darkGray.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
How can I make a class so that every UItext field I place in the storyboard I can simply make it part of said class? I don't want to copy and paste this code for each UITextField. And is there a way to do it where I could individually edit the placeholder text for each UITextfield this class is applied to?
it's very easy just enter this code in under any class only one time
#IBDesignable
open class customUITextField: UITextField {
func setup() {
let border = CALayer()
let width = CGFloat(2.0)
border.borderColor = UIColor.darkGray.cgColor
border.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width, height: self.frame.size.height)
border.borderWidth = width
self.layer.addSublayer(border)
self.layer.masksToBounds = true
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
}
In "Setup" function put all customizations you want.
After that back to design and choose it in all TextField you have and Run
Here is an example:
class CustomTextField: UITextField {
convenience init() {
self.init(frame: .zero)
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)
border.borderWidth = width
layer.addSublayer(border)
layer.masksToBounds = true
}
}
To simplify your border code you could do this:
layer.borderWidth = 2.0
layer.masksToBounds = true
I'm trying to apply a single bottom border to a textField that sits within one of my collectionViewCells. Here is the code:
class AddressCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
func basicTextField(placeHolderString: String) -> UITextField {
let textField = UITextField()
textField.font = UIFont.boldSystemFont(ofSize: 12)
textField.attributedPlaceholder = NSAttributedString(string: placeHolderString, attributes:[NSForegroundColorAttributeName: UIColor.lightGray, NSFontAttributeName: UIFont.boldSystemFont(ofSize: 12)])
textField.backgroundColor = UIColor.white
textField.translatesAutoresizingMaskIntoConstraints = false
return textField
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupViews() {
backgroundColor = UIColor.white
layer.addBorder(edge: UIRectEdge.bottom, color: .black, thickness: 0.5)
let streetTextfield = basicTextField(placeHolderString: "street")
addSubview(streetTextfield)
}
}
I am using an extension that enables me to apply a single border, which has worked great so far:
extension CALayer {
func addBorder(edge: UIRectEdge, color: UIColor, thickness: CGFloat) {
let border = CALayer()
switch edge {
case UIRectEdge.top:
border.frame = CGRect.init(x: 0, y: 0, width: frame.width, height: thickness)
break
case UIRectEdge.bottom:
border.frame = CGRect.init(x: 0, y: frame.height - thickness, width: frame.width, height: thickness)
break
case UIRectEdge.left:
border.frame = CGRect.init(x: 0, y: 0, width: thickness, height: frame.height)
break
case UIRectEdge.right:
border.frame = CGRect.init(x: frame.width - thickness, y: 0, width: thickness, height: frame.height)
break
default:
break
}
border.backgroundColor = color.cgColor;
self.addSublayer(border)
}
}
When i simply add a borderWidth to the textfield like this:
textField.layer.borderWidth = 0.5
I get a border and it renders fine. However, when i apply the extension to add a bottom border, like this:
textField.layer.addBorder(edge: UIRectEdge.bottom, color: .black, thickness: 0.5)
the border doesn't apply for some reason.
I'm not sure about the extension, but I have a working solution for a TextField with a bottom border.
basically create a class BottomBorderedTextField subclassing UITextField and insert the following code:
class BottomBorderedTextField: UITextField {
override func draw(_ rect: CGRect) {
super.draw(rect)
//this is the color of the bottom border. Change to whatever you what
let color: UIColor = UIColor.rgb(red: 230, green: 230, blue: 230)
let bottomBorder = CALayer()
bottomBorder.frame = CGRect(x: 0, y: bounds.size.height - 1, width: bounds.size.width, height: 2)
bottomBorder.backgroundColor = color.cgColor
self.layer.addSublayer(bottomBorder)
}
}
Then on your basicTextField function set the return type to the BottomBorderedTextField class you just made. so your new code will look like:
func basicTextField(placeHolderString: String) -> BottomBorderedTextField {
let textField = BottomBorderedTextField()
textField.font = UIFont.boldSystemFont(ofSize: 12)
textField.attributedPlaceholder = NSAttributedString(string: placeHolderString, attributes:[NSForegroundColorAttributeName: UIColor.lightGray, NSFontAttributeName: UIFont.boldSystemFont(ofSize: 12)])
textField.backgroundColor = UIColor.white
textField.translatesAutoresizingMaskIntoConstraints = false
return textField
}
I wrote a UIView extension that accomplishes the same thing:
extension UIView {
func addBottomBorder(width: CGFloat, color: UIColor, alpha: CGFloat) {
let border = CALayer()
let width = width
border.borderColor = color.withAlphaComponent(alpha).cgColor
border.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width, height: self.frame.size.height)
border.borderWidth = width
self.layer.addSublayer(border)
self.layer.masksToBounds = true
}
}
Usage:
usernameField.addBottomBorder(width: 2.0, color: UIColor.white, alpha: 0.5)
Also, seems within setupViews() you're calling:
layer.addBorder... //this is being called on the collection view cells layer
As opposed to:
streetTextfield.layer.addBorder...
I added bottom border to UITextField this way:
let bottomLine = CALayer()
bottomLine.frame = CGRectMake(0.0, self.frame.height, self.frame.width, CGFloat(borderWidth))
bottomLine.backgroundColor = borderColor.CGColor
self.borderStyle = UITextBorderStyle.None
self.layer.addSublayer(bottomLine)
How can I change the border color of this bottom line when UITextField call textFieldDidBeginEditing() and then change back color to default when it calls textFieldDidEndEditing()
I'm using a custom class of UITextField
Try just re-adding the layer with the default color in the textFieldDidEndEditing method, like so:
func textFieldDidBeginEditing(_ textField: UITextField) {
let bottomLine = CALayer()
bottomLine.frame = CGRectMake(0.0, self.frame.height, self.frame.width, CGFloat(borderWidth))
bottomLine.backgroundColor = borderColor.CGColor
self.borderStyle = UITextBorderStyle.None
self.layer.addSublayer(bottomLine)
}
func textFieldDidEndEditing(_ textField: UITextField) {
let bottomLine = CALayer()
bottomLine.frame = CGRectMake(0.0, self.frame.height, self.frame.width, CGFloat(borderWidth))
bottomLine.backgroundColor = defaultColor.CGColor
self.borderStyle = UITextBorderStyle.None
self.layer.addSublayer(bottomLine)
}
This worked for me
Take Action methods of textfield as editing did begin and editing did end
This will work fine, I have tested it
#IBAction func didbegin(_ sender: AnyObject) {
let border = CALayer()
let width = CGFloat(2.0)
border.borderColor = UIColor.green.cgColor
border.frame = CGRect(x: 0, y: txtfield.frame.size.height - width, width: txtfield.frame.size.width, height: txtfield.frame.size.height)
border.borderWidth = width
txtfield.layer.addSublayer(border)
txtfield.layer.masksToBounds = true
}
#IBAction func endediting(_ sender: AnyObject) {
let border = CALayer()
let width = CGFloat(2.0)
border.borderColor = UIColor.black.cgColor
border.frame = CGRect(x: 0, y: txtfield.frame.size.height - width, width: txtfield.frame.size.width, height: txtfield.frame.size.height)
border.borderWidth = width
txtfield.layer.addSublayer(border)
txtfield.layer.masksToBounds = true
}
Hope this thing helps you.
func viewWillAppear(_ animated: Bool) {
let border = CALayer()
let width = CGFloat(2.0)
border.borderColor = UIColor.white.cgColor
border.frame = CGRect(x: 0, y: yourTextFeild.frame.size.height - width, width: yourTextFeild.frame.size.width, height: yourTextFeild.frame.size.height)
border.borderWidth = width
yourTextFeild.layer.addSublayer(border)
yourTextFeild.layer.masksToBounds = true
}
//Mark Textfield Delegate
func textFieldDidBeginEditing(_ textField: UITextField) {
for layer in textField.layer.sublayers!{
layer.borderColor = UIColor.green.cgColor
}
}
func textFieldDidEndEditing(_ textField: UITextField) {
for layer in textField.layer.sublayers!{
layer.borderColor = UIColor.white.cgColor
}
}
I'm trying to change border properties with the following code:
class SimpleTextField: UITextField, UITextFieldDelegate {
override func layoutSubviews() {
super.layoutSubviews()
let border = CALayer()
let width = CGFloat(2.0)
border.borderColor = UIColor.black.cgColor
border.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width, height: self.frame.size.height)
border.borderWidth = width
self.layer.addSublayer(border)
self.layer.masksToBounds = true
self.delegate = self
}
func textFieldDidBeginEditing(_ textField: UITextField) {
let border = CALayer()
let width = CGFloat(2.0)
border.borderColor = UIColor.green.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
}
func textFieldDidEndEditing(_ textField: UITextField) {
let border = CALayer()
let width = CGFloat(2.0)
border.borderColor = UIColor.black.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
}
}
I wrote code in layoutSubviews() function as a default appearance for textField. I used textFieldDidBeginEditing() and textFieldDidEndEditing() functions for changing bottom border color. If I use the code layoutSubviews() the border color won't be changed at all but if I remove the code that I use as default appearance, border color will change but I don't have default border as the first time when text field is appeared.
Don't create new layer every time you start/end editing the text field. Instead, reuse it: make it a property and then just update when needed accordingly.
The default appearance you can set at the same point where the text field itself and the border are created, e.g.:
let textField = UITextField(frame: CGRect(x: 100.0, y: 100.0, width: 200.0, height: 50.0))
let border = CALayer()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(textField)
textField.layer.addSublayer(border)
textField.delegate = self
updateBorder(textField: textField, color: UIColor.black, width: 2.0)
}
func updateBorder(textField: UITextField, color: UIColor, width: CGFloat) -> Void {
border.backgroundColor = color.cgColor
border.frame = CGRect(x: 0.0, y: textField.frame.size.height - width, width: textField.frame.size.width, height: width);
}
func textFieldDidBeginEditing(_ textField: UITextField) {
updateBorder(textField: textField, color: UIColor.green, width: 2.0)
}
func textFieldDidEndEditing(_ textField: UITextField) {
updateBorder(textField: textField, color: UIColor.black, width: 2.0)
}