Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7a6cd5efbb | |||
| 7c1d6bc4ae | |||
| 134ea16381 | |||
| fa80dfcc2a | |||
| f60823d275 | |||
| 9623689d46 | |||
| 9b9aed68f2 | |||
| c211f8e075 | |||
| 8582f640fe | |||
| 6a0bafe3e7 | |||
| 03ca046803 | |||
| 16056845e9 |
+1
-1
@@ -9,7 +9,7 @@
|
||||
Pod::Spec.new do |s|
|
||||
|
||||
s.name = 'DTTextField'
|
||||
s.version = '0.2.1'
|
||||
s.version = '0.2.4'
|
||||
s.summary = 'DTTextField is UITextField library.'
|
||||
|
||||
s.description = <<-DESC
|
||||
|
||||
@@ -10,7 +10,7 @@ import Foundation
|
||||
import UIKit
|
||||
|
||||
public extension String {
|
||||
|
||||
|
||||
var isEmptyStr:Bool{
|
||||
return self.trimmingCharacters(in: NSCharacterSet.whitespaces).isEmpty
|
||||
}
|
||||
@@ -18,17 +18,24 @@ public extension String {
|
||||
|
||||
public class DTTextField: UITextField {
|
||||
|
||||
fileprivate var lblFloatPlaceholder:UILabel = UILabel()
|
||||
fileprivate var lblError:UILabel = UILabel()
|
||||
public enum FloatingDisplayStatus{
|
||||
case always
|
||||
case never
|
||||
case defaults
|
||||
}
|
||||
|
||||
fileprivate var lblFloatPlaceholder:UILabel = UILabel()
|
||||
fileprivate var lblError:UILabel = UILabel()
|
||||
|
||||
fileprivate let paddingX:CGFloat = 5.0
|
||||
fileprivate let floatingLabelShowAnimationDuration = 0.3
|
||||
|
||||
fileprivate let paddingHeight:CGFloat = 10.0
|
||||
|
||||
public var dtLayer:CALayer = CALayer()
|
||||
public var floatPlaceholderColor:UIColor = UIColor.black
|
||||
public var floatPlaceholderActiveColor:UIColor = UIColor.black
|
||||
|
||||
public var dtLayer:CALayer = CALayer()
|
||||
public var floatPlaceholderColor:UIColor = UIColor.black
|
||||
public var floatPlaceholderActiveColor:UIColor = UIColor.black
|
||||
public var floatingLabelShowAnimationDuration = 0.3
|
||||
public var floatingDisplayStatus:FloatingDisplayStatus = .defaults
|
||||
|
||||
public var errorMessage:String = ""{
|
||||
didSet{ lblError.text = errorMessage }
|
||||
@@ -78,6 +85,14 @@ public class DTTextField: UITextField {
|
||||
return paddingX
|
||||
}
|
||||
|
||||
fileprivate var fontHeight:CGFloat{
|
||||
return ceil(font!.lineHeight)
|
||||
}
|
||||
|
||||
fileprivate var dtLayerHeight:CGFloat{
|
||||
return showErrorLabel ? floor(bounds.height - lblError.bounds.size.height - paddingYErrorLabel) : bounds.height
|
||||
}
|
||||
|
||||
fileprivate var floatLabelWidth:CGFloat{
|
||||
|
||||
var width = bounds.size.width
|
||||
@@ -100,12 +115,12 @@ public class DTTextField: UITextField {
|
||||
|
||||
fileprivate var isFloatLabelShowing:Bool = false
|
||||
|
||||
public var showError:Bool = false{
|
||||
fileprivate var showErrorLabel:Bool = false{
|
||||
didSet{
|
||||
|
||||
guard showError != oldValue else { return }
|
||||
guard showErrorLabel != oldValue else { return }
|
||||
|
||||
guard showError else {
|
||||
guard showErrorLabel else {
|
||||
hideErrorMessage()
|
||||
return
|
||||
}
|
||||
@@ -152,6 +167,15 @@ public class DTTextField: UITextField {
|
||||
commonInit()
|
||||
}
|
||||
|
||||
public func showError(message:String? = nil) {
|
||||
if let msg = message { errorMessage = msg }
|
||||
showErrorLabel = true
|
||||
}
|
||||
|
||||
public func hideError() {
|
||||
showErrorLabel = false
|
||||
}
|
||||
|
||||
fileprivate func commonInit() {
|
||||
|
||||
dtLayer.cornerRadius = 4.5
|
||||
@@ -202,7 +226,10 @@ public class DTTextField: UITextField {
|
||||
|
||||
let animations:(()->()) = {
|
||||
self.lblFloatPlaceholder.alpha = 1.0
|
||||
self.lblFloatPlaceholder.frame = CGRect(x: self.lblFloatPlaceholder.frame.origin.x, y: self.paddingYFloatLabel, width: self.lblFloatPlaceholder.bounds.size.width, height: self.lblFloatPlaceholder.bounds.size.height)
|
||||
self.lblFloatPlaceholder.frame = CGRect(x: self.lblFloatPlaceholder.frame.origin.x,
|
||||
y: self.paddingYFloatLabel,
|
||||
width: self.lblFloatPlaceholder.bounds.size.width,
|
||||
height: self.lblFloatPlaceholder.bounds.size.height)
|
||||
}
|
||||
|
||||
if animated && animateFloatPlaceholder {
|
||||
@@ -223,7 +250,10 @@ public class DTTextField: UITextField {
|
||||
|
||||
let animations:(()->()) = {
|
||||
self.lblFloatPlaceholder.alpha = 0.0
|
||||
self.lblFloatPlaceholder.frame = CGRect(x: self.lblFloatPlaceholder.frame.origin.x, y: self.lblFloatPlaceholder.font.lineHeight, width: self.lblFloatPlaceholder.bounds.size.width, height: self.lblFloatPlaceholder.bounds.size.height)
|
||||
self.lblFloatPlaceholder.frame = CGRect(x: self.lblFloatPlaceholder.frame.origin.x,
|
||||
y: self.lblFloatPlaceholder.font.lineHeight,
|
||||
width: self.lblFloatPlaceholder.bounds.size.width,
|
||||
height: self.lblFloatPlaceholder.bounds.size.height)
|
||||
}
|
||||
|
||||
if animated && animateFloatPlaceholder {
|
||||
@@ -242,29 +272,39 @@ public class DTTextField: UITextField {
|
||||
|
||||
fileprivate func insetRectForEmptyBounds(rect:CGRect) -> CGRect{
|
||||
|
||||
guard showError else { return CGRect(x: x, y: 0, width: rect.width, height: rect.height) }
|
||||
guard showErrorLabel else { return CGRect(x: x, y: 0, width: rect.width - paddingX, height: rect.height) }
|
||||
|
||||
let topInset = (rect.size.height - lblError.bounds.size.height - paddingYErrorLabel - ceil(font!.lineHeight)) / 2.0
|
||||
let textY = ((rect.height - ceil(font!.lineHeight)) / 2.0) - topInset
|
||||
return CGRect(x: x, y: -ceil(textY), width: rect.size.width, height: rect.size.height)
|
||||
let topInset = (rect.size.height - lblError.bounds.size.height - paddingYErrorLabel - fontHeight) / 2.0
|
||||
let textY = topInset - ((rect.height - fontHeight) / 2.0)
|
||||
|
||||
return CGRect(x: x, y: floor(textY), width: rect.size.width - paddingX, height: rect.size.height)
|
||||
}
|
||||
|
||||
fileprivate func insetRectForBounds(rect:CGRect) -> CGRect {
|
||||
|
||||
guard !lblFloatPlaceholder.text!.isEmptyStr else { return insetRectForEmptyBounds(rect: rect) }
|
||||
|
||||
if let text = text,text.isEmptyStr {
|
||||
if floatingDisplayStatus == .never {
|
||||
return insetRectForEmptyBounds(rect: rect)
|
||||
}else{
|
||||
let topInset = paddingYFloatLabel + lblFloatPlaceholder.bounds.size.height + (paddingHeight / 2.0)
|
||||
let textOriginalY = (rect.height - font!.lineHeight) / 2.0
|
||||
let textY = textOriginalY - topInset
|
||||
return CGRect(x: x, y: -ceil(textY), width: rect.size.width, height: rect.size.height)
|
||||
|
||||
if let text = text,text.isEmptyStr && floatingDisplayStatus == .defaults {
|
||||
return insetRectForEmptyBounds(rect: rect)
|
||||
}else{
|
||||
let topInset = paddingYFloatLabel + lblFloatPlaceholder.bounds.size.height + (paddingHeight / 2.0)
|
||||
let textOriginalY = (rect.height - fontHeight) / 2.0
|
||||
var textY = topInset - textOriginalY
|
||||
|
||||
if textY < 0 && !showErrorLabel { textY = topInset }
|
||||
|
||||
return CGRect(x: x, y: ceil(textY), width: rect.size.width - paddingX, height: rect.height)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc fileprivate func textFieldTextChanged(){
|
||||
guard hideErrorWhenEditing && showError else { return }
|
||||
showError = false
|
||||
guard hideErrorWhenEditing && showErrorLabel else { return }
|
||||
showErrorLabel = false
|
||||
}
|
||||
|
||||
override public var intrinsicContentSize: CGSize{
|
||||
@@ -274,7 +314,7 @@ public class DTTextField: UITextField {
|
||||
|
||||
lblError.sizeToFit()
|
||||
|
||||
if showError {
|
||||
if showErrorLabel {
|
||||
lblFloatPlaceholder.sizeToFit()
|
||||
return CGSize(width: textFieldIntrinsicContentSize.width,
|
||||
height: textFieldIntrinsicContentSize.height + paddingYFloatLabel + paddingYErrorLabel + lblFloatPlaceholder.bounds.size.height + lblError.bounds.size.height + paddingHeight)
|
||||
@@ -294,45 +334,45 @@ public class DTTextField: UITextField {
|
||||
return insetRectForBounds(rect: rect)
|
||||
}
|
||||
|
||||
override public func leftViewRect(forBounds bounds: CGRect) -> CGRect {
|
||||
var rect = super.leftViewRect(forBounds: bounds)
|
||||
fileprivate func insetForSideView(forBounds bounds: CGRect) -> CGRect{
|
||||
var rect = bounds
|
||||
rect.origin.y = 0
|
||||
rect.size.height = dtLayer.bounds.height
|
||||
rect.size.height = dtLayerHeight
|
||||
return rect
|
||||
}
|
||||
|
||||
override public func leftViewRect(forBounds bounds: CGRect) -> CGRect {
|
||||
let rect = super.leftViewRect(forBounds: bounds)
|
||||
return insetForSideView(forBounds: rect)
|
||||
}
|
||||
|
||||
override public func rightViewRect(forBounds bounds: CGRect) -> CGRect {
|
||||
var rect = super.rightViewRect(forBounds: bounds)
|
||||
rect.origin.y = 0
|
||||
rect.size.height = dtLayer.bounds.height
|
||||
return rect
|
||||
let rect = super.rightViewRect(forBounds: bounds)
|
||||
return insetForSideView(forBounds: rect)
|
||||
}
|
||||
|
||||
override public func clearButtonRect(forBounds bounds: CGRect) -> CGRect {
|
||||
var rect = super.clearButtonRect(forBounds: bounds)
|
||||
rect.origin.y = (dtLayer.bounds.height / 2) - (rect.size.height / 2)
|
||||
rect.origin.y = (dtLayerHeight - rect.size.height) / 2
|
||||
return rect
|
||||
}
|
||||
|
||||
override public func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
if showError {
|
||||
|
||||
dtLayer.frame = CGRect(x: bounds.origin.x,
|
||||
y: bounds.origin.y,
|
||||
width: bounds.width,
|
||||
height: floor(bounds.height - lblError.bounds.size.height - paddingYErrorLabel))
|
||||
CATransaction.begin()
|
||||
CATransaction.setDisableActions(true)
|
||||
dtLayer.frame = CGRect(x: bounds.origin.x,
|
||||
y: bounds.origin.y,
|
||||
width: bounds.width,
|
||||
height: dtLayerHeight)
|
||||
CATransaction.commit()
|
||||
|
||||
if showErrorLabel {
|
||||
|
||||
var lblErrorFrame = lblError.frame
|
||||
lblErrorFrame.origin.y = dtLayer.frame.origin.y + dtLayer.frame.size.height + paddingYErrorLabel
|
||||
lblError.frame = lblErrorFrame
|
||||
|
||||
}else{
|
||||
dtLayer.frame = CGRect(x: bounds.origin.x,
|
||||
y: bounds.origin.y,
|
||||
width: bounds.width,
|
||||
height: bounds.height)
|
||||
}
|
||||
|
||||
let floatingLabelSize = lblFloatPlaceholder.sizeThatFits(lblFloatPlaceholder.superview!.bounds.size)
|
||||
@@ -343,10 +383,17 @@ public class DTTextField: UITextField {
|
||||
|
||||
lblFloatPlaceholder.textColor = isFirstResponder ? floatPlaceholderActiveColor : floatPlaceholderColor
|
||||
|
||||
if let enteredText = text,!enteredText.isEmptyStr{
|
||||
showFloatingLabel(isFirstResponder)
|
||||
}else{
|
||||
switch floatingDisplayStatus {
|
||||
case .never:
|
||||
hideFlotingLabel(isFirstResponder)
|
||||
case .always:
|
||||
showFloatingLabel(isFirstResponder)
|
||||
default:
|
||||
if let enteredText = text,!enteredText.isEmptyStr{
|
||||
showFloatingLabel(isFirstResponder)
|
||||
}else{
|
||||
hideFlotingLabel(isFirstResponder)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,13 +28,7 @@ class ViewController: UIViewController {
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
title = "Registration"
|
||||
txtFirstName.errorMessage = firstNameMessage
|
||||
txtLastName.errorMessage = lastNameMessage
|
||||
txtEmail.errorMessage = emailMessage
|
||||
txtPassword.errorMessage = passwordMessage
|
||||
txtConfirmPassword.errorMessage = confirmPasswordMessage
|
||||
|
||||
title = "Registration"
|
||||
// Do any additional setup after loading the view, typically from a nib.
|
||||
}
|
||||
|
||||
@@ -93,34 +87,32 @@ extension ViewController{
|
||||
func validateData() -> Bool {
|
||||
|
||||
guard !txtFirstName.text!.isEmptyStr else {
|
||||
txtFirstName.showError = true
|
||||
txtFirstName.showError(message: firstNameMessage)
|
||||
return false
|
||||
}
|
||||
|
||||
guard !txtLastName.text!.isEmptyStr else {
|
||||
txtLastName.showError = true
|
||||
txtLastName.showError(message: lastNameMessage)
|
||||
return false
|
||||
}
|
||||
|
||||
guard !txtEmail.text!.isEmptyStr else {
|
||||
txtEmail.showError = true
|
||||
txtEmail.showError(message: emailMessage)
|
||||
return false
|
||||
}
|
||||
|
||||
guard !txtPassword.text!.isEmptyStr else {
|
||||
txtPassword.showError = true
|
||||
txtPassword.showError(message: passwordMessage)
|
||||
return false
|
||||
}
|
||||
|
||||
guard !txtConfirmPassword.text!.isEmptyStr else {
|
||||
txtConfirmPassword.errorMessage = confirmPasswordMessage
|
||||
txtConfirmPassword.showError = true
|
||||
txtConfirmPassword.showError(message: confirmPasswordMessage)
|
||||
return false
|
||||
}
|
||||
|
||||
guard txtPassword.text == txtConfirmPassword.text else {
|
||||
txtConfirmPassword.errorMessage = mismatchPasswordMessage
|
||||
txtConfirmPassword.showError = true
|
||||
txtConfirmPassword.showError(message: mismatchPasswordMessage)
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# DTTextField
|
||||
|
||||

|
||||

|
||||

|
||||
[](https://github.com/iDhaval/DTTextField/releases/tag/0.2.4)
|
||||
[](https://github.com/iDhaval/DTTextField/blob/master/LICENSE)
|
||||
[](https://github.com/matteocrippa/awesome-swift)
|
||||
[](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/)
|
||||

|
||||
|
||||

|
||||
@@ -43,24 +44,31 @@ pod 'DTTextField'
|
||||
| ------------- |------------- | ----- |
|
||||
| errorMessage | String | Add your error message to this property|
|
||||
| errorFont | UIFont | Change font of error text |
|
||||
| showError | Bool | Use to toggle error message|
|
||||
| paddingYErrorLabel | CGFloat | Error text top padding |
|
||||
| floatPlaceholderColor | UIColor | To change float placeholder color |
|
||||
| floatPlaceholderActiveColor | UIColor | To change float placeholder color while TextField is active(First responder)|
|
||||
| floatPlaceholderFont | UIFont | Change font of float placeholder |
|
||||
| paddingYFloatLabel | CGFloat | float placeholder top padding |
|
||||
| placeholderColor | UIColor | change placeholder color |
|
||||
|
||||
| animateFloatPlaceholder | Bool | animate float placeholder label |
|
||||
| hideErrorWhenEditing | Bool | hide error label when typing |
|
||||
| floatingDisplayStatus | enum | maintain display status always, never, defaults |
|
||||
|
||||
### Important Properties
|
||||
|
||||
|
||||
| Property name | Type | Remark |
|
||||
| ------------- |------------- | ----- |
|
||||
| dtLayer | CALayer | If you want to formate DTTextField than use dtLayer property instead of layer |
|
||||
| borderColor | UIColor | Change border color of DTTextField |
|
||||
| canShowBorder | Bool | Toggle border of DTTextField |
|
||||
|
||||
## Methods
|
||||
|
||||
| Method Name | Remark |
|
||||
| ------------|--------|
|
||||
| showError | to show error message |
|
||||
| hideError | to hide error message |
|
||||
|
||||
## TODO
|
||||
* Add inbuilt validation
|
||||
|
||||
|
||||
Reference in New Issue
Block a user