Goals
- Create custom UITextField
- It should be transparent
- It should have border
- It should have rounded corners
- Rounded corners and border width should be setting via Xcode Interface Builder (IBInspectable / IBDesignable)
- Create custom clear button for custom UITextField
- Use Extensions for creating custom clear button
- Use Google Material Design Icon as image for button
- Set for button image custom color
- Make button always visible even if textfield is not in focus
- Set for button padding from right side of textfield
- Make textfield not editable but still available for touches
- Do not show keyboard
- Add default parameter values
- Clear button should be available for tap
- Fill textfield by clicking on special button
- Send Local Notification when custom clear button is tapped
- Use completely different approach for the same goal - Create custom clear button without adding Right View in UITextField
Implementation
Custom TextField
import UIKit
import UIKit
@IBDesignable
class CustomTextField: UITextField {
@IBInspectable
var borderWidth: CGFloat {
get {
return self.layer.borderWidth
}
set {
self.layer.borderWidth = newValue
}
}
@IBInspectable
var borderColor: UIColor? {
get {
return UIColor(cgColor: self.layer.borderColor!)
}
set {
self.layer.borderColor = newValue?.cgColor
}
}
@IBInspectable
var cornerRadius: CGFloat {
set {
self.layer.cornerRadius = newValue
}
get {
return self.layer.cornerRadius
}
}
}
Add Custom Clear Button with Extensions
import Foundation
import UIKit
extension UITextField {
func clearButtonWithImage(_ image: UIImage) {
let clearButton = UIButton()
clearButton.setImage(image, for: .normal)
clearButton.frame = CGRect(x: 0, y: 0, width: 15, height: 15)
clearButton.contentMode = .scaleAspectFit
clearButton.addTarget(self, action: #selector(self.clear(sender:)), for: .touchUpInside)
self.rightView = clearButton
self.rightViewMode = .always
}
func clear(sender: AnyObject) {
self.text = ""
}
}
override func viewDidLoad() {
super.viewDidLoad()
let clearImage = UIImage(named: "ic_close_white_48pt")!
self.firstWordTextField.clearButtonWithImage(clearImage)
}
Moving Clear Button
override func rightViewRect(forBounds bounds: CGRect) -> CGRect {
var rightViewRect = super.rightViewRect(forBounds: bounds)
rightViewRect.origin.x -= 10;
return rightViewRect
}
import UIKit
import UIKit
@IBDesignable
class CustomTextField: UITextField {
@IBInspectable
var borderWidth: CGFloat {
get {
return self.layer.borderWidth
}
set {
self.layer.borderWidth = newValue
}
}
@IBInspectable
var borderColor: UIColor? {
get {
return UIColor(cgColor: self.layer.borderColor!)
}
set {
self.layer.borderColor = newValue?.cgColor
}
}
@IBInspectable
var cornerRadius: CGFloat {
set {
self.layer.cornerRadius = newValue
}
get {
return self.layer.cornerRadius
}
}
override func rightViewRect(forBounds bounds: CGRect) -> CGRect {
var rightViewRect = super.rightViewRect(forBounds: bounds)
rightViewRect.origin.x -= 10;
return rightViewRect
}
}
Add Color to Clear Button
import Foundation
import UIKit
extension UITextField {
func clearButtonWithImage(_ image: UIImage,
_ imageColor: UIColor = UIColor.white,
_ isAlwaysVisible: Bool = true) {
let clearButton = UIButton()
clearButton.tintColor = imageColor
let coloredImage = image.withRenderingMode(.alwaysTemplate)
clearButton.setImage(coloredImage, for: .normal)
clearButton.frame = CGRect(x: 0, y: 0, width: 15, height: 15)
clearButton.contentMode = .scaleAspectFit
clearButton.addTarget(self, action: #selector(self.clear(sender:)), for: .touchUpInside)
self.rightView = clearButton
self.rightViewMode = isAlwaysVisible ? .always : .never
}
func clear(sender: AnyObject) {
self.text = ""
}
}
Create two clear buttons with default color and with custom color
override func viewDidLoad() {
super.viewDidLoad()
let clearImage = UIImage(named: "ic_close_white_48pt")!
self.firstWordTextField.clearButtonWithImage(clearImage)
self.secondWordTextField.clearButtonWithImage(clearImage, UIColor.red)
}
Send Local Notification when tapped on clear button
import Foundation
import UIKit
extension UITextField {
func clearButtonWithImage(_ image: UIImage,
_ imageColor: UIColor = UIColor.white,
_ isAlwaysVisible: Bool = true) {
let clearButton = UIButton()
clearButton.tintColor = imageColor
let coloredImage = image.withRenderingMode(.alwaysTemplate)
clearButton.setImage(coloredImage, for: .normal)
clearButton.frame = CGRect(x: 0, y: 0, width: 15, height: 15)
clearButton.contentMode = .scaleAspectFit
clearButton.addTarget(self, action: #selector(self.clear(sender:)), for: .touchUpInside)
self.rightView = clearButton
self.rightViewMode = isAlwaysVisible ? .always : .never
}
func clear(sender: AnyObject) {
self.text = ""
NotificationCenter.default.post(
name: Notification.Name("TextFieldCleared"), object: nil, userInfo: nil)
}
}
override func viewDidLoad() {
super.viewDidLoad()
let clearImage = UIImage(named: "ic_close_white_48pt")!
self.firstWordTextField.clearButtonWithImage(clearImage)
self.secondWordTextField.clearButtonWithImage(clearImage, UIColor.red)
NotificationCenter.default.addObserver(self,
selector: #selector(ViewController.clearSelection),
name: Notification.Name("TextFieldCleared"),
object: nil)
}
Full Code of ViewController
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var firstWordTextField: CustomTextField!
@IBOutlet weak var secondWordTextField: CustomTextField!
@IBOutlet weak var firstButton: UIButton!
@IBOutlet weak var secondButton: UIButton!
var isFirstSelected: Bool = false
var isSecondSelected: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
let clearImage = UIImage(named: "ic_close_white_48pt")!
self.firstWordTextField.clearButtonWithImage(clearImage)
self.secondWordTextField.clearButtonWithImage(clearImage, UIColor.red)
NotificationCenter.default.addObserver(self,
selector: #selector(ViewController.clearSelection),
name: Notification.Name("TextFieldCleared"),
object: nil)
}
@IBAction func firstButtonTapped(_ sender: Any) {
if !self.isFirstSelected {
self.firstWordTextField.text = "Fill First TextField"
self.setFirstButtonSelected(selected: !self.firstButton.isSelected)
}
}
@IBAction func secondButtonTapped(_ sender: Any) {
if !self.isSecondSelected {
self.secondWordTextField.text = "A long time ago"
self.setSecondButtonSelected(selected: !self.secondButton.isSelected)
}
}
func clearSelection() {
if self.isFirstSelected {
if let text = self.firstWordTextField.text {
if text.isEmpty {
self.setFirstButtonSelected(selected: false)
}
}
}
if self.isSecondSelected {
if let text = self.secondWordTextField.text {
if text.isEmpty {
self.setSecondButtonSelected(selected: false)
}
}
}
}
func setFirstButtonSelected(selected: Bool) {
self.isFirstSelected = selected
self.firstButton.isSelected = selected
}
func setSecondButtonSelected(selected: Bool) {
self.isSecondSelected = selected
self.secondButton.isSelected = selected
}
}
Sources