Creating and removing border line on textFields - ios

Actually i am trying to change border colour of each text field(By increasing border width) on tap.
I have given textFieldEmailAddress.tag = 1 and textFieldPassword.tag = 2 by using stotyBoard.
I am using UITextFieldDelegate.
Means my requirement is :-
1. when i click on a text field its border colour should be dark blue(width =0.8)
and other text fields border line colour should be light blue (width = 0.4)
If we don't click on a text field its border line colour should be light blue.(width = 0.4).
But i am facing a problem when click on text field first time its working fine ,but just when i tap on another text field ,its giving dark blue border colour.
problem is whaever textfield became 0.8 it's not reverting to 0.4 in UI (means UI is not updating only value is getting updated to 0.4)
Is any thing wrong in delegate method or in my below code :-
//View Did load function
override func viewDidLoad()
{
//Set delegate
self.textFieldEmailAddress.delegate = self
self.textFieldPassword.delegate = self
//Create border line on text email address fields.
self.borderline(textFieldEmailAddress)
//Create border line on text password fields.
self.borderline(textFieldPassword)
}
func textFieldDidBeginEditing(textField: UITextField)
{
switch textField.tag
{
case 1:
self.Darkborderline(textFieldEmailAddress)
break
case 2:
self.Darkborderline(textFieldPassword)
break
default:
break
}
}
func textFieldDidEndEditing(textField: UITextField)
{
switch textField.tag
{
case 1:
self.borderline(textFieldEmailAddress)
break
case 2:
self.borderline(textFieldPassword)
break
default:
break
}
}
//Light blue Border line on text field.
func borderline(textField : UITextField)
{
switch textField.tag
{
case 1:
width = CGFloat(0.40)
let border = CALayer()
border.borderColor = UIColor.blueColor().CGColor
border.frame = CGRect(x: 0, y: textFieldEmailAddress.frame.size.height - width,
width: textFieldEmailAddress.frame.size.width, height: width)
border.borderWidth = width
textFieldEmailAddress.borderStyle = UITextBorderStyle.None
textFieldEmailAddress.layer.addSublayer(border)
textFieldEmailAddress.layer.masksToBounds = true
break
case 2:
width = CGFloat(0.40)
let border = CALayer()
border.borderColor = UIColor.blueColor().CGColor
border.frame = CGRect(x: 0, y: textFieldPassword.frame.size.height - width,
width: textFieldPassword.frame.size.width, height: width)
border.borderWidth = width
textFieldPassword.borderStyle = UITextBorderStyle.None
textFieldPassword.layer.addSublayer(border)
textFieldPassword.layer.masksToBounds = true
break
default: break
}
}
//Dark blue Border line on text field.
func Darkborderline(textField : UITextField)
{
//let border = CALayer()
switch textField.tag
{
case 1:
width = CGFloat(0.80)
let border = CALayer()
border.borderColor = UIColor.blueColor().CGColor
border.frame = CGRect(x: 0, y: textFieldEmailAddress.frame.size.height - width,
width: textFieldEmailAddress.frame.size.width, height: width)
border.borderWidth = width
textFieldEmailAddress.borderStyle = UITextBorderStyle.None
textFieldEmailAddress.layer.addSublayer(border)
textFieldEmailAddress.layer.masksToBounds = true
break
case 2:
width = CGFloat(0.80)
let border = CALayer()
border.borderColor = UIColor.blueColor().CGColor
border.frame = CGRect(x: 0, y: textFieldPassword.frame.size.height - width,
width: textFieldPassword.frame.size.width, height: width)
border.borderWidth = width
textFieldPassword.borderStyle = UITextBorderStyle.None
textFieldPassword.layer.addSublayer(border)
textFieldPassword.layer.masksToBounds = true
break
default: break
}
}

First declare one method to set bottom border to field and use the delegate method of UITextFieldDelegate like this
On viewDidLoad first assign thin border like this to both the fields
override func viewDidLoad() {
super.viewDidLoad()
self.setBottomBorder(self.textFieldEmailAddress, width: 0.4)
self.setBottomBorder(self.textFieldPassword, width: 0.4)
self.setBottomBorder(self.passwordBtn, width: 0.4)
}
func setBottomBorder(view: UIView, width: CGFloat) {
let border = CALayer()
border.name = "BottomBorder"
border.borderColor = UIColor.blueColor().CGColor
border.frame = CGRect(x: 0, y: view.frame.size.height - width,
width: view.frame.size.width, height: width)
border.borderWidth = width
view.borderStyle = UITextBorderStyle.None
view.layer.addSublayer(border)
view.layer.masksToBounds = true
}
func removeBottomBorder(view: UIView) {
if let sublayers = view.layer.sublayers {
for layer: CALayer in sublayers {
if layer.name == "BottomBorder" {
layer.removeFromSuperlayer()
break
}
}
}
}
func textFieldDidBeginEditing(textField: UITextField) {
self.removeBottomBorder(textField)
self.setBottomBorder(textField, width: 0.8)
if (textFieldPassword == textField) {
self.setBottomBorder(self.passwordBtn, width: 0.8)
}
}
func textFieldDidEndEditing(textField: UITextField) {
self.removeBottomBorder(textField)
self.setBottomBorder(textField, width: 0.4)
if (textFieldPassword == textField) {
self.removeBottomBorder(self.passwordBtn)
self.setBottomBorder(self.passwordBtn, width: 0.4)
}
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}

Try this once .
func textFieldShouldBeginEditing(textField: UITextField) -> Bool
{
if 1 == textField.tag
{
selectedTextField = textFieldEmailAddress
self.selectedTextField.layer.borderColor = UIColor.blueColor().CGColor
self.selectedTextField.layer.borderWidth = 0.8
self.selectedTextField = textField
self.textFieldPassword.layer.borderColor = UIColor.blueColor().CGColor
self.textFieldPassword.layer.borderWidth = 0.4
return true
}
else if 2 == textField.tag
{
selectedTextField = textFieldPassword
self.selectedTextField.layer.borderColor = UIColor.blueColor().CGColor
self.selectedTextField.layer.borderWidth = 0.8
self.selectedTextField = textField
self.textFieldEmailAddress.layer.borderColor = UIColor.blueColor().CGColor
self.textFieldEmailAddress.layer.borderWidth = 0.4
return true
}
else
{
return false
}
}
func textFieldShouldReturn(textField: UITextField) -> Bool
{
self.selectedTextField.layer.borderColor = UIColor.blueColor().CGColor
self.selectedTextField.layer.borderWidth = 0.4
self.selectedTextField = UITextField()
textField.resignFirstResponder()
return true
}

Related

How to Make an UIButton Shrink Into an UIActivityIndicator When Pressed?

I'm trying to create an UIButton that will shrink down to an Activity Indicator when tapped on. The UIButton I'm referring to is named Request Ride. I have most of the code already set, but for some reason the button won't shrink and the indicator won't show up? I'll attach pictures of the app and my code.
// My app
// My end result I'm needing
// Main Storyboard
// HomeVC
#IBAction func actionBtnWasPressed(_ sender: Any) {
actionBtn.animateButton(shouldLoad: true, withMessage: nil)
}
// RoundedShadowButton
class RoundedShadowButton: UIButton {
// Variables
var originalSize: CGRect?
func setupView() {
originalSize = self.frame
self.layer.cornerRadius = 5.0
self.layer.shadowRadius = 10.0
self.layer.shadowColor = UIColor.darkGray.cgColor
self.layer.shadowOpacity = 0.3
self.layer.shadowOffset = CGSize.zero
}
override func awakeFromNib() {
setupView()
}
func animateButton(shouldLoad: Bool, withMessage message: String?) {
let spinner = UIActivityIndicatorView()
spinner.style = .large
spinner.color = UIColor.darkGray
spinner.alpha = 0.0
spinner.hidesWhenStopped = true
spinner.tag = 21
if shouldLoad {
self.addSubview(spinner)
self.setTitle("", for: .normal)
UIView.animate(withDuration: 0.2, animations: {
self.layer.cornerRadius = self.frame.height / 2
self.frame = CGRect(x: self.frame.midX - (self.frame.height / 2), y: self.frame.origin.y, width: self.frame.height, height: self.frame.height)
}) { (finished) in
if finished == true {
spinner.startAnimating()
spinner.center = CGPoint(x: self.bounds.width / 2 + 1, y: self.bounds.width / 2 + 1)
UIView.animate(withDuration: 0.2) {
spinner.alpha = 1.0
}
}
}
self.isUserInteractionEnabled = false
} else {
self.isUserInteractionEnabled = true
for subview in self.subviews {
if subview.tag == 21 {
subview.removeFromSuperview()
}
}
UIView.animate(withDuration: 0.2) {
self.layer.cornerRadius = 5.0
self.frame = self.originalSize!
self.setTitle(message, for: .normal)
}
}
}
}
One obvious thing is that this line is totally wrong:
spinner.center = CGPoint(x: self.frame.width / 2 + 1, y: self.frame.width / 2 + 1)
You are placing the spinner incorrectly. If the activity view is a subview of the button, then it needs to be centered at the middle of the button’s bounds, not its frame.
I was able to get an effect somewhat like what you are describing:
So this ought to be possible if you get your values right.

How to change border thickness of UISearchBar?

I'm trying to make my search bar look like this
A white background with a thin grey border.
On Xcode, I can set Search style to default (which gives the white background) and Bar tint to grey (which gives the grey border.)
But the result I get is this
How do I change the thickness of the bar to reflect the design I'm going for?
(also, is there a way to change just the font of the search bar? I only found ways to change the font size)
Follow this below steps -
1.Choose UITextField from the object library
2.Drag to your storyboard
3.Choose border style as none.
4.Create a Swift file and add this below extension -
extension UIView {
#IBInspectable var cornerRadius: CGFloat {
get {
return layer.cornerRadius
}
set {
layer.cornerRadius = newValue
layer.masksToBounds = newValue > 0
}
}
#IBInspectable var borderWidth: CGFloat {
get {
return layer.borderWidth
}
set {
layer.borderWidth = newValue
}
}
#IBInspectable var borderColor: UIColor? {
get {
return UIColor(cgColor: layer.borderColor!)
}
set {
layer.borderColor = newValue?.cgColor
}
}
}
extension UIButton {
func roundedButton(){
let maskPAth1 = UIBezierPath(roundedRect: self.bounds,
byRoundingCorners: [.topLeft , .topRight],
cornerRadii:CGSize(width:8.0, height:8.0))
let maskLayer1 = CAShapeLayer()
maskLayer1.frame = self.bounds
maskLayer1.path = maskPAth1.cgPath
self.layer.mask = maskLayer1
}
}
extension UITextField {
func setLeftPaddingPoints(_ amount:CGFloat){
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: amount, height: self.frame.size.height))
self.leftView = paddingView
self.leftViewMode = .always
}
func setRightPaddingPoints(_ amount:CGFloat) {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: amount, height: self.frame.size.height))
self.rightView = paddingView
self.rightViewMode = .always
}
}
extension UITextField {
#IBInspectable var maxLength: Int {
get {
if let length = objc_getAssociatedObject(self, &kAssociationKeyMaxLength) as? Int {
return length
} else {
return Int.max
}
}
set {
objc_setAssociatedObject(self, &kAssociationKeyMaxLength, newValue, .OBJC_ASSOCIATION_RETAIN)
addTarget(self, action: #selector(checkMaxLength), for: .editingChanged)
}
}
#objc func checkMaxLength(textField: UITextField) {
guard let prospectiveText = self.text,
prospectiveText.count > maxLength
else {
return
}
let selection = selectedTextRange
let indexEndOfText = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
let substring = prospectiveText[..<indexEndOfText]
text = String(substring)
selectedTextRange = selection
}
}
5.Now you can access this extensions either from storyboard or from code to change the values and see the effects.
6.You can change the corner radius, border width, border colour for UITextField.
Hope this method also helps.
The style UISearchBar.Style.minimal provides no default background color or image
and use UITextFiled instead search bar so you can customise icon location
YourTextFiled.rightView = UIImageView(image: UIImage(named: "search-icon"))
YourTextFiled.rightViewMode = UITextField.ViewMode.always

Why the Horizontal line in text fields are conflicting in Landscape mode in ipad in Swift?

I am using this code in Xcode 9, iOS 11.
var boolName: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
if boolName == true {
self.designTextField()
self.view.layoutIfNeeded()
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if boolName == false {
self.designTextField()
boolName = true
}
self.view.layoutIfNeeded()
}
func designTextField() {
//Set the horizontal line in bottom of text field
nameLayer.frame = CGRect(x: 0, y: self.tfName.bounds.size.height, width: self.tfName.bounds.size.width, height: 1)
nameLayer.backgroundColor = UIColor.lightGray.cgColor
tfName.layer.addSublayer(nameLayer)
//Set the horizontal line in bottom of text field
phoneLayer.frame = CGRect(x: 0, y: self.tfPhone.bounds.size.height, width: self.tfPhone.bounds.size.width, height: 1)
phoneLayer.backgroundColor = UIColor.lightGray.cgColor
tfPhone.layer.addSublayer(phoneLayer)
//Set the horizontal line in bottom of text field
emailLayer.frame = CGRect(x: 0, y: self.tfEmail.bounds.size.height, width: self.tfEmail.bounds.size.width, height: 1)
emailLayer.backgroundColor = UIColor.lightGray.cgColor
tfEmail.layer.addSublayer(emailLayer)
}
When using that code and testing in iPad. And the issue is when i rotate the iPad in Landscape Mode, then the horizontal line of text fields(in bottom) are conflicting.
Can somebody plzz help ?
Case if boolName == false stops the redrawing on landscape mode, remove it. And in method designTextField, set the line layers' names, then you are able to get and update them.
let kLineName = "nameLine"
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.designTextField()
}
func designTextField()
{
//Set the horizontal line in bottom of text field
if let index = tfName.layer.sublayers?.index(where: { (layer) -> Bool in
return layer.name == kLineName
}) {
//Update line's frame if it's existed.
let nameLayer = tfName.layer.sublayers![index]
nameLayer.frame = CGRect(x: 0, y: self.tfName.bounds.size.height, width: self.tfName.bounds.size.width, height: 1)
}
else{
//Add layer if it's not existed.
nameLayer.frame = CGRect(x: 0, y: self.tfName.bounds.size.height, width: self.tfName.bounds.size.width, height: 1)
nameLayer.backgroundColor = UIColor.lightGray.cgColor
nameLayer.name = kLineName
tfName.layer.addSublayer(nameLayer)
}
//Same to the phoneLayer and emailLayer ......
}

CALayer border colour and width are not changing?

I have 5 textFields and my requirement is I have to set 0.2 border width initially, after that when tap on edit button I have to change border width from 0.2 to 0.8 and again tap on submit button I have to change border width from 0.8 to 0.2.
The thing is that border colour and width are not changing. Here below is my code:
class EditProductCell: UITableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
//Create Border Line.
createBorderLine(0.2,UIColor.lightGray)
}
//Create Border Line on Text Field
func createBorderLine(_ width : CGFloat, _ color : UIColor)//_ width : CGFloat, _ color : UIColor)
{
setBottomBorder(textField: InvoiceDate, width: width,color : color)
setBottomBorder(textField: InvoiceNumber, width: width,color : color)
setBottomBorder(textField: modelNumber, width: width,color : color)
setBottomBorder(textField: productName, width: width,color : color)
setBottomBorder(textField: serialNumber, width: width,color : color)
self.layoutSubviews()
}
}
Here is another class:
class EditProductView: BaseViewController {
//TableView
#IBOutlet var tableView: UITableView!
//View Did Load
override func viewDidLoad() {
super.viewDidLoad()
//self.view.backgroundColor = hexStringToUIColor(hex: "#CCCCCC")
tableView.delegate = self
tableView.dataSource = self
//Button Submit
self.btnSubmit.isHidden = true
tableView.bounces = false
tableView.alwaysBounceVertical = false
hideKeyboardWhenTappedAround()
}
//Button Submit
#IBAction func btnSubmitAction(_ sender: Any) {
self.btnSubmit.isHidden = true
let index : NSIndexPath = NSIndexPath(row: 0, section: 0)
let tCell : EditProductCell = self.tableView.cellForRow(at: index as IndexPath) as! EditProductCell
//Change border line
tCell.createBorderLine(0.2, UIColor.lightGray)
tCell.btnEdit.isHidden = false
dismissKeyboard()
}
func btnEditAction()
{
btnSubmit.isHidden = false
let index : NSIndexPath = NSIndexPath(row: 0, section: 0)
let tCell : EditProductCell = self.tableView.cellForRow(at: index as IndexPath) as! EditProductCell
tCell.btnEdit.isHidden = true
//Create border line
tCell.createBorderLine(0.8, UIColor.black)
dismissKeyboard()
}
}
Here is set bottom border method in separate class:
//Set Bottom border line.
func setBottomBorder(textField: UITextField, width: CGFloat,color : UIColor) {
let border = CALayer()
border.name = "BottomBorder"
border.borderColor = color.cgColor
border.frame = CGRect(x: 0, y: textField.frame.size.height - width,
width: textField.frame.size.width, height: width)
border.borderWidth = width
textField.borderStyle = UITextBorderStyle.none
textField.layer.addSublayer(border)
textField.layer.masksToBounds = true
}
You can see in my code that button submit and button edit. I am changing border line colour and width. Colour and width are not.
I also tried something in but not able to get width change.
override func layoutSublayers(of layer: CALayer) {
if (layer == self.layer)
{
layer.borderWidth = 0.3
}
}
//MARK:- TextField Delegate
extension EditProductCell : UITextFieldDelegate
{
func textFieldDidBeginEditing(_ textField: UITextField) {
if let sublayers = textField.layer.sublayers {
for layer: CALayer in sublayers {
if layer.name == "BottomBorder" {
layer.removeFromSuperlayer()
}
}
}
setBottomBorder(textField: textField, width: 0.8, color: hexStringToUIColor(hex: "#55ACEE"))
}
//TextField Did End Editing
func textFieldDidEndEditing(_ textField: UITextField) {
if let sublayers = textField.layer.sublayers {
for layer: CALayer in sublayers {
if layer.name == "BottomBorder" {
layer.removeFromSuperlayer()
}
}
}
setBottomBorder(textField: textField, width: 0.8,color : UIColor.black)
textField.resignFirstResponder()
}
//TextField Return Key
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// Try to find next responder
if let nextField = textField.superview?.viewWithTag(textField.tag + 1) as? UITextField
{
nextField.becomeFirstResponder()
}
else
{
textField.resignFirstResponder()
}
return false
}
}
Swift 4
shape.strokeColor = UIColor.lightGray.cgColor
shape.lineWidth = 1.0
If you try with numbers greater than 1 your code works. I think the border width need to be greater than 1.

Why bottom border line of textField is showing half?

I have 5 textFields in my UIViewController and I have to show bottom border line on these all textFields.
I am using FloatLabelTextField class and trying to set bottom border on each textField by programatically but very first time (in viewDidLoad method) border line is just showing half. I don't know why this is showing.
Here is my code:
import UIKit
class ViewController: UITableViewController {
#IBOutlet var vwName: FloatLabelTextField!
override func viewDidLoad() {
super.viewDidLoad()
vwName.delegate = self
setBottomBorder(textField: vwName, width: 0.8, color: .darkGray)
}
}
extension ViewController : UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
if let sublayers = textField.layer.sublayers {
for layer: CALayer in sublayers {
if layer.name == "BottomBorder" {
layer.removeFromSuperlayer()
}
}
}
setBottomBorder(textField: textField, width: 0.8, color: .blue)
}
func textFieldDidEndEditing(_ textField: UITextField) {
if let sublayers = textField.layer.sublayers {
for layer: CALayer in sublayers {
if layer.name == "BottomBorder" {
layer.removeFromSuperlayer()
}
}
}
setBottomBorder(textField: textField, width: 0.8, color: .lightGray)
textField.resignFirstResponder()
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
extension ViewController {
func setBottomBorder(textField: UITextField, width: CGFloat, color: UIColor) {
let border = CALayer()
border.name = "BottomBorder"
border.borderColor = color.cgColor
border.frame = CGRect(x: 0, y: textField.frame.size.height - width, width: textField.frame.size.width, height: width)
border.borderWidth = width
textField.borderStyle = UITextBorderStyle.none
textField.layer.addSublayer(border)
textField.layer.masksToBounds = true
}
}
If I tap on a text field then border line is coming properly. I mean when TextFieldDidBeginEditing delegate method call then border line showing properly.
But initially when view load then it is showing half.

Resources