From e75d699d0f157c83f8d7efd860385666548a8a15 Mon Sep 17 00:00:00 2001 From: Patrick Date: Tue, 5 Jan 2016 15:52:10 +0100 Subject: [PATCH 01/29] fix, add IBInspectable var to configure from IB, fix default floating option true --- .../EGFloatingTextField.swift | 144 +++++++++--------- 1 file changed, 75 insertions(+), 69 deletions(-) diff --git a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift index 5230d6c..605dd7a 100644 --- a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift +++ b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift @@ -9,32 +9,51 @@ import UIKit import Foundation import PureLayout - public enum EGFloatingTextFieldValidationType { case Email case Number } +@IBDesignable public class EGFloatingTextField: UITextField { - private typealias EGFloatingTextFieldValidationBlock = ((text:String,inout message:String)-> Bool)! public var validationType : EGFloatingTextFieldValidationType! + @IBInspectable var validator: String!{ + didSet{ + switch validator{ + case "@": + self.validationType = EGFloatingTextFieldValidationType.Email + break + case "0": + self.validationType = EGFloatingTextFieldValidationType.Number + break + default: + break + } + } + } + + @IBInspectable public var IBPlaceholder: String?{ + didSet{ + if (IBPlaceholder != nil) { + setPlaceHolder(IBPlaceholder!) + } + } + } private var emailValidationBlock : EGFloatingTextFieldValidationBlock private var numberValidationBlock : EGFloatingTextFieldValidationBlock - let kDefaultInactiveColor = UIColor(white: CGFloat(0), alpha: CGFloat(0.54)) let kDefaultActiveColor = UIColor.blueColor() let kDefaultErrorColor = UIColor.redColor() let kDefaultLineHeight = CGFloat(22) let kDefaultLabelTextColor = UIColor(white: CGFloat(0), alpha: CGFloat(0.54)) - - public var floatingLabel : Bool! + public var floatingLabel : Bool! = true var label : UILabel! var labelFont : UIFont! var labelTextColor : UIColor! @@ -44,14 +63,11 @@ public class EGFloatingTextField: UITextField { var hasError : Bool! var errorMessage : String! - - required public init(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) + super.init(coder: aDecoder)! self.commonInit() } - override public init(frame: CGRect) { super.init(frame: frame) self.commonInit() @@ -60,21 +76,21 @@ public class EGFloatingTextField: UITextField { func commonInit(){ self.emailValidationBlock = ({(text:String, inout message: String) -> Bool in - var emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}" + let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}" - var emailTest = NSPredicate(format:"SELF MATCHES %@" , emailRegex) + let emailTest = NSPredicate(format:"SELF MATCHES %@" , emailRegex) - var isValid = emailTest.evaluateWithObject(text) + let isValid = emailTest.evaluateWithObject(text) if !isValid { message = "Invalid Email Address" } return isValid; }) self.numberValidationBlock = ({(text:String,inout message: String) -> Bool in - var numRegex = "[0-9.+-]+"; - var numTest = NSPredicate(format:"SELF MATCHES %@" , numRegex) + let numRegex = "[0-9.+-]+"; + let numTest = NSPredicate(format:"SELF MATCHES %@" , numRegex) - var isValid = numTest.evaluateWithObject(text) + let isValid = numTest.evaluateWithObject(text) if !isValid { message = "Invalid Number" } @@ -111,66 +127,56 @@ public class EGFloatingTextField: UITextField { NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("textDidChange:"), name: "UITextFieldTextDidChangeNotification", object: self) } + public func setPlaceHolder(placeholder:String){ self.label.text = placeholder } override public func becomeFirstResponder() -> Bool { - var flag:Bool = super.becomeFirstResponder() - - if flag { + if self.floatingLabel! { - if self.floatingLabel! { - - if !self.floating! || self.text!.isEmpty { - self.floatLabelToTop() - self.floating = true - } - } else { - self.label.textColor = kDefaultActiveColor - self.label.layer.opacity = 0 + if !self.floating! || self.text!.isEmpty { + self.floatLabelToTop() + self.floating = true } - self.showActiveBorder() + } else { + self.label.textColor = kDefaultActiveColor + self.label.layer.opacity = 0 } - - self.active=flag - return flag + self.showActiveBorder() + return super.becomeFirstResponder() } + override public func resignFirstResponder() -> Bool { - var flag:Bool = super.becomeFirstResponder() - if flag { + if self.floatingLabel! { - if self.floatingLabel! { - - if self.floating! && self.text!.isEmpty { - self.animateLabelBack() - self.floating = false - } - } else { - if self.text!.isEmpty { - self.label.layer.opacity = 1 - } + if self.floating! && self.text!.isEmpty { + self.animateLabelBack() + self.floating = false + } + } else { + if self.text!.isEmpty { + self.label.layer.opacity = 1 } - self.label.textColor = kDefaultInactiveColor - self.showInactiveBorder() - self.validate() } - self.active = flag - return flag + self.label.textColor = kDefaultInactiveColor + self.showInactiveBorder() + self.validate() + return super.resignFirstResponder() } override public func drawRect(rect: CGRect){ super.drawRect(rect) - var borderColor = self.hasError! ? kDefaultErrorColor : kDefaultInactiveColor + let borderColor = self.hasError! ? kDefaultErrorColor : kDefaultInactiveColor - var textRect = self.textRectForBounds(rect) - var context = UIGraphicsGetCurrentContext() - var borderlines : [CGPoint] = [CGPointMake(0, CGRectGetHeight(textRect) - 1), + let textRect = self.textRectForBounds(rect) + let context = UIGraphicsGetCurrentContext() + let borderlines : [CGPoint] = [CGPointMake(0, CGRectGetHeight(textRect) - 1), CGPointMake(CGRectGetWidth(textRect), CGRectGetHeight(textRect) - 1)] if self.enabled { @@ -186,7 +192,7 @@ public class EGFloatingTextField: UITextField { CGContextBeginPath(context); CGContextAddLines(context, borderlines, 2); CGContextSetLineWidth(context, 1.0); - var dashPattern : [CGFloat] = [2, 4] + let dashPattern : [CGFloat] = [2, 4] CGContextSetLineDash(context, 0, dashPattern, 2); CGContextSetStrokeColorWithColor(context, borderColor.CGColor); CGContextStrokePath(context); @@ -205,14 +211,14 @@ public class EGFloatingTextField: UITextField { self.label.textColor = self.kDefaultActiveColor } - var anim2 = CABasicAnimation(keyPath: "transform") - var fromTransform = CATransform3DMakeScale(CGFloat(1.0), CGFloat(1.0), CGFloat(1)) + let anim2 = CABasicAnimation(keyPath: "transform") + let fromTransform = CATransform3DMakeScale(CGFloat(1.0), CGFloat(1.0), CGFloat(1)) var toTransform = CATransform3DMakeScale(CGFloat(0.5), CGFloat(0.5), CGFloat(1)) toTransform = CATransform3DTranslate(toTransform, -CGRectGetWidth(self.label.frame)/2, -CGRectGetHeight(self.label.frame), 0) anim2.fromValue = NSValue(CATransform3D: fromTransform) anim2.toValue = NSValue(CATransform3D: toTransform) anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) - var animGroup = CAAnimationGroup() + let animGroup = CAAnimationGroup() animGroup.animations = [anim2] animGroup.duration = 0.3 animGroup.fillMode = kCAFillModeForwards; @@ -221,15 +227,16 @@ public class EGFloatingTextField: UITextField { self.clipsToBounds = false CATransaction.commit() } + func showActiveBorder() { self.activeBorder.layer.transform = CATransform3DMakeScale(CGFloat(0.01), CGFloat(1.0), 1) self.activeBorder.layer.opacity = 1 CATransaction.begin() self.activeBorder.layer.transform = CATransform3DMakeScale(CGFloat(0.01), CGFloat(1.0), 1) - var anim2 = CABasicAnimation(keyPath: "transform") - var fromTransform = CATransform3DMakeScale(CGFloat(0.01), CGFloat(1.0), 1) - var toTransform = CATransform3DMakeScale(CGFloat(1.0), CGFloat(1.0), 1) + let anim2 = CABasicAnimation(keyPath: "transform") + let fromTransform = CATransform3DMakeScale(CGFloat(0.01), CGFloat(1.0), 1) + let toTransform = CATransform3DMakeScale(CGFloat(1.0), CGFloat(1.0), 1) anim2.fromValue = NSValue(CATransform3D: fromTransform) anim2.toValue = NSValue(CATransform3D: toTransform) anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) @@ -245,15 +252,15 @@ public class EGFloatingTextField: UITextField { self.label.textColor = self.kDefaultInactiveColor } - var anim2 = CABasicAnimation(keyPath: "transform") + let anim2 = CABasicAnimation(keyPath: "transform") var fromTransform = CATransform3DMakeScale(0.5, 0.5, 1) fromTransform = CATransform3DTranslate(fromTransform, -CGRectGetWidth(self.label.frame)/2, -CGRectGetHeight(self.label.frame), 0); - var toTransform = CATransform3DMakeScale(1.0, 1.0, 1) + let toTransform = CATransform3DMakeScale(1.0, 1.0, 1) anim2.fromValue = NSValue(CATransform3D: fromTransform) anim2.toValue = NSValue(CATransform3D: toTransform) anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) - var animGroup = CAAnimationGroup() + let animGroup = CAAnimationGroup() animGroup.animations = [anim2] animGroup.duration = 0.3 animGroup.fillMode = kCAFillModeForwards; @@ -262,15 +269,16 @@ public class EGFloatingTextField: UITextField { self.label.layer.addAnimation(animGroup, forKey: "_animateLabelBack") CATransaction.commit() } + func showInactiveBorder() { CATransaction.begin() CATransaction.setCompletionBlock { () -> Void in self.activeBorder.layer.opacity = 0 } - var anim2 = CABasicAnimation(keyPath: "transform") - var fromTransform = CATransform3DMakeScale(1.0, 1.0, 1) - var toTransform = CATransform3DMakeScale(0.01, 1.0, 1) + let anim2 = CABasicAnimation(keyPath: "transform") + let fromTransform = CATransform3DMakeScale(1.0, 1.0, 1) + let toTransform = CATransform3DMakeScale(0.01, 1.0, 1) anim2.fromValue = NSValue(CATransform3D: fromTransform) anim2.toValue = NSValue(CATransform3D: toTransform) anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) @@ -303,19 +311,17 @@ public class EGFloatingTextField: UITextField { if self.validationType! == .Email { - var isValid = self.emailValidationBlock(text: self.text, message: &message) + let isValid = self.emailValidationBlock(text: self.text!, message: &message) performValidation(isValid,message: message) } else { - var isValid = self.numberValidationBlock(text: self.text, message: &message) + let isValid = self.numberValidationBlock(text: self.text!, message: &message) performValidation(isValid,message: message) } } } - - } extension EGFloatingTextField { From e922217b6ee1bb9f1cecfc34c2013d3fda78f6f8 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 13 Jan 2016 11:00:27 +0100 Subject: [PATCH 02/29] fix --- .../EGFloatingTextField/EGFloatingTextField.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift index 605dd7a..aa8207c 100644 --- a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift +++ b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift @@ -99,7 +99,7 @@ public class EGFloatingTextField: UITextField { }) self.floating = false self.hasError = false - + self.textColor = UIColor.whiteColor() self.labelTextColor = kDefaultLabelTextColor self.label = UILabel(frame: CGRectZero) self.label.font = self.labelFont @@ -111,8 +111,8 @@ public class EGFloatingTextField: UITextField { self.activeBorder = UIView(frame: CGRectZero) - self.activeBorder.backgroundColor = kDefaultActiveColor - self.activeBorder.layer.opacity = 0 + self.activeBorder.backgroundColor = UIColor.whiteColor() + self.activeBorder.layer.opacity = 0.5 self.addSubview(self.activeBorder) self.label.autoAlignAxis(ALAxis.Horizontal, toSameAxisOfView: self) @@ -274,11 +274,11 @@ public class EGFloatingTextField: UITextField { CATransaction.begin() CATransaction.setCompletionBlock { () -> Void in - self.activeBorder.layer.opacity = 0 + self.activeBorder.layer.opacity = 0.5 } let anim2 = CABasicAnimation(keyPath: "transform") let fromTransform = CATransform3DMakeScale(1.0, 1.0, 1) - let toTransform = CATransform3DMakeScale(0.01, 1.0, 1) + let toTransform = CATransform3DMakeScale(1.0, 1.0, 1) anim2.fromValue = NSValue(CATransform3D: fromTransform) anim2.toValue = NSValue(CATransform3D: toTransform) anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) From 118a887958f05782517ded175e3823e626ba5d28 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 27 Jan 2016 10:37:38 +0100 Subject: [PATCH 03/29] add default text public func --- EGFloatingTextField.podspec | 2 +- .../project.pbxproj | 3 +++ .../EGFloatingTextField.swift | 21 ++++++++++++++----- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/EGFloatingTextField.podspec b/EGFloatingTextField.podspec index 60c2e70..e54ce7f 100644 --- a/EGFloatingTextField.podspec +++ b/EGFloatingTextField.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "EGFloatingTextField" - s.version = "0.0.1" + s.version = "1.0.0" s.summary = "Implementation of Google's 'Floating labels' of Material design." s.homepage = "https://github.com/enisgayretli/EGFloatingTextField" s.license = 'MIT' diff --git a/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj b/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj index 896e4c9..7191a4c 100644 --- a/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj +++ b/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj @@ -309,6 +309,7 @@ B7CBFB1F1B769D1700CDE475 /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0640; TargetAttributes = { B77E397B1B778E880078ABA3 = { @@ -714,6 +715,7 @@ B77E399A1B778E880078ABA3 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; B77E399B1B778E880078ABA3 /* Build configuration list for PBXNativeTarget "ExampleTests" */ = { isa = XCConfigurationList; @@ -722,6 +724,7 @@ B77E399D1B778E880078ABA3 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; B7CBFB221B769D1700CDE475 /* Build configuration list for PBXProject "EGFloatingTextField" */ = { isa = XCConfigurationList; diff --git a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift index aa8207c..ed388db 100644 --- a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift +++ b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift @@ -15,6 +15,7 @@ public enum EGFloatingTextFieldValidationType { } @IBDesignable + public class EGFloatingTextField: UITextField { private typealias EGFloatingTextFieldValidationBlock = ((text:String,inout message:String)-> Bool)! @@ -99,7 +100,7 @@ public class EGFloatingTextField: UITextField { }) self.floating = false self.hasError = false - self.textColor = UIColor.whiteColor() + self.labelTextColor = kDefaultLabelTextColor self.label = UILabel(frame: CGRectZero) self.label.font = self.labelFont @@ -111,8 +112,8 @@ public class EGFloatingTextField: UITextField { self.activeBorder = UIView(frame: CGRectZero) - self.activeBorder.backgroundColor = UIColor.whiteColor() - self.activeBorder.layer.opacity = 0.5 + self.activeBorder.backgroundColor = kDefaultActiveColor + self.activeBorder.layer.opacity = 0 self.addSubview(self.activeBorder) self.label.autoAlignAxis(ALAxis.Horizontal, toSameAxisOfView: self) @@ -204,6 +205,16 @@ public class EGFloatingTextField: UITextField { self.validate() } + public func setDefaultText(string: String){ + text = string + floatLabelToTop() + floating = true + showInactiveBorder() + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.5 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in + self.label.textColor = self.kDefaultInactiveColor + } + } + func floatLabelToTop() { CATransaction.begin() @@ -274,11 +285,11 @@ public class EGFloatingTextField: UITextField { CATransaction.begin() CATransaction.setCompletionBlock { () -> Void in - self.activeBorder.layer.opacity = 0.5 + self.activeBorder.layer.opacity = 0 } let anim2 = CABasicAnimation(keyPath: "transform") let fromTransform = CATransform3DMakeScale(1.0, 1.0, 1) - let toTransform = CATransform3DMakeScale(1.0, 1.0, 1) + let toTransform = CATransform3DMakeScale(0.01, 1.0, 1) anim2.fromValue = NSValue(CATransform3D: fromTransform) anim2.toValue = NSValue(CATransform3D: toTransform) anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) From 173043b34ffed12bf6ce9775227c38af9e805c8c Mon Sep 17 00:00:00 2001 From: Patrick Date: Thu, 24 Mar 2016 11:13:04 +0100 Subject: [PATCH 04/29] fix border color on vibrancy --- .../EGFloatingTextField/EGFloatingTextField.swift | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift index ed388db..3215b47 100644 --- a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift +++ b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift @@ -173,8 +173,18 @@ public class EGFloatingTextField: UITextField { override public func drawRect(rect: CGRect){ super.drawRect(rect) - let borderColor = self.hasError! ? kDefaultErrorColor : kDefaultInactiveColor - + var borderColor = self.hasError! ? kDefaultErrorColor : kDefaultInactiveColor + var sView: UIView? = superview + while sView != nil { + if let effectView = sView as? UIVisualEffectView{ + if effectView.effect is UIVibrancyEffect { + borderColor = UIColor.whiteColor() + } + break + }else{ + sView = sView!.superview + } + } let textRect = self.textRectForBounds(rect) let context = UIGraphicsGetCurrentContext() let borderlines : [CGPoint] = [CGPointMake(0, CGRectGetHeight(textRect) - 1), From 8416555d00b1ff9b5a8aabe27ce3f6a9b3056f22 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 20 Jul 2016 13:02:38 +0200 Subject: [PATCH 05/29] Merge remote-tracking branch 'enisgayretli/master' # Conflicts: # EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift --- .../EGFloatingTextField/EGFloatingTextField.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift index 3215b47..077d1a8 100644 --- a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift +++ b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift @@ -151,6 +151,7 @@ public class EGFloatingTextField: UITextField { override public func resignFirstResponder() -> Bool { + var flag:Bool = super.resignFirstResponder() if self.floatingLabel! { From 928173cc768f7ba36cc2b9718525031df832472d Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 20 Jul 2016 13:03:26 +0200 Subject: [PATCH 06/29] fix --- .../EGFloatingTextField/EGFloatingTextField.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift index 077d1a8..f0b4b5b 100644 --- a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift +++ b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift @@ -151,8 +151,6 @@ public class EGFloatingTextField: UITextField { override public func resignFirstResponder() -> Bool { - var flag:Bool = super.resignFirstResponder() - if self.floatingLabel! { if self.floating! && self.text!.isEmpty { @@ -189,7 +187,7 @@ public class EGFloatingTextField: UITextField { let textRect = self.textRectForBounds(rect) let context = UIGraphicsGetCurrentContext() let borderlines : [CGPoint] = [CGPointMake(0, CGRectGetHeight(textRect) - 1), - CGPointMake(CGRectGetWidth(textRect), CGRectGetHeight(textRect) - 1)] + CGPointMake(CGRectGetWidth(textRect), CGRectGetHeight(textRect) - 1)] if self.enabled { From 23b9f280767b2c7a009b6d0d6ad1442775fdb4ea Mon Sep 17 00:00:00 2001 From: Patrick Date: Thu, 11 Aug 2016 11:57:30 +0200 Subject: [PATCH 07/29] fix regex for number --- .../EGFloatingTextField/EGFloatingTextField.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift index f0b4b5b..81e820c 100644 --- a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift +++ b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift @@ -88,7 +88,7 @@ public class EGFloatingTextField: UITextField { return isValid; }) self.numberValidationBlock = ({(text:String,inout message: String) -> Bool in - let numRegex = "[0-9.+-]+"; + let numRegex = "^[+-]?[0-9]+([,|.]+[0-9]+|)$" let numTest = NSPredicate(format:"SELF MATCHES %@" , numRegex) let isValid = numTest.evaluateWithObject(text) From d11454c803cf1b1adf80aacee386d6b0d33c3a56 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 24 Aug 2016 11:38:53 +0200 Subject: [PATCH 08/29] added type and fix validation blocks --- EGFloatingTextField.podspec | 4 +- .../EGFloatingTextField.swift | 142 ++++++++++++------ 2 files changed, 96 insertions(+), 50 deletions(-) diff --git a/EGFloatingTextField.podspec b/EGFloatingTextField.podspec index e54ce7f..51662ce 100644 --- a/EGFloatingTextField.podspec +++ b/EGFloatingTextField.podspec @@ -1,11 +1,11 @@ Pod::Spec.new do |s| s.name = "EGFloatingTextField" - s.version = "1.0.0" + s.version = "2.0.0" s.summary = "Implementation of Google's 'Floating labels' of Material design." s.homepage = "https://github.com/enisgayretli/EGFloatingTextField" s.license = 'MIT' s.author = { "Enis Gayretli" => "enisgayretli@gmail.com" } - s.source = { :git => "https://github.com/enisgayretli/EGFloatingTextField.git", :tag => s.version.to_s } + s.source = { :git => "https://github.com/LaserPatrick/EGFloatingTextField.git" } s.social_media_url = 'https://twitter.com/enisgayretli' s.platform = :ios, '8.0' s.requires_arc = true diff --git a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift index 81e820c..bb0fc03 100644 --- a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift +++ b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift @@ -9,9 +9,14 @@ import UIKit import Foundation import PureLayout -public enum EGFloatingTextFieldValidationType { + +public enum EGFloatingTextFieldValidationType: String { + case Default case Email - case Number + case Integer + case Decimal + case PhoneNumber + case WebURL } @IBDesignable @@ -20,23 +25,49 @@ public class EGFloatingTextField: UITextField { private typealias EGFloatingTextFieldValidationBlock = ((text:String,inout message:String)-> Bool)! - public var validationType : EGFloatingTextFieldValidationType! - - @IBInspectable var validator: String!{ + public var validationType : EGFloatingTextFieldValidationType!{ didSet{ - switch validator{ - case "@": - self.validationType = EGFloatingTextFieldValidationType.Email - break - case "0": - self.validationType = EGFloatingTextFieldValidationType.Number - break + if validationType != nil{ + switch validationType! { + case .Email: + keyboardType = .EmailAddress + autocapitalizationType = .None + autocorrectionType = .No + case .Decimal: + keyboardType = .DecimalPad + autocapitalizationType = .None + autocorrectionType = .No + case .Integer: + keyboardType = .NumberPad + autocapitalizationType = .None + autocorrectionType = .No + case .PhoneNumber: + keyboardType = .PhonePad + autocapitalizationType = .None + autocorrectionType = .No + case .WebURL: + keyboardType = .URL + autocapitalizationType = .None + autocorrectionType = .No default: + keyboardType = .Default + autocapitalizationType = .Sentences + autocorrectionType = .Default break + } } } } + @IBInspectable var validationTypeAdapter: String { + get { + return validationType.rawValue + } + set(shapeIndex) { + self.validationType = EGFloatingTextFieldValidationType(rawValue: shapeIndex) ?? .Default + } + } + @IBInspectable public var IBPlaceholder: String?{ didSet{ if (IBPlaceholder != nil) { @@ -46,7 +77,10 @@ public class EGFloatingTextField: UITextField { } private var emailValidationBlock : EGFloatingTextFieldValidationBlock - private var numberValidationBlock : EGFloatingTextFieldValidationBlock + private var integerValidationBlock : EGFloatingTextFieldValidationBlock + private var decimalValidationBlock : EGFloatingTextFieldValidationBlock + private var phoneNumberValidationBlock : EGFloatingTextFieldValidationBlock + private var urlValidationBlock : EGFloatingTextFieldValidationBlock let kDefaultInactiveColor = UIColor(white: CGFloat(0), alpha: CGFloat(0.54)) let kDefaultActiveColor = UIColor.blueColor() @@ -77,27 +111,50 @@ public class EGFloatingTextField: UITextField { func commonInit(){ self.emailValidationBlock = ({(text:String, inout message: String) -> Bool in - let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}" - + let emailRegex = "([A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6})?" let emailTest = NSPredicate(format:"SELF MATCHES %@" , emailRegex) - let isValid = emailTest.evaluateWithObject(text) if !isValid { - message = "Invalid Email Address" + message = "Invalid Email address" } return isValid; }) - self.numberValidationBlock = ({(text:String,inout message: String) -> Bool in - let numRegex = "^[+-]?[0-9]+([,|.]+[0-9]+|)$" + self.integerValidationBlock = ({(text:String,inout message: String) -> Bool in + let numRegex = "^([+-]?[0-9]+)?$" let numTest = NSPredicate(format:"SELF MATCHES %@" , numRegex) - let isValid = numTest.evaluateWithObject(text) if !isValid { - message = "Invalid Number" + message = "Invalid integer number" } return isValid; - }) + self.decimalValidationBlock = ({(text:String,inout message: String) -> Bool in + let numRegex = "^([+-]?[0-9]+([,|.]+[0-9]+|))?$" + let numTest = NSPredicate(format:"SELF MATCHES %@" , numRegex) + let isValid = numTest.evaluateWithObject(text) + if !isValid { + message = "Invalid decimal number" + } + return isValid; + }) + self.phoneNumberValidationBlock = ({(text:String,inout message: String) -> Bool in + let numRegex = "^([+]?[0-9]+)?$" + let numTest = NSPredicate(format:"SELF MATCHES %@" , numRegex) + let isValid = numTest.evaluateWithObject(text) + if !isValid { + message = "Invalid phone number" + } + return isValid; + }) + self.urlValidationBlock = ({(text:String,inout message: String) -> Bool in + let regex = try! NSRegularExpression(pattern: "^(((http|https):\\/\\/)?((\\w)*|([0-9]*)|([-|_])*)+([\\/.|\\/]((\\w)*|([0-9]*)|([-|_])*))+)?$", options: [.CaseInsensitive]) + let isValid = regex.firstMatchInString(text, options:[], range: NSMakeRange(0, (text as! NSString).length)) != nil + if !isValid { + message = "Invalid url" + } + return isValid; + }) + self.floating = false self.hasError = false @@ -110,7 +167,6 @@ public class EGFloatingTextField: UITextField { self.label.layer.masksToBounds = false self.addSubview(self.label) - self.activeBorder = UIView(frame: CGRectZero) self.activeBorder.backgroundColor = kDefaultActiveColor self.activeBorder.layer.opacity = 0 @@ -134,9 +190,7 @@ public class EGFloatingTextField: UITextField { } override public func becomeFirstResponder() -> Bool { - if self.floatingLabel! { - if !self.floating! || self.text!.isEmpty { self.floatLabelToTop() self.floating = true @@ -150,7 +204,6 @@ public class EGFloatingTextField: UITextField { } override public func resignFirstResponder() -> Bool { - if self.floatingLabel! { if self.floating! && self.text!.isEmpty { @@ -166,12 +219,10 @@ public class EGFloatingTextField: UITextField { self.showInactiveBorder() self.validate() return super.resignFirstResponder() - } override public func drawRect(rect: CGRect){ super.drawRect(rect) - var borderColor = self.hasError! ? kDefaultErrorColor : kDefaultInactiveColor var sView: UIView? = superview while sView != nil { @@ -188,17 +239,13 @@ public class EGFloatingTextField: UITextField { let context = UIGraphicsGetCurrentContext() let borderlines : [CGPoint] = [CGPointMake(0, CGRectGetHeight(textRect) - 1), CGPointMake(CGRectGetWidth(textRect), CGRectGetHeight(textRect) - 1)] - if self.enabled { - CGContextBeginPath(context); CGContextAddLines(context, borderlines, 2); CGContextSetLineWidth(context, 1.0); CGContextSetStrokeColorWithColor(context, borderColor.CGColor); CGContextStrokePath(context); - } else { - CGContextBeginPath(context); CGContextAddLines(context, borderlines, 2); CGContextSetLineWidth(context, 1.0); @@ -206,7 +253,6 @@ public class EGFloatingTextField: UITextField { CGContextSetLineDash(context, 0, dashPattern, 2); CGContextSetStrokeColorWithColor(context, borderColor.CGColor); CGContextStrokePath(context); - } } @@ -225,12 +271,10 @@ public class EGFloatingTextField: UITextField { } func floatLabelToTop() { - CATransaction.begin() CATransaction.setCompletionBlock { () -> Void in self.label.textColor = self.kDefaultActiveColor } - let anim2 = CABasicAnimation(keyPath: "transform") let fromTransform = CATransform3DMakeScale(CGFloat(1.0), CGFloat(1.0), CGFloat(1)) var toTransform = CATransform3DMakeScale(CGFloat(0.5), CGFloat(0.5), CGFloat(1)) @@ -249,7 +293,6 @@ public class EGFloatingTextField: UITextField { } func showActiveBorder() { - self.activeBorder.layer.transform = CATransform3DMakeScale(CGFloat(0.01), CGFloat(1.0), 1) self.activeBorder.layer.opacity = 1 CATransaction.begin() @@ -325,25 +368,28 @@ public class EGFloatingTextField: UITextField { } func validate(){ - if self.validationType != nil { var message : String = "" - - if self.validationType! == .Email { - + switch self.validationType!{ + case .Email: let isValid = self.emailValidationBlock(text: self.text!, message: &message) - performValidation(isValid,message: message) - - } else { - let isValid = self.numberValidationBlock(text: self.text!, message: &message) - + case .Integer: + let isValid = self.integerValidationBlock(text: self.text!, message: &message) + performValidation(isValid,message: message) + case .Decimal: + let isValid = self.decimalValidationBlock(text: self.text!, message: &message) performValidation(isValid,message: message) + case .PhoneNumber: + let isValid = self.phoneNumberValidationBlock(text: self.text!, message: &message) + performValidation(isValid,message: message) + case .WebURL: + let isValid = self.urlValidationBlock(text: self.text!, message: &message) + performValidation(isValid,message: message) + default: + break } } } } -extension EGFloatingTextField { - -} From 047df552d535bf6a812606fac115f2e9f619b89f Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 24 Aug 2016 16:10:31 +0200 Subject: [PATCH 09/29] fix --- EGFloatingTextField.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EGFloatingTextField.podspec b/EGFloatingTextField.podspec index 51662ce..eb5fd13 100644 --- a/EGFloatingTextField.podspec +++ b/EGFloatingTextField.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "EGFloatingTextField" - s.version = "2.0.0" + s.version = "0.0.1" s.summary = "Implementation of Google's 'Floating labels' of Material design." s.homepage = "https://github.com/enisgayretli/EGFloatingTextField" s.license = 'MIT' From f2fd4c487cdf79a8d14312f090194db81015182b Mon Sep 17 00:00:00 2001 From: Patrick Date: Thu, 1 Sep 2016 17:51:42 +0200 Subject: [PATCH 10/29] fix swift --- .../EGFloatingTextField/EGFloatingTextField.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift index bb0fc03..9c2090e 100644 --- a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift +++ b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift @@ -182,7 +182,7 @@ public class EGFloatingTextField: UITextField { self.activeBorder.autoPinEdge(ALEdge.Right, toEdge: ALEdge.Right, ofView: self) self.activeBorder.autoSetDimension(ALDimension.Height, toSize: 2) - NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("textDidChange:"), name: "UITextFieldTextDidChangeNotification", object: self) + NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(UITextInputDelegate.textDidChange(_:)), name: "UITextFieldTextDidChangeNotification", object: self) } public func setPlaceHolder(placeholder:String){ From 56a6fc671313c797e97ea341877dc87ac5f7e285 Mon Sep 17 00:00:00 2001 From: Patrick Date: Thu, 8 Sep 2016 14:22:50 +0200 Subject: [PATCH 11/29] fix swift 2.3 --- .../project.pbxproj | 3 ++ .../EGFloatingTextField.swift | 37 ++++++++++--------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj b/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj index 7191a4c..6462d51 100644 --- a/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj +++ b/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj @@ -321,6 +321,7 @@ }; B7CBFB271B769D1700CDE475 = { CreatedOnToolsVersion = 6.4; + LastSwiftMigration = 0800; }; B7CBFB321B769D1800CDE475 = { CreatedOnToolsVersion = 6.4; @@ -654,6 +655,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 2.3; }; name = Debug; }; @@ -672,6 +674,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 2.3; }; name = Release; }; diff --git a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift index 9c2090e..07629ef 100644 --- a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift +++ b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift @@ -148,7 +148,7 @@ public class EGFloatingTextField: UITextField { }) self.urlValidationBlock = ({(text:String,inout message: String) -> Bool in let regex = try! NSRegularExpression(pattern: "^(((http|https):\\/\\/)?((\\w)*|([0-9]*)|([-|_])*)+([\\/.|\\/]((\\w)*|([0-9]*)|([-|_])*))+)?$", options: [.CaseInsensitive]) - let isValid = regex.firstMatchInString(text, options:[], range: NSMakeRange(0, (text as! NSString).length)) != nil + let isValid = regex.firstMatchInString(text, options:[], range: NSMakeRange(0, (text as NSString).length)) != nil if !isValid { message = "Invalid url" } @@ -236,23 +236,24 @@ public class EGFloatingTextField: UITextField { } } let textRect = self.textRectForBounds(rect) - let context = UIGraphicsGetCurrentContext() - let borderlines : [CGPoint] = [CGPointMake(0, CGRectGetHeight(textRect) - 1), - CGPointMake(CGRectGetWidth(textRect), CGRectGetHeight(textRect) - 1)] - if self.enabled { - CGContextBeginPath(context); - CGContextAddLines(context, borderlines, 2); - CGContextSetLineWidth(context, 1.0); - CGContextSetStrokeColorWithColor(context, borderColor.CGColor); - CGContextStrokePath(context); - } else { - CGContextBeginPath(context); - CGContextAddLines(context, borderlines, 2); - CGContextSetLineWidth(context, 1.0); - let dashPattern : [CGFloat] = [2, 4] - CGContextSetLineDash(context, 0, dashPattern, 2); - CGContextSetStrokeColorWithColor(context, borderColor.CGColor); - CGContextStrokePath(context); + if let context = UIGraphicsGetCurrentContext(){ + let borderlines : [CGPoint] = [CGPointMake(0, CGRectGetHeight(textRect) - 1), + CGPointMake(CGRectGetWidth(textRect), CGRectGetHeight(textRect) - 1)] + if self.enabled { + CGContextBeginPath(context); + CGContextAddLines(context, borderlines, 2); + CGContextSetLineWidth(context, 1.0); + CGContextSetStrokeColorWithColor(context, borderColor.CGColor); + CGContextStrokePath(context); + } else { + CGContextBeginPath(context); + CGContextAddLines(context, borderlines, 2); + CGContextSetLineWidth(context, 1.0); + let dashPattern : [CGFloat] = [2, 4] + CGContextSetLineDash(context, 0, dashPattern, 2); + CGContextSetStrokeColorWithColor(context, borderColor.CGColor); + CGContextStrokePath(context); + } } } From 5ecf1f0f2a6b1b6a105a9e22e8ba1c45436ca257 Mon Sep 17 00:00:00 2001 From: Patrick Date: Tue, 13 Sep 2016 10:34:42 +0200 Subject: [PATCH 12/29] fix --- .../EGFloatingTextField.xcodeproj/project.pbxproj | 3 +++ .../EGFloatingTextField/EGFloatingTextField.swift | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj b/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj index 6462d51..2b93f00 100644 --- a/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj +++ b/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj @@ -325,6 +325,7 @@ }; B7CBFB321B769D1800CDE475 = { CreatedOnToolsVersion = 6.4; + LastSwiftMigration = 0800; }; }; }; @@ -692,6 +693,7 @@ INFOPLIST_FILE = EGFloatingTextFieldTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 2.3; }; name = Debug; }; @@ -705,6 +707,7 @@ INFOPLIST_FILE = EGFloatingTextFieldTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 2.3; }; name = Release; }; diff --git a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift index 07629ef..837794e 100644 --- a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift +++ b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift @@ -261,10 +261,10 @@ public class EGFloatingTextField: UITextField { self.validate() } - public func setDefaultText(string: String){ + public func setDefaultText(string: String?){ text = string - floatLabelToTop() - floating = true + string != nil ? floatLabelToTop() : animateLabelBack() + floating = !(string == nil) showInactiveBorder() dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.5 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in self.label.textColor = self.kDefaultInactiveColor From 3931fbdbd51d2d992b68b15fe976f35318553aa5 Mon Sep 17 00:00:00 2001 From: Joel Gerbore Date: Thu, 22 Sep 2016 15:46:39 +0200 Subject: [PATCH 13/29] Conversion to Swift 3.0 --- .../project.pbxproj | 34 ++- .../xcschemes/EGFloatingTextField.xcscheme | 13 +- .../EGFloatingTextField.swift | 200 +++++++++--------- .../EGFloatingTextField/Info.plist | 2 +- .../EGFloatingTextFieldTests.swift | 2 +- .../EGFloatingTextFieldTests/Info.plist | 2 +- EGFloatingTextField/Example/AppDelegate.swift | 12 +- EGFloatingTextField/Example/Info.plist | 2 +- .../Example/ViewController.swift | 24 +-- .../ExampleTests/ExampleTests.swift | 2 +- EGFloatingTextField/ExampleTests/Info.plist | 2 +- 11 files changed, 161 insertions(+), 134 deletions(-) diff --git a/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj b/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj index 2b93f00..e4cc5a2 100644 --- a/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj +++ b/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj @@ -310,13 +310,15 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0640; + LastUpgradeCheck = 0800; TargetAttributes = { B77E397B1B778E880078ABA3 = { CreatedOnToolsVersion = 6.4; + LastSwiftMigration = 0800; }; B77E398F1B778E880078ABA3 = { CreatedOnToolsVersion = 6.4; + LastSwiftMigration = 0800; TestTargetID = B77E397B1B778E880078ABA3; }; B7CBFB271B769D1700CDE475 = { @@ -501,7 +503,9 @@ ); INFOPLIST_FILE = Example/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -511,7 +515,9 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Example/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -530,7 +536,9 @@ INFOPLIST_FILE = ExampleTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example"; }; name = Debug; @@ -546,7 +554,9 @@ INFOPLIST_FILE = ExampleTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example"; }; name = Release; @@ -564,8 +574,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -573,6 +585,7 @@ CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -593,6 +606,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -612,8 +626,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -633,6 +649,8 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.4; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -645,6 +663,7 @@ baseConfigurationReference = 36B5992605E1EC32FF7D24F9 /* Pods-EGFloatingTextField.debug.xcconfig */; buildSettings = { CLANG_ENABLE_MODULES = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -653,10 +672,11 @@ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -665,6 +685,7 @@ baseConfigurationReference = 54182CEE59BCC3469EBBBFA4 /* Pods-EGFloatingTextField.release.xcconfig */; buildSettings = { CLANG_ENABLE_MODULES = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -673,9 +694,10 @@ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -692,8 +714,9 @@ ); INFOPLIST_FILE = EGFloatingTextFieldTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -706,8 +729,9 @@ ); INFOPLIST_FILE = EGFloatingTextFieldTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/EGFloatingTextField/EGFloatingTextField.xcodeproj/xcshareddata/xcschemes/EGFloatingTextField.xcscheme b/EGFloatingTextField/EGFloatingTextField.xcodeproj/xcshareddata/xcschemes/EGFloatingTextField.xcscheme index 206fe62..7f49f94 100644 --- a/EGFloatingTextField/EGFloatingTextField.xcodeproj/xcshareddata/xcschemes/EGFloatingTextField.xcscheme +++ b/EGFloatingTextField/EGFloatingTextField.xcodeproj/xcshareddata/xcschemes/EGFloatingTextField.xcscheme @@ -1,6 +1,6 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -62,15 +62,18 @@ ReferencedContainer = "container:EGFloatingTextField.xcodeproj"> + + Bool)! + fileprivate typealias EGFloatingTextFieldValidationBlock = ((_ text:String,_ message:inout String)-> Bool)! - public var validationType : EGFloatingTextFieldValidationType!{ + open var validationType : EGFloatingTextFieldValidationType!{ didSet{ if validationType != nil{ switch validationType! { case .Email: - keyboardType = .EmailAddress - autocapitalizationType = .None - autocorrectionType = .No + keyboardType = .emailAddress + autocapitalizationType = .none + autocorrectionType = .no case .Decimal: - keyboardType = .DecimalPad - autocapitalizationType = .None - autocorrectionType = .No + keyboardType = .decimalPad + autocapitalizationType = .none + autocorrectionType = .no case .Integer: - keyboardType = .NumberPad - autocapitalizationType = .None - autocorrectionType = .No + keyboardType = .numberPad + autocapitalizationType = .none + autocorrectionType = .no case .PhoneNumber: - keyboardType = .PhonePad - autocapitalizationType = .None - autocorrectionType = .No + keyboardType = .phonePad + autocapitalizationType = .none + autocorrectionType = .no case .WebURL: keyboardType = .URL - autocapitalizationType = .None - autocorrectionType = .No + autocapitalizationType = .none + autocorrectionType = .no default: - keyboardType = .Default - autocapitalizationType = .Sentences - autocorrectionType = .Default + keyboardType = .default + autocapitalizationType = .sentences + autocorrectionType = .default break } } @@ -68,7 +68,7 @@ public class EGFloatingTextField: UITextField { } } - @IBInspectable public var IBPlaceholder: String?{ + @IBInspectable open var IBPlaceholder: String?{ didSet{ if (IBPlaceholder != nil) { setPlaceHolder(IBPlaceholder!) @@ -76,19 +76,19 @@ public class EGFloatingTextField: UITextField { } } - private var emailValidationBlock : EGFloatingTextFieldValidationBlock - private var integerValidationBlock : EGFloatingTextFieldValidationBlock - private var decimalValidationBlock : EGFloatingTextFieldValidationBlock - private var phoneNumberValidationBlock : EGFloatingTextFieldValidationBlock - private var urlValidationBlock : EGFloatingTextFieldValidationBlock + fileprivate var emailValidationBlock : EGFloatingTextFieldValidationBlock + fileprivate var integerValidationBlock : EGFloatingTextFieldValidationBlock + fileprivate var decimalValidationBlock : EGFloatingTextFieldValidationBlock + fileprivate var phoneNumberValidationBlock : EGFloatingTextFieldValidationBlock + fileprivate var urlValidationBlock : EGFloatingTextFieldValidationBlock let kDefaultInactiveColor = UIColor(white: CGFloat(0), alpha: CGFloat(0.54)) - let kDefaultActiveColor = UIColor.blueColor() - let kDefaultErrorColor = UIColor.redColor() + let kDefaultActiveColor = UIColor.blue + let kDefaultErrorColor = UIColor.red let kDefaultLineHeight = CGFloat(22) let kDefaultLabelTextColor = UIColor(white: CGFloat(0), alpha: CGFloat(0.54)) - public var floatingLabel : Bool! = true + open var floatingLabel : Bool! = true var label : UILabel! var labelFont : UIFont! var labelTextColor : UIColor! @@ -110,45 +110,45 @@ public class EGFloatingTextField: UITextField { func commonInit(){ - self.emailValidationBlock = ({(text:String, inout message: String) -> Bool in + self.emailValidationBlock = ({(text:String, message: inout String) -> Bool in let emailRegex = "([A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6})?" let emailTest = NSPredicate(format:"SELF MATCHES %@" , emailRegex) - let isValid = emailTest.evaluateWithObject(text) + let isValid = emailTest.evaluate(with: text) if !isValid { message = "Invalid Email address" } return isValid; }) - self.integerValidationBlock = ({(text:String,inout message: String) -> Bool in + self.integerValidationBlock = ({(text:String,message: inout String) -> Bool in let numRegex = "^([+-]?[0-9]+)?$" let numTest = NSPredicate(format:"SELF MATCHES %@" , numRegex) - let isValid = numTest.evaluateWithObject(text) + let isValid = numTest.evaluate(with: text) if !isValid { message = "Invalid integer number" } return isValid; }) - self.decimalValidationBlock = ({(text:String,inout message: String) -> Bool in + self.decimalValidationBlock = ({(text:String,message: inout String) -> Bool in let numRegex = "^([+-]?[0-9]+([,|.]+[0-9]+|))?$" let numTest = NSPredicate(format:"SELF MATCHES %@" , numRegex) - let isValid = numTest.evaluateWithObject(text) + let isValid = numTest.evaluate(with: text) if !isValid { message = "Invalid decimal number" } return isValid; }) - self.phoneNumberValidationBlock = ({(text:String,inout message: String) -> Bool in + self.phoneNumberValidationBlock = ({(text:String,message: inout String) -> Bool in let numRegex = "^([+]?[0-9]+)?$" let numTest = NSPredicate(format:"SELF MATCHES %@" , numRegex) - let isValid = numTest.evaluateWithObject(text) + let isValid = numTest.evaluate(with: text) if !isValid { message = "Invalid phone number" } return isValid; }) - self.urlValidationBlock = ({(text:String,inout message: String) -> Bool in - let regex = try! NSRegularExpression(pattern: "^(((http|https):\\/\\/)?((\\w)*|([0-9]*)|([-|_])*)+([\\/.|\\/]((\\w)*|([0-9]*)|([-|_])*))+)?$", options: [.CaseInsensitive]) - let isValid = regex.firstMatchInString(text, options:[], range: NSMakeRange(0, (text as NSString).length)) != nil + self.urlValidationBlock = ({(text:String,message: inout String) -> Bool in + let regex = try! NSRegularExpression(pattern: "^(((http|https):\\/\\/)?((\\w)*|([0-9]*)|([-|_])*)+([\\/.|\\/]((\\w)*|([0-9]*)|([-|_])*))+)?$", options: [.caseInsensitive]) + let isValid = regex.firstMatch(in: text, options:[], range: NSMakeRange(0, (text as NSString).length)) != nil if !isValid { message = "Invalid url" } @@ -159,37 +159,37 @@ public class EGFloatingTextField: UITextField { self.hasError = false self.labelTextColor = kDefaultLabelTextColor - self.label = UILabel(frame: CGRectZero) + self.label = UILabel(frame: CGRect.zero) self.label.font = self.labelFont self.label.textColor = self.labelTextColor - self.label.textAlignment = NSTextAlignment.Left + self.label.textAlignment = NSTextAlignment.left self.label.numberOfLines = 1 self.label.layer.masksToBounds = false self.addSubview(self.label) - self.activeBorder = UIView(frame: CGRectZero) + self.activeBorder = UIView(frame: CGRect.zero) self.activeBorder.backgroundColor = kDefaultActiveColor self.activeBorder.layer.opacity = 0 self.addSubview(self.activeBorder) - self.label.autoAlignAxis(ALAxis.Horizontal, toSameAxisOfView: self) - self.label.autoPinEdge(ALEdge.Left, toEdge: ALEdge.Left, ofView: self) - self.label.autoMatchDimension(ALDimension.Width, toDimension: ALDimension.Width, ofView: self) - self.label.autoMatchDimension(ALDimension.Height, toDimension: ALDimension.Height, ofView: self) + self.label.autoAlignAxis(ALAxis.horizontal, toSameAxisOf: self) + self.label.autoPinEdge(ALEdge.left, to: ALEdge.left, of: self) + self.label.autoMatch(ALDimension.width, to: ALDimension.width, of: self) + self.label.autoMatch(ALDimension.height, to: ALDimension.height, of: self) - self.activeBorder.autoPinEdge(ALEdge.Bottom, toEdge: ALEdge.Bottom, ofView: self) - self.activeBorder.autoPinEdge(ALEdge.Left, toEdge: ALEdge.Left, ofView: self) - self.activeBorder.autoPinEdge(ALEdge.Right, toEdge: ALEdge.Right, ofView: self) - self.activeBorder.autoSetDimension(ALDimension.Height, toSize: 2) + self.activeBorder.autoPinEdge(ALEdge.bottom, to: ALEdge.bottom, of: self) + self.activeBorder.autoPinEdge(ALEdge.left, to: ALEdge.left, of: self) + self.activeBorder.autoPinEdge(ALEdge.right, to: ALEdge.right, of: self) + self.activeBorder.autoSetDimension(ALDimension.height, toSize: 2) - NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(UITextInputDelegate.textDidChange(_:)), name: "UITextFieldTextDidChangeNotification", object: self) + NotificationCenter.default.addObserver(self, selector: #selector(UITextInputDelegate.textDidChange(_:)), name: NSNotification.Name(rawValue: "UITextFieldTextDidChangeNotification"), object: self) } - public func setPlaceHolder(placeholder:String){ + open func setPlaceHolder(_ placeholder:String){ self.label.text = placeholder } - override public func becomeFirstResponder() -> Bool { + override open func becomeFirstResponder() -> Bool { if self.floatingLabel! { if !self.floating! || self.text!.isEmpty { self.floatLabelToTop() @@ -203,7 +203,7 @@ public class EGFloatingTextField: UITextField { return super.becomeFirstResponder() } - override public func resignFirstResponder() -> Bool { + override open func resignFirstResponder() -> Bool { if self.floatingLabel! { if self.floating! && self.text!.isEmpty { @@ -221,52 +221,52 @@ public class EGFloatingTextField: UITextField { return super.resignFirstResponder() } - override public func drawRect(rect: CGRect){ - super.drawRect(rect) + override open func draw(_ rect: CGRect){ + super.draw(rect) var borderColor = self.hasError! ? kDefaultErrorColor : kDefaultInactiveColor var sView: UIView? = superview while sView != nil { if let effectView = sView as? UIVisualEffectView{ if effectView.effect is UIVibrancyEffect { - borderColor = UIColor.whiteColor() + borderColor = UIColor.white } break }else{ sView = sView!.superview } } - let textRect = self.textRectForBounds(rect) + let textRect = self.textRect(forBounds: rect) if let context = UIGraphicsGetCurrentContext(){ - let borderlines : [CGPoint] = [CGPointMake(0, CGRectGetHeight(textRect) - 1), - CGPointMake(CGRectGetWidth(textRect), CGRectGetHeight(textRect) - 1)] - if self.enabled { - CGContextBeginPath(context); - CGContextAddLines(context, borderlines, 2); - CGContextSetLineWidth(context, 1.0); - CGContextSetStrokeColorWithColor(context, borderColor.CGColor); - CGContextStrokePath(context); + let borderlines : [CGPoint] = [CGPoint(x: 0, y: textRect.height - 1), + CGPoint(x: textRect.width, y: textRect.height - 1)] + if self.isEnabled { + context.beginPath(); + context.addLines(between: borderlines) + context.setLineWidth(1.0); + context.setStrokeColor(borderColor.cgColor); + context.strokePath(); } else { - CGContextBeginPath(context); - CGContextAddLines(context, borderlines, 2); - CGContextSetLineWidth(context, 1.0); + context.beginPath(); + context.addLines(between: borderlines) + context.setLineWidth(1.0) let dashPattern : [CGFloat] = [2, 4] - CGContextSetLineDash(context, 0, dashPattern, 2); - CGContextSetStrokeColorWithColor(context, borderColor.CGColor); - CGContextStrokePath(context); + context.setLineDash(phase: 0, lengths: dashPattern) + context.setStrokeColor(borderColor.cgColor); + context.strokePath(); } } } - func textDidChange(notif: NSNotification){ + func textDidChange(_ notif: Notification){ self.validate() } - public func setDefaultText(string: String?){ + open func setDefaultText(_ string: String?){ text = string string != nil ? floatLabelToTop() : animateLabelBack() floating = !(string == nil) showInactiveBorder() - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.5 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(0.5 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)) { () -> Void in self.label.textColor = self.kDefaultInactiveColor } } @@ -279,16 +279,16 @@ public class EGFloatingTextField: UITextField { let anim2 = CABasicAnimation(keyPath: "transform") let fromTransform = CATransform3DMakeScale(CGFloat(1.0), CGFloat(1.0), CGFloat(1)) var toTransform = CATransform3DMakeScale(CGFloat(0.5), CGFloat(0.5), CGFloat(1)) - toTransform = CATransform3DTranslate(toTransform, -CGRectGetWidth(self.label.frame)/2, -CGRectGetHeight(self.label.frame), 0) - anim2.fromValue = NSValue(CATransform3D: fromTransform) - anim2.toValue = NSValue(CATransform3D: toTransform) + toTransform = CATransform3DTranslate(toTransform, -self.label.frame.width/2, -self.label.frame.height, 0) + anim2.fromValue = NSValue(caTransform3D: fromTransform) + anim2.toValue = NSValue(caTransform3D: toTransform) anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) let animGroup = CAAnimationGroup() animGroup.animations = [anim2] animGroup.duration = 0.3 animGroup.fillMode = kCAFillModeForwards; - animGroup.removedOnCompletion = false; - self.label.layer.addAnimation(animGroup, forKey: "_floatingLabel") + animGroup.isRemovedOnCompletion = false; + self.label.layer.add(animGroup, forKey: "_floatingLabel") self.clipsToBounds = false CATransaction.commit() } @@ -301,12 +301,12 @@ public class EGFloatingTextField: UITextField { let anim2 = CABasicAnimation(keyPath: "transform") let fromTransform = CATransform3DMakeScale(CGFloat(0.01), CGFloat(1.0), 1) let toTransform = CATransform3DMakeScale(CGFloat(1.0), CGFloat(1.0), 1) - anim2.fromValue = NSValue(CATransform3D: fromTransform) - anim2.toValue = NSValue(CATransform3D: toTransform) + anim2.fromValue = NSValue(caTransform3D: fromTransform) + anim2.toValue = NSValue(caTransform3D: toTransform) anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) anim2.fillMode = kCAFillModeForwards - anim2.removedOnCompletion = false - self.activeBorder.layer.addAnimation(anim2, forKey: "_activeBorder") + anim2.isRemovedOnCompletion = false + self.activeBorder.layer.add(anim2, forKey: "_activeBorder") CATransaction.commit() } @@ -318,19 +318,19 @@ public class EGFloatingTextField: UITextField { let anim2 = CABasicAnimation(keyPath: "transform") var fromTransform = CATransform3DMakeScale(0.5, 0.5, 1) - fromTransform = CATransform3DTranslate(fromTransform, -CGRectGetWidth(self.label.frame)/2, -CGRectGetHeight(self.label.frame), 0); + fromTransform = CATransform3DTranslate(fromTransform, -self.label.frame.width/2, -self.label.frame.height, 0); let toTransform = CATransform3DMakeScale(1.0, 1.0, 1) - anim2.fromValue = NSValue(CATransform3D: fromTransform) - anim2.toValue = NSValue(CATransform3D: toTransform) + anim2.fromValue = NSValue(caTransform3D: fromTransform) + anim2.toValue = NSValue(caTransform3D: toTransform) anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) let animGroup = CAAnimationGroup() animGroup.animations = [anim2] animGroup.duration = 0.3 animGroup.fillMode = kCAFillModeForwards; - animGroup.removedOnCompletion = false; + animGroup.isRemovedOnCompletion = false; - self.label.layer.addAnimation(animGroup, forKey: "_animateLabelBack") + self.label.layer.add(animGroup, forKey: "_animateLabelBack") CATransaction.commit() } @@ -343,16 +343,16 @@ public class EGFloatingTextField: UITextField { let anim2 = CABasicAnimation(keyPath: "transform") let fromTransform = CATransform3DMakeScale(1.0, 1.0, 1) let toTransform = CATransform3DMakeScale(0.01, 1.0, 1) - anim2.fromValue = NSValue(CATransform3D: fromTransform) - anim2.toValue = NSValue(CATransform3D: toTransform) + anim2.fromValue = NSValue(caTransform3D: fromTransform) + anim2.toValue = NSValue(caTransform3D: toTransform) anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) anim2.fillMode = kCAFillModeForwards - anim2.removedOnCompletion = false - self.activeBorder.layer.addAnimation(anim2, forKey: "_activeBorder") + anim2.isRemovedOnCompletion = false + self.activeBorder.layer.add(anim2, forKey: "_activeBorder") CATransaction.commit() } - func performValidation(isValid:Bool,message:String){ + func performValidation(_ isValid:Bool,message:String){ if !isValid { self.hasError = true self.errorMessage = message @@ -373,19 +373,19 @@ public class EGFloatingTextField: UITextField { var message : String = "" switch self.validationType!{ case .Email: - let isValid = self.emailValidationBlock(text: self.text!, message: &message) + let isValid = self.emailValidationBlock(self.text!, &message) performValidation(isValid,message: message) case .Integer: - let isValid = self.integerValidationBlock(text: self.text!, message: &message) + let isValid = self.integerValidationBlock(self.text!, &message) performValidation(isValid,message: message) case .Decimal: - let isValid = self.decimalValidationBlock(text: self.text!, message: &message) + let isValid = self.decimalValidationBlock(self.text!, &message) performValidation(isValid,message: message) case .PhoneNumber: - let isValid = self.phoneNumberValidationBlock(text: self.text!, message: &message) + let isValid = self.phoneNumberValidationBlock(self.text!, &message) performValidation(isValid,message: message) case .WebURL: - let isValid = self.urlValidationBlock(text: self.text!, message: &message) + let isValid = self.urlValidationBlock( self.text!, &message) performValidation(isValid,message: message) default: break diff --git a/EGFloatingTextField/EGFloatingTextField/Info.plist b/EGFloatingTextField/EGFloatingTextField/Info.plist index b9a2b46..d3de8ee 100644 --- a/EGFloatingTextField/EGFloatingTextField/Info.plist +++ b/EGFloatingTextField/EGFloatingTextField/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/EGFloatingTextField/EGFloatingTextFieldTests/EGFloatingTextFieldTests.swift b/EGFloatingTextField/EGFloatingTextFieldTests/EGFloatingTextFieldTests.swift index c6bb333..cdcac58 100644 --- a/EGFloatingTextField/EGFloatingTextFieldTests/EGFloatingTextFieldTests.swift +++ b/EGFloatingTextField/EGFloatingTextFieldTests/EGFloatingTextFieldTests.swift @@ -28,7 +28,7 @@ class EGFloatingTextFieldTests: XCTestCase { func testPerformanceExample() { // This is an example of a performance test case. - self.measureBlock() { + self.measure() { // Put the code you want to measure the time of here. } } diff --git a/EGFloatingTextField/EGFloatingTextFieldTests/Info.plist b/EGFloatingTextField/EGFloatingTextFieldTests/Info.plist index 037bf91..ba72822 100644 --- a/EGFloatingTextField/EGFloatingTextFieldTests/Info.plist +++ b/EGFloatingTextField/EGFloatingTextFieldTests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/EGFloatingTextField/Example/AppDelegate.swift b/EGFloatingTextField/Example/AppDelegate.swift index af5a657..e3dd50a 100644 --- a/EGFloatingTextField/Example/AppDelegate.swift +++ b/EGFloatingTextField/Example/AppDelegate.swift @@ -14,30 +14,30 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } - func applicationWillResignActive(application: UIApplication) { + func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - func applicationDidEnterBackground(application: UIApplication) { + func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - func applicationWillEnterForeground(application: UIApplication) { + func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - func applicationDidBecomeActive(application: UIApplication) { + func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - func applicationWillTerminate(application: UIApplication) { + func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } diff --git a/EGFloatingTextField/Example/Info.plist b/EGFloatingTextField/Example/Info.plist index 7d08205..40c6215 100644 --- a/EGFloatingTextField/Example/Info.plist +++ b/EGFloatingTextField/Example/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/EGFloatingTextField/Example/ViewController.swift b/EGFloatingTextField/Example/ViewController.swift index a1a59f2..f63bd45 100644 --- a/EGFloatingTextField/Example/ViewController.swift +++ b/EGFloatingTextField/Example/ViewController.swift @@ -14,28 +14,28 @@ class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - let emailLabel = EGFloatingTextField(frame: CGRectMake(8, 64, CGRectGetWidth(self.view.bounds) - 16, 48)) + let emailLabel = EGFloatingTextField(frame: CGRect(x: 8, y: 64, width: (self.view.bounds).width - 16, height: 48)) emailLabel.floatingLabel = true emailLabel.setPlaceHolder("Email") emailLabel.validationType = .Email - emailLabel.keyboardType = .EmailAddress + emailLabel.keyboardType = .emailAddress self.view.addSubview(emailLabel) - let passwordLabel = EGFloatingTextField(frame: CGRectMake(8, 128, CGRectGetWidth(self.view.bounds) - 16, 48)) + let passwordLabel = EGFloatingTextField(frame: CGRect(x: 8, y: 128, width: (self.view.bounds).width - 16, height: 48)) passwordLabel.floatingLabel = true - passwordLabel.secureTextEntry = true + passwordLabel.isSecureTextEntry = true passwordLabel.setPlaceHolder("Password") self.view.addSubview(passwordLabel) - emailLabel.autoPinEdge(ALEdge.Left, toEdge:ALEdge.Left, ofView:self.view, withOffset:8) - emailLabel.autoPinEdge(ALEdge.Right, toEdge:ALEdge.Right, ofView:self.view, withOffset:-8) - emailLabel.autoPinToTopLayoutGuideOfViewController(self, withInset:16) - emailLabel.autoSetDimension(ALDimension.Height, toSize:44) + emailLabel.autoPinEdge(ALEdge.left, to:ALEdge.left, of:self.view, withOffset:8) + emailLabel.autoPinEdge(ALEdge.right, to:ALEdge.right, of:self.view, withOffset:-8) + emailLabel.autoPin(toTopLayoutGuideOf: self, withInset:16) + emailLabel.autoSetDimension(ALDimension.height, toSize:44) - passwordLabel.autoPinEdge(ALEdge.Left, toEdge:ALEdge.Left, ofView:self.view, withOffset:8) - passwordLabel.autoPinEdge(ALEdge.Right, toEdge:ALEdge.Right, ofView:self.view, withOffset:-8) - passwordLabel.autoPinEdge(ALEdge.Top, toEdge:ALEdge.Bottom, ofView:emailLabel, withOffset:16) - passwordLabel.autoSetDimension(ALDimension.Height, toSize:44) + passwordLabel.autoPinEdge(ALEdge.left, to:ALEdge.left, of:self.view, withOffset:8) + passwordLabel.autoPinEdge(ALEdge.right, to:ALEdge.right, of:self.view, withOffset:-8) + passwordLabel.autoPinEdge(ALEdge.top, to:ALEdge.bottom, of:emailLabel, withOffset:16) + passwordLabel.autoSetDimension(ALDimension.height, toSize:44) // Do any additional setup after loading the view, typically from a nib. } diff --git a/EGFloatingTextField/ExampleTests/ExampleTests.swift b/EGFloatingTextField/ExampleTests/ExampleTests.swift index e85f379..2ed1381 100644 --- a/EGFloatingTextField/ExampleTests/ExampleTests.swift +++ b/EGFloatingTextField/ExampleTests/ExampleTests.swift @@ -28,7 +28,7 @@ class ExampleTests: XCTestCase { func testPerformanceExample() { // This is an example of a performance test case. - self.measureBlock() { + self.measure() { // Put the code you want to measure the time of here. } } diff --git a/EGFloatingTextField/ExampleTests/Info.plist b/EGFloatingTextField/ExampleTests/Info.plist index 037bf91..ba72822 100644 --- a/EGFloatingTextField/ExampleTests/Info.plist +++ b/EGFloatingTextField/ExampleTests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName From cae93d8961ae2e272e499a9ef53abc7cc787cddb Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 15 Mar 2017 16:12:44 +0100 Subject: [PATCH 14/29] fix animation on text change --- .../EGFloatingTextField.swift | 73 ++++++++++--------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift index edfbc86..cf4008d 100644 --- a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift +++ b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift @@ -23,6 +23,20 @@ public enum EGFloatingTextFieldValidationType: String { open class EGFloatingTextField: UITextField { + open override var text: String?{ + didSet{ + if !isFirstResponder{ + if !(text ?? "").isEmpty && (oldValue ?? "").isEmpty{ + floatLabelToTop(active: false, animated: false) + floating = true + }else if (text ?? "").isEmpty && !(oldValue ?? "").isEmpty{ + animateLabelBack() + floating = false + } + } + } + } + fileprivate typealias EGFloatingTextFieldValidationBlock = ((_ text:String,_ message:inout String)-> Bool)! open var validationType : EGFloatingTextFieldValidationType!{ @@ -117,7 +131,7 @@ open class EGFloatingTextField: UITextField { if !isValid { message = "Invalid Email address" } - return isValid; + return isValid }) self.integerValidationBlock = ({(text:String,message: inout String) -> Bool in let numRegex = "^([+-]?[0-9]+)?$" @@ -126,7 +140,7 @@ open class EGFloatingTextField: UITextField { if !isValid { message = "Invalid integer number" } - return isValid; + return isValid }) self.decimalValidationBlock = ({(text:String,message: inout String) -> Bool in let numRegex = "^([+-]?[0-9]+([,|.]+[0-9]+|))?$" @@ -135,7 +149,7 @@ open class EGFloatingTextField: UITextField { if !isValid { message = "Invalid decimal number" } - return isValid; + return isValid }) self.phoneNumberValidationBlock = ({(text:String,message: inout String) -> Bool in let numRegex = "^([+]?[0-9]+)?$" @@ -144,7 +158,7 @@ open class EGFloatingTextField: UITextField { if !isValid { message = "Invalid phone number" } - return isValid; + return isValid }) self.urlValidationBlock = ({(text:String,message: inout String) -> Bool in let regex = try! NSRegularExpression(pattern: "^(((http|https):\\/\\/)?((\\w)*|([0-9]*)|([-|_])*)+([\\/.|\\/]((\\w)*|([0-9]*)|([-|_])*))+)?$", options: [.caseInsensitive]) @@ -152,7 +166,7 @@ open class EGFloatingTextField: UITextField { if !isValid { message = "Invalid url" } - return isValid; + return isValid }) self.floating = false @@ -240,19 +254,19 @@ open class EGFloatingTextField: UITextField { let borderlines : [CGPoint] = [CGPoint(x: 0, y: textRect.height - 1), CGPoint(x: textRect.width, y: textRect.height - 1)] if self.isEnabled { - context.beginPath(); + context.beginPath() context.addLines(between: borderlines) - context.setLineWidth(1.0); - context.setStrokeColor(borderColor.cgColor); - context.strokePath(); + context.setLineWidth(1.0) + context.setStrokeColor(borderColor.cgColor) + context.strokePath() } else { - context.beginPath(); + context.beginPath() context.addLines(between: borderlines) context.setLineWidth(1.0) let dashPattern : [CGFloat] = [2, 4] context.setLineDash(phase: 0, lengths: dashPattern) - context.setStrokeColor(borderColor.cgColor); - context.strokePath(); + context.setStrokeColor(borderColor.cgColor) + context.strokePath() } } } @@ -261,33 +275,26 @@ open class EGFloatingTextField: UITextField { self.validate() } - open func setDefaultText(_ string: String?){ - text = string - string != nil ? floatLabelToTop() : animateLabelBack() - floating = !(string == nil) - showInactiveBorder() - DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(0.5 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)) { () -> Void in - self.label.textColor = self.kDefaultInactiveColor - } - } - - func floatLabelToTop() { + func floatLabelToTop(active: Bool = true, animated: Bool = true) { + label.layoutIfNeeded() CATransaction.begin() - CATransaction.setCompletionBlock { () -> Void in - self.label.textColor = self.kDefaultActiveColor + if active { + CATransaction.setCompletionBlock { () -> Void in + self.label.textColor = self.kDefaultActiveColor + } } let anim2 = CABasicAnimation(keyPath: "transform") let fromTransform = CATransform3DMakeScale(CGFloat(1.0), CGFloat(1.0), CGFloat(1)) var toTransform = CATransform3DMakeScale(CGFloat(0.5), CGFloat(0.5), CGFloat(1)) - toTransform = CATransform3DTranslate(toTransform, -self.label.frame.width/2, -self.label.frame.height, 0) + toTransform = CATransform3DTranslate(toTransform, -label.frame.width/2, -label.frame.height, 0) anim2.fromValue = NSValue(caTransform3D: fromTransform) anim2.toValue = NSValue(caTransform3D: toTransform) anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) let animGroup = CAAnimationGroup() animGroup.animations = [anim2] - animGroup.duration = 0.3 - animGroup.fillMode = kCAFillModeForwards; - animGroup.isRemovedOnCompletion = false; + animGroup.duration = animated ? 0.3 : 0.0 + animGroup.fillMode = kCAFillModeForwards + animGroup.isRemovedOnCompletion = false self.label.layer.add(animGroup, forKey: "_floatingLabel") self.clipsToBounds = false CATransaction.commit() @@ -311,14 +318,14 @@ open class EGFloatingTextField: UITextField { } func animateLabelBack() { + label.layoutIfNeeded() CATransaction.begin() CATransaction.setCompletionBlock { () -> Void in self.label.textColor = self.kDefaultInactiveColor } - let anim2 = CABasicAnimation(keyPath: "transform") var fromTransform = CATransform3DMakeScale(0.5, 0.5, 1) - fromTransform = CATransform3DTranslate(fromTransform, -self.label.frame.width/2, -self.label.frame.height, 0); + fromTransform = CATransform3DTranslate(fromTransform, -self.label.frame.width/2, -self.label.frame.height, 0) let toTransform = CATransform3DMakeScale(1.0, 1.0, 1) anim2.fromValue = NSValue(caTransform3D: fromTransform) anim2.toValue = NSValue(caTransform3D: toTransform) @@ -327,8 +334,8 @@ open class EGFloatingTextField: UITextField { let animGroup = CAAnimationGroup() animGroup.animations = [anim2] animGroup.duration = 0.3 - animGroup.fillMode = kCAFillModeForwards; - animGroup.isRemovedOnCompletion = false; + animGroup.fillMode = kCAFillModeForwards + animGroup.isRemovedOnCompletion = false self.label.layer.add(animGroup, forKey: "_animateLabelBack") CATransaction.commit() From 9ba85c003c6e0d312feed5509181d9278dc92a37 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 15 Mar 2017 16:13:58 +0100 Subject: [PATCH 15/29] changed podspec version --- EGFloatingTextField.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EGFloatingTextField.podspec b/EGFloatingTextField.podspec index eb5fd13..b964cb6 100644 --- a/EGFloatingTextField.podspec +++ b/EGFloatingTextField.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "EGFloatingTextField" - s.version = "0.0.1" + s.version = "0.1.1" s.summary = "Implementation of Google's 'Floating labels' of Material design." s.homepage = "https://github.com/enisgayretli/EGFloatingTextField" s.license = 'MIT' From 12924f6b8f4d488b1c8a399cce4dc23f3e5e7538 Mon Sep 17 00:00:00 2001 From: Patrick Date: Fri, 14 Apr 2017 14:52:27 +0200 Subject: [PATCH 16/29] fix --- EGFloatingTextField.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EGFloatingTextField.podspec b/EGFloatingTextField.podspec index b964cb6..dbff9ca 100644 --- a/EGFloatingTextField.podspec +++ b/EGFloatingTextField.podspec @@ -9,7 +9,7 @@ Pod::Spec.new do |s| s.social_media_url = 'https://twitter.com/enisgayretli' s.platform = :ios, '8.0' s.requires_arc = true - s.dependency 'PureLayout', '~>2.0' + s.dependency 'PureLayout', '~>3.0' s.source_files = 'EGFloatingTextField/EGFloatingTextField/*.swift' end From df61f829c6c255b066d9611a8b9e40ef62983e02 Mon Sep 17 00:00:00 2001 From: Patrick Date: Fri, 12 May 2017 15:54:32 +0200 Subject: [PATCH 17/29] added validation for required element --- .../EGFloatingTextField.swift | 104 ++++++++++-------- 1 file changed, 57 insertions(+), 47 deletions(-) diff --git a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift index cf4008d..3d97671 100644 --- a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift +++ b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift @@ -42,32 +42,32 @@ open class EGFloatingTextField: UITextField { open var validationType : EGFloatingTextFieldValidationType!{ didSet{ if validationType != nil{ - switch validationType! { - case .Email: - keyboardType = .emailAddress - autocapitalizationType = .none - autocorrectionType = .no - case .Decimal: - keyboardType = .decimalPad - autocapitalizationType = .none - autocorrectionType = .no - case .Integer: - keyboardType = .numberPad - autocapitalizationType = .none - autocorrectionType = .no - case .PhoneNumber: - keyboardType = .phonePad - autocapitalizationType = .none - autocorrectionType = .no - case .WebURL: - keyboardType = .URL - autocapitalizationType = .none - autocorrectionType = .no - default: - keyboardType = .default - autocapitalizationType = .sentences - autocorrectionType = .default - break + switch validationType! { + case .Email: + keyboardType = .emailAddress + autocapitalizationType = .none + autocorrectionType = .no + case .Decimal: + keyboardType = .decimalPad + autocapitalizationType = .none + autocorrectionType = .no + case .Integer: + keyboardType = .numberPad + autocapitalizationType = .none + autocorrectionType = .no + case .PhoneNumber: + keyboardType = .phonePad + autocapitalizationType = .none + autocorrectionType = .no + case .WebURL: + keyboardType = .URL + autocapitalizationType = .none + autocorrectionType = .no + default: + keyboardType = .default + autocapitalizationType = .sentences + autocorrectionType = .default + break } } } @@ -90,6 +90,12 @@ open class EGFloatingTextField: UITextField { } } + @IBInspectable open var canBeEmpty: Bool = true{ + didSet{ + setPlaceHolder(label.text ?? "") + } + } + fileprivate var emailValidationBlock : EGFloatingTextFieldValidationBlock fileprivate var integerValidationBlock : EGFloatingTextFieldValidationBlock fileprivate var decimalValidationBlock : EGFloatingTextFieldValidationBlock @@ -200,7 +206,7 @@ open class EGFloatingTextField: UITextField { } open func setPlaceHolder(_ placeholder:String){ - self.label.text = placeholder + self.label.text = canBeEmpty ? placeholder : placeholder + " *" } override open func becomeFirstResponder() -> Bool { @@ -376,26 +382,30 @@ open class EGFloatingTextField: UITextField { } func validate(){ - if self.validationType != nil { - var message : String = "" - switch self.validationType!{ - case .Email: - let isValid = self.emailValidationBlock(self.text!, &message) - performValidation(isValid,message: message) - case .Integer: - let isValid = self.integerValidationBlock(self.text!, &message) - performValidation(isValid,message: message) - case .Decimal: - let isValid = self.decimalValidationBlock(self.text!, &message) - performValidation(isValid,message: message) - case .PhoneNumber: - let isValid = self.phoneNumberValidationBlock(self.text!, &message) - performValidation(isValid,message: message) - case .WebURL: - let isValid = self.urlValidationBlock( self.text!, &message) - performValidation(isValid,message: message) - default: - break + if !canBeEmpty, text?.isEmpty ?? true{ + performValidation(false, message: "Required") + }else{ + if self.validationType != nil { + var message : String = "" + switch self.validationType!{ + case .Email: + let isValid = self.emailValidationBlock(self.text!, &message) + performValidation(isValid,message: message) + case .Integer: + let isValid = self.integerValidationBlock(self.text!, &message) + performValidation(isValid,message: message) + case .Decimal: + let isValid = self.decimalValidationBlock(self.text!, &message) + performValidation(isValid,message: message) + case .PhoneNumber: + let isValid = self.phoneNumberValidationBlock(self.text!, &message) + performValidation(isValid,message: message) + case .WebURL: + let isValid = self.urlValidationBlock( self.text!, &message) + performValidation(isValid,message: message) + default: + performValidation(true,message: message) + } } } } From caf18b051c62cb25d3a9a6365fef3df984e00b85 Mon Sep 17 00:00:00 2001 From: Patrick Date: Fri, 23 Jun 2017 17:30:43 +0200 Subject: [PATCH 18/29] added localization error string added public method to check isValid field --- EGFloatingTextField.podspec | 1 + .../project.pbxproj | 21 +++ .../EGFloatingTextField/.DS_Store | Bin 6148 -> 8196 bytes .../Base.lproj/EGLocalizable.strings | 14 ++ .../EGFloatingTextField.swift | 127 +++++++++++++----- .../it.lproj/EGLocalizable.strings | 14 ++ .../Example/it.lproj/LaunchScreen.strings | 3 + .../Example/it.lproj/Main.strings | 1 + 8 files changed, 148 insertions(+), 33 deletions(-) create mode 100644 EGFloatingTextField/EGFloatingTextField/Base.lproj/EGLocalizable.strings create mode 100644 EGFloatingTextField/EGFloatingTextField/it.lproj/EGLocalizable.strings create mode 100644 EGFloatingTextField/Example/it.lproj/LaunchScreen.strings create mode 100644 EGFloatingTextField/Example/it.lproj/Main.strings diff --git a/EGFloatingTextField.podspec b/EGFloatingTextField.podspec index dbff9ca..c12d1b2 100644 --- a/EGFloatingTextField.podspec +++ b/EGFloatingTextField.podspec @@ -11,5 +11,6 @@ Pod::Spec.new do |s| s.requires_arc = true s.dependency 'PureLayout', '~>3.0' s.source_files = 'EGFloatingTextField/EGFloatingTextField/*.swift' + s.resource = 'EGFloatingTextField/EGFloatingTextField/**/*.{lproj}' end diff --git a/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj b/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj index e4cc5a2..67666a3 100644 --- a/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj +++ b/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj @@ -18,6 +18,7 @@ B7CBFB341B769D1800CDE475 /* EGFloatingTextField.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B7CBFB281B769D1700CDE475 /* EGFloatingTextField.framework */; }; B7CBFB3B1B769D1800CDE475 /* EGFloatingTextFieldTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7CBFB3A1B769D1800CDE475 /* EGFloatingTextFieldTests.swift */; }; B7CBFB451B769D8700CDE475 /* EGFloatingTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7CBFB441B769D8700CDE475 /* EGFloatingTextField.swift */; }; + CDD1766E1EFD62F000009C4E /* EGLocalizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = CDD1766C1EFD62F000009C4E /* EGLocalizable.strings */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -64,6 +65,10 @@ B7CBFB391B769D1800CDE475 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; B7CBFB3A1B769D1800CDE475 /* EGFloatingTextFieldTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EGFloatingTextFieldTests.swift; sourceTree = ""; }; B7CBFB441B769D8700CDE475 /* EGFloatingTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EGFloatingTextField.swift; sourceTree = ""; }; + CDD176691EFD604900009C4E /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Main.strings; sourceTree = ""; }; + CDD1766A1EFD604900009C4E /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/LaunchScreen.strings; sourceTree = ""; }; + CDD1766D1EFD62F000009C4E /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/EGLocalizable.strings; sourceTree = ""; }; + CDD1766F1EFD62F400009C4E /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/EGLocalizable.strings; sourceTree = ""; }; DD19DB55B4D44EF6A9BB8740 /* Pods_EGFloatingTextField.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_EGFloatingTextField.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -183,6 +188,7 @@ B7CBFB2A1B769D1700CDE475 /* EGFloatingTextField */ = { isa = PBXGroup; children = ( + CDD1766C1EFD62F000009C4E /* EGLocalizable.strings */, B7CBFB2D1B769D1700CDE475 /* EGFloatingTextField.h */, B7CBFB441B769D8700CDE475 /* EGFloatingTextField.swift */, B7CBFB2B1B769D1700CDE475 /* Supporting Files */, @@ -338,6 +344,7 @@ knownRegions = ( en, Base, + it, ); mainGroup = B7CBFB1E1B769D1700CDE475; productRefGroup = B7CBFB291B769D1700CDE475 /* Products */; @@ -374,6 +381,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + CDD1766E1EFD62F000009C4E /* EGLocalizable.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -478,6 +486,7 @@ isa = PBXVariantGroup; children = ( B77E39851B778E880078ABA3 /* Base */, + CDD176691EFD604900009C4E /* it */, ); name = Main.storyboard; sourceTree = ""; @@ -486,10 +495,20 @@ isa = PBXVariantGroup; children = ( B77E398A1B778E880078ABA3 /* Base */, + CDD1766A1EFD604900009C4E /* it */, ); name = LaunchScreen.xib; sourceTree = ""; }; + CDD1766C1EFD62F000009C4E /* EGLocalizable.strings */ = { + isa = PBXVariantGroup; + children = ( + CDD1766D1EFD62F000009C4E /* Base */, + CDD1766F1EFD62F400009C4E /* it */, + ); + name = EGLocalizable.strings; + sourceTree = ""; + }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ @@ -565,6 +584,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -617,6 +637,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; diff --git a/EGFloatingTextField/EGFloatingTextField/.DS_Store b/EGFloatingTextField/EGFloatingTextField/.DS_Store index 73e6f09c7fe43432866a57d1410153a57a68eef1..117b60b5a1881995e7d35828a62b1b8e0457253f 100644 GIT binary patch literal 8196 zcmeHM&1(}u6o1oJ-DxR}pxAJp#CYucugdjKrGryUg_ulOO=9itk1OP~`?qmR_0l>h@ zF*SirLgDkg_LUKJC51@PAHaeL7}UTm_L{(dmAa?C1hOBAmTY(xrxIEI%+!9Gt1xR0qYtFSE*XRr|IiYQ%)N->CZ z$LprD%PMS3let**o9M;IOdf9|a1 zuFS7L+~I}B%J;T^{gCs+RxbQBPAx%S4lQK0zDM*`r`D6bAU~PF#F>4 zh*BQl`uy)~q3&n~hRVRGTy2`?|Eq(4{~zi->BTeynt|amK*sV`K8I@_e+!N;&yQ*o w>lRjCxLsSKaKT2L=7=I4N9_Dzh2ja&G9^Qm;syM5{m!; diff --git a/EGFloatingTextField/EGFloatingTextField/Base.lproj/EGLocalizable.strings b/EGFloatingTextField/EGFloatingTextField/Base.lproj/EGLocalizable.strings new file mode 100644 index 0000000..78ca79a --- /dev/null +++ b/EGFloatingTextField/EGFloatingTextField/Base.lproj/EGLocalizable.strings @@ -0,0 +1,14 @@ +/* + Localizable.strings + EGFloatingTextField + + Created by Patrick on 23/06/17. + +*/ + +"Invalid_Email_Address" = "Invalid E-Mail address"; +"Invalid_integer_number" = "Invalid integer number"; +"Invalid_decimal_number" = "Invalid decimal number"; +"Invalid_phone_number" = "Invalid phone number"; +"Invalid_URL" = "Invalid URL"; +"Required" = "Required"; diff --git a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift index 3d97671..6c7ea83 100644 --- a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift +++ b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift @@ -23,6 +23,8 @@ public enum EGFloatingTextFieldValidationType: String { open class EGFloatingTextField: UITextField { + static let bundle = Bundle(for: EGFloatingTextField.self) + open override var text: String?{ didSet{ if !isFirstResponder{ @@ -110,6 +112,7 @@ open class EGFloatingTextField: UITextField { open var floatingLabel : Bool! = true var label : UILabel! + var errorLabel : UILabel! var labelFont : UIFont! var labelTextColor : UIColor! var activeBorder : UIView! @@ -135,7 +138,7 @@ open class EGFloatingTextField: UITextField { let emailTest = NSPredicate(format:"SELF MATCHES %@" , emailRegex) let isValid = emailTest.evaluate(with: text) if !isValid { - message = "Invalid Email address" + message = EGFloatingTextField.localizedString(string: "Invalid_Email_Address") } return isValid }) @@ -144,7 +147,7 @@ open class EGFloatingTextField: UITextField { let numTest = NSPredicate(format:"SELF MATCHES %@" , numRegex) let isValid = numTest.evaluate(with: text) if !isValid { - message = "Invalid integer number" + message = EGFloatingTextField.localizedString(string: "Invalid_integer_number") } return isValid }) @@ -153,7 +156,7 @@ open class EGFloatingTextField: UITextField { let numTest = NSPredicate(format:"SELF MATCHES %@" , numRegex) let isValid = numTest.evaluate(with: text) if !isValid { - message = "Invalid decimal number" + message = EGFloatingTextField.localizedString(string: "Invalid_decimal_number") } return isValid }) @@ -162,7 +165,7 @@ open class EGFloatingTextField: UITextField { let numTest = NSPredicate(format:"SELF MATCHES %@" , numRegex) let isValid = numTest.evaluate(with: text) if !isValid { - message = "Invalid phone number" + message = EGFloatingTextField.localizedString(string: "Invalid_phone_number") } return isValid }) @@ -170,7 +173,7 @@ open class EGFloatingTextField: UITextField { let regex = try! NSRegularExpression(pattern: "^(((http|https):\\/\\/)?((\\w)*|([0-9]*)|([-|_])*)+([\\/.|\\/]((\\w)*|([0-9]*)|([-|_])*))+)?$", options: [.caseInsensitive]) let isValid = regex.firstMatch(in: text, options:[], range: NSMakeRange(0, (text as NSString).length)) != nil if !isValid { - message = "Invalid url" + message = EGFloatingTextField.localizedString(string: "Invalid_URL") } return isValid }) @@ -187,6 +190,14 @@ open class EGFloatingTextField: UITextField { self.label.layer.masksToBounds = false self.addSubview(self.label) + self.errorLabel = UILabel(frame: CGRect.zero) + self.errorLabel.font = self.labelFont + self.errorLabel.textColor = self.labelTextColor + self.errorLabel.textAlignment = NSTextAlignment.right + self.errorLabel.numberOfLines = 1 + self.errorLabel.layer.masksToBounds = false + self.addSubview(self.errorLabel) + self.activeBorder = UIView(frame: CGRect.zero) self.activeBorder.backgroundColor = kDefaultActiveColor self.activeBorder.layer.opacity = 0 @@ -197,6 +208,11 @@ open class EGFloatingTextField: UITextField { self.label.autoMatch(ALDimension.width, to: ALDimension.width, of: self) self.label.autoMatch(ALDimension.height, to: ALDimension.height, of: self) + self.errorLabel.autoAlignAxis(ALAxis.horizontal, toSameAxisOf: self) + self.errorLabel.autoPinEdge(ALEdge.right, to: ALEdge.right, of: self) + self.errorLabel.autoMatch(ALDimension.width, to: ALDimension.width, of: self) + self.errorLabel.autoMatch(ALDimension.height, to: ALDimension.height, of: self) + self.activeBorder.autoPinEdge(ALEdge.bottom, to: ALEdge.bottom, of: self) self.activeBorder.autoPinEdge(ALEdge.left, to: ALEdge.left, of: self) self.activeBorder.autoPinEdge(ALEdge.right, to: ALEdge.right, of: self) @@ -306,6 +322,35 @@ open class EGFloatingTextField: UITextField { CATransaction.commit() } + func floatErrorLabelToTop() { + if errorLabel.layer.animation(forKey: "_floatingLabel") == nil { + errorLabel.layoutIfNeeded() + CATransaction.begin() + errorLabel.textColor = kDefaultErrorColor + let anim2 = CABasicAnimation(keyPath: "transform") + let fromTransform = CATransform3DMakeScale(CGFloat(1.0), CGFloat(1.0), CGFloat(1)) + var toTransform = CATransform3DMakeScale(CGFloat(0.5), CGFloat(0.5), CGFloat(1)) + toTransform = CATransform3DTranslate(toTransform, errorLabel.frame.width/2, -errorLabel.frame.height, 0) + anim2.fromValue = NSValue(caTransform3D: fromTransform) + anim2.toValue = NSValue(caTransform3D: toTransform) + anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) + let animGroup = CAAnimationGroup() + animGroup.animations = [anim2] + animGroup.duration = 0.3 + animGroup.fillMode = kCAFillModeForwards + animGroup.isRemovedOnCompletion = false + errorLabel.layer.add(animGroup, forKey: "_floatingLabel") + clipsToBounds = false + CATransaction.commit() + } + } + + func removeAnimationForErrorLabel(){ + if errorLabel.layer.animation(forKey: "_floatingLabel") != nil { + errorLabel.layer.removeAnimation(forKey: "_floatingLabel") + } + } + func showActiveBorder() { self.activeBorder.layer.transform = CATransform3DMakeScale(CGFloat(0.01), CGFloat(1.0), 1) self.activeBorder.layer.opacity = 1 @@ -365,49 +410,65 @@ open class EGFloatingTextField: UITextField { CATransaction.commit() } - func performValidation(_ isValid:Bool,message:String){ - if !isValid { - self.hasError = true - self.errorMessage = message + func performValidation(){ + if hasError { + floatErrorLabelToTop() self.labelTextColor = kDefaultErrorColor self.activeBorder.backgroundColor = kDefaultErrorColor + errorLabel.text = errorMessage + errorLabel.isHidden = false self.setNeedsDisplay() } else { - self.hasError = false - self.errorMessage = nil + removeAnimationForErrorLabel() self.labelTextColor = kDefaultActiveColor self.activeBorder.backgroundColor = kDefaultActiveColor + errorLabel.text = nil + errorLabel.isHidden = true self.setNeedsDisplay() } } func validate(){ if !canBeEmpty, text?.isEmpty ?? true{ - performValidation(false, message: "Required") + hasError(true, withMessage: EGFloatingTextField.localizedString(string: "Required")) + performValidation() }else{ - if self.validationType != nil { - var message : String = "" - switch self.validationType!{ - case .Email: - let isValid = self.emailValidationBlock(self.text!, &message) - performValidation(isValid,message: message) - case .Integer: - let isValid = self.integerValidationBlock(self.text!, &message) - performValidation(isValid,message: message) - case .Decimal: - let isValid = self.decimalValidationBlock(self.text!, &message) - performValidation(isValid,message: message) - case .PhoneNumber: - let isValid = self.phoneNumberValidationBlock(self.text!, &message) - performValidation(isValid,message: message) - case .WebURL: - let isValid = self.urlValidationBlock( self.text!, &message) - performValidation(isValid,message: message) - default: - performValidation(true,message: message) - } + let (valid, message) = isValid() + hasError(!valid, withMessage: message) + performValidation() + } + } + + func hasError(_ hasError: Bool = false, withMessage message: String? = nil){ + self.hasError = hasError + errorMessage = message + } + + public func isValid() -> (Bool, String?){ + var message = String() + var isValid = true + if self.validationType != nil { + switch self.validationType!{ + case .Email: + isValid = self.emailValidationBlock(self.text!, &message) + case .Integer: + isValid = self.integerValidationBlock(self.text!, &message) + case .Decimal: + isValid = self.decimalValidationBlock(self.text!, &message) + case .PhoneNumber: + isValid = self.phoneNumberValidationBlock(self.text!, &message) + case .WebURL: + isValid = self.urlValidationBlock( self.text!, &message) + default: + break } } + return (isValid, message.isEmpty ? nil : message) + } + + static fileprivate func localizedString(string: String) -> String{ + return NSLocalizedString(string, tableName: nil, bundle: Bundle.main, value: EGFloatingTextField.bundle.localizedString(forKey: string, value: string, table: "EGLocalizable"), comment: "") } } + diff --git a/EGFloatingTextField/EGFloatingTextField/it.lproj/EGLocalizable.strings b/EGFloatingTextField/EGFloatingTextField/it.lproj/EGLocalizable.strings new file mode 100644 index 0000000..af0b4cc --- /dev/null +++ b/EGFloatingTextField/EGFloatingTextField/it.lproj/EGLocalizable.strings @@ -0,0 +1,14 @@ +/* + Localizable.strings + EGFloatingTextField + + Created by Patrick on 23/06/17. + +*/ + +"Invalid_Email_Address" = "Indirizzo E-Mail non valido"; +"Invalid_integer_number" = "Numero intero non valido"; +"Invalid_decimal_number" = "Numero decimale non valido"; +"Invalid_phone_number" = "Numero di telefono non valido"; +"Invalid_URL" = "URL non valido"; +"Required" = "Obbligatorio"; diff --git a/EGFloatingTextField/Example/it.lproj/LaunchScreen.strings b/EGFloatingTextField/Example/it.lproj/LaunchScreen.strings new file mode 100644 index 0000000..60cf34e --- /dev/null +++ b/EGFloatingTextField/Example/it.lproj/LaunchScreen.strings @@ -0,0 +1,3 @@ + +/* Class = "UILabel"; text = "Example"; ObjectID = "kId-c2-rCX"; */ +"kId-c2-rCX.text" = "Example"; diff --git a/EGFloatingTextField/Example/it.lproj/Main.strings b/EGFloatingTextField/Example/it.lproj/Main.strings new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/EGFloatingTextField/Example/it.lproj/Main.strings @@ -0,0 +1 @@ + From a5bc2bdb844c41b502557ada89bcc472dc5f147a Mon Sep 17 00:00:00 2001 From: Patrick Date: Fri, 23 Jun 2017 17:31:27 +0200 Subject: [PATCH 19/29] new version number --- EGFloatingTextField.podspec | 2 +- .../EGFloatingTextField/.DS_Store | Bin 8196 -> 8196 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/EGFloatingTextField.podspec b/EGFloatingTextField.podspec index c12d1b2..fe9ae49 100644 --- a/EGFloatingTextField.podspec +++ b/EGFloatingTextField.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "EGFloatingTextField" - s.version = "0.1.1" + s.version = "0.1.2" s.summary = "Implementation of Google's 'Floating labels' of Material design." s.homepage = "https://github.com/enisgayretli/EGFloatingTextField" s.license = 'MIT' diff --git a/EGFloatingTextField/EGFloatingTextField/.DS_Store b/EGFloatingTextField/EGFloatingTextField/.DS_Store index 117b60b5a1881995e7d35828a62b1b8e0457253f..904bdaf75ffc4f7435c2c6483df185c5024d1717 100644 GIT binary patch delta 53 zcmZp1XmQvOD9FSZKiN(|Vls~i57QIH$qNOgHcu8zW@2Kjn(QDV0ugqbY$qbN*+Aq9 FHvpPN4+{VQ delta 47 zcmZp1XmQvOD9FUnGuci+Vls~i&*b@nGMgt0CNnWHOq}c>A_5k(5s}zzAaaEp07k40 A8UO$Q From 3d7401a018df9d4359c860cbbfb52df287830e74 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 28 Jun 2017 08:56:22 +0200 Subject: [PATCH 20/29] add french localization --- .../fr.lproj/EGLocalizable.strings | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 EGFloatingTextField/EGFloatingTextField/fr.lproj/EGLocalizable.strings diff --git a/EGFloatingTextField/EGFloatingTextField/fr.lproj/EGLocalizable.strings b/EGFloatingTextField/EGFloatingTextField/fr.lproj/EGLocalizable.strings new file mode 100644 index 0000000..adc1cbe --- /dev/null +++ b/EGFloatingTextField/EGFloatingTextField/fr.lproj/EGLocalizable.strings @@ -0,0 +1,14 @@ +/* + Localizable.strings + EGFloatingTextField + + Created by Patrick on 23/06/17. + +*/ + +"Invalid_Email_Address" = "Adresse e-mail invalide"; +"Invalid_integer_number" = "Numéro entier invalide"; +"Invalid_decimal_number" = "Numéro décimal invalide"; +"Invalid_phone_number" = "Numéro de téléphone invalide"; +"Invalid_URL" = "URL invalide"; +"Required" = "Obligatoire"; From 92b0be506543f7bb19adb9d4719f10189af9ff32 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 28 Jun 2017 08:57:05 +0200 Subject: [PATCH 21/29] add fr language --- .../EGFloatingTextField.xcodeproj/project.pbxproj | 3 +++ 1 file changed, 3 insertions(+) diff --git a/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj b/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj index 67666a3..f2da3f9 100644 --- a/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj +++ b/EGFloatingTextField/EGFloatingTextField.xcodeproj/project.pbxproj @@ -65,6 +65,7 @@ B7CBFB391B769D1800CDE475 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; B7CBFB3A1B769D1800CDE475 /* EGFloatingTextFieldTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EGFloatingTextFieldTests.swift; sourceTree = ""; }; B7CBFB441B769D8700CDE475 /* EGFloatingTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EGFloatingTextField.swift; sourceTree = ""; }; + CDB85F0A1F038A2E00E0B831 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/EGLocalizable.strings; sourceTree = ""; }; CDD176691EFD604900009C4E /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Main.strings; sourceTree = ""; }; CDD1766A1EFD604900009C4E /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/LaunchScreen.strings; sourceTree = ""; }; CDD1766D1EFD62F000009C4E /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/EGLocalizable.strings; sourceTree = ""; }; @@ -345,6 +346,7 @@ en, Base, it, + fr, ); mainGroup = B7CBFB1E1B769D1700CDE475; productRefGroup = B7CBFB291B769D1700CDE475 /* Products */; @@ -505,6 +507,7 @@ children = ( CDD1766D1EFD62F000009C4E /* Base */, CDD1766F1EFD62F400009C4E /* it */, + CDB85F0A1F038A2E00E0B831 /* fr */, ); name = EGLocalizable.strings; sourceTree = ""; From 4fb0205b0f95a16c233e63a1df0ad0b4a4373e85 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 28 Jun 2017 08:57:31 +0200 Subject: [PATCH 22/29] new pod version --- EGFloatingTextField.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EGFloatingTextField.podspec b/EGFloatingTextField.podspec index fe9ae49..01baccc 100644 --- a/EGFloatingTextField.podspec +++ b/EGFloatingTextField.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "EGFloatingTextField" - s.version = "0.1.2" + s.version = "0.1.3" s.summary = "Implementation of Google's 'Floating labels' of Material design." s.homepage = "https://github.com/enisgayretli/EGFloatingTextField" s.license = 'MIT' From 10cf062fb7de76e77a96e8bfc30e54b2e579e437 Mon Sep 17 00:00:00 2001 From: Patrick Date: Fri, 11 Aug 2017 09:52:11 +0200 Subject: [PATCH 23/29] fix @objc method --- .../EGFloatingTextField/EGFloatingTextField.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift index 6c7ea83..15640f6 100644 --- a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift +++ b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift @@ -293,7 +293,7 @@ open class EGFloatingTextField: UITextField { } } - func textDidChange(_ notif: Notification){ + @objc func textDidChange(_ notif: Notification){ self.validate() } From a0240b921c760983a4a9c9a84852ab90be4b4843 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 13 Sep 2017 15:53:42 +0200 Subject: [PATCH 24/29] fix new version --- EGFloatingTextField.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EGFloatingTextField.podspec b/EGFloatingTextField.podspec index 01baccc..b353d12 100644 --- a/EGFloatingTextField.podspec +++ b/EGFloatingTextField.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "EGFloatingTextField" - s.version = "0.1.3" + s.version = "0.1.4" s.summary = "Implementation of Google's 'Floating labels' of Material design." s.homepage = "https://github.com/enisgayretli/EGFloatingTextField" s.license = 'MIT' From 954ede4f46eaa07aa585fb24a0ef00cf66234e63 Mon Sep 17 00:00:00 2001 From: Patrick Date: Thu, 19 Oct 2017 12:16:17 +0200 Subject: [PATCH 25/29] fix required field --- EGFloatingTextField.podspec | 2 +- .../EGFloatingTextField/EGFloatingTextField.swift | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/EGFloatingTextField.podspec b/EGFloatingTextField.podspec index b353d12..7a5948c 100644 --- a/EGFloatingTextField.podspec +++ b/EGFloatingTextField.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "EGFloatingTextField" - s.version = "0.1.4" + s.version = "0.1.5" s.summary = "Implementation of Google's 'Floating labels' of Material design." s.homepage = "https://github.com/enisgayretli/EGFloatingTextField" s.license = 'MIT' diff --git a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift index 15640f6..7a0f2b5 100644 --- a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift +++ b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift @@ -83,18 +83,17 @@ open class EGFloatingTextField: UITextField { self.validationType = EGFloatingTextFieldValidationType(rawValue: shapeIndex) ?? .Default } } - + fileprivate var egPlaceholder: String? @IBInspectable open var IBPlaceholder: String?{ didSet{ - if (IBPlaceholder != nil) { - setPlaceHolder(IBPlaceholder!) - } + egPlaceholder = IBPlaceholder + refreshPlaceHolder() } } @IBInspectable open var canBeEmpty: Bool = true{ didSet{ - setPlaceHolder(label.text ?? "") + refreshPlaceHolder() } } @@ -221,8 +220,8 @@ open class EGFloatingTextField: UITextField { NotificationCenter.default.addObserver(self, selector: #selector(UITextInputDelegate.textDidChange(_:)), name: NSNotification.Name(rawValue: "UITextFieldTextDidChangeNotification"), object: self) } - open func setPlaceHolder(_ placeholder:String){ - self.label.text = canBeEmpty ? placeholder : placeholder + " *" + open func refreshPlaceHolder(){ + self.label.text = canBeEmpty ? egPlaceholder : (egPlaceholder != nil ? egPlaceholder! + " *" : nil) } override open func becomeFirstResponder() -> Bool { From f107083a0e23d520b6c276e46f6a0103ae5c8be8 Mon Sep 17 00:00:00 2001 From: Joel Date: Thu, 1 Feb 2018 12:13:36 +0100 Subject: [PATCH 26/29] Customizable label color and font --- .../EGFloatingTextField.swift | 94 ++++++++++++++----- 1 file changed, 73 insertions(+), 21 deletions(-) diff --git a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift index 7a0f2b5..1d0dd29 100644 --- a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift +++ b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift @@ -103,17 +103,72 @@ open class EGFloatingTextField: UITextField { fileprivate var phoneNumberValidationBlock : EGFloatingTextFieldValidationBlock fileprivate var urlValidationBlock : EGFloatingTextFieldValidationBlock - let kDefaultInactiveColor = UIColor(white: CGFloat(0), alpha: CGFloat(0.54)) - let kDefaultActiveColor = UIColor.blue - let kDefaultErrorColor = UIColor.red + public var defaultInactiveColor = UIColor(white: CGFloat(0), alpha: CGFloat(0.54)) { + willSet{ + if defaultInactiveColor == self.label.textColor + { + self.label.textColor = newValue + } + + if self.activeBorder.backgroundColor == defaultInactiveColor + { + self.activeBorder.backgroundColor = newValue + } + } + } + + public var defaultActiveColor = UIColor.blue { + willSet{ + if defaultActiveColor == self.label.textColor + { + self.label.textColor = newValue + } + + if self.activeBorder.backgroundColor == defaultActiveColor + { + self.activeBorder.backgroundColor = newValue + } + } + } + + public var defaultErrorColor = UIColor.red { + willSet{ + if defaultErrorColor == self.label.textColor + { + self.label.textColor = newValue + } + + if self.activeBorder.backgroundColor == defaultErrorColor + { + self.activeBorder.backgroundColor = newValue + } + } + didSet{ + errorLabel.textColor = defaultErrorColor + } + } + + public var defaultLabelTextColor = UIColor(white: CGFloat(0), alpha: CGFloat(0.54)) { + willSet{ + if defaultLabelTextColor == self.label.textColor + { + self.label.textColor = newValue + } + } + } + let kDefaultLineHeight = CGFloat(22) - let kDefaultLabelTextColor = UIColor(white: CGFloat(0), alpha: CGFloat(0.54)) + open var floatingLabel : Bool! = true var label : UILabel! var errorLabel : UILabel! - var labelFont : UIFont! - var labelTextColor : UIColor! + public var labelFont : UIFont! { + didSet { + self.errorLabel.font = labelFont + self.label.font = labelFont + } + } var activeBorder : UIView! var floating : Bool! var active : Bool! @@ -179,11 +234,10 @@ open class EGFloatingTextField: UITextField { self.floating = false self.hasError = false - - self.labelTextColor = kDefaultLabelTextColor + self.label = UILabel(frame: CGRect.zero) self.label.font = self.labelFont - self.label.textColor = self.labelTextColor + self.label.textColor = defaultLabelTextColor self.label.textAlignment = NSTextAlignment.left self.label.numberOfLines = 1 self.label.layer.masksToBounds = false @@ -191,14 +245,14 @@ open class EGFloatingTextField: UITextField { self.errorLabel = UILabel(frame: CGRect.zero) self.errorLabel.font = self.labelFont - self.errorLabel.textColor = self.labelTextColor + self.errorLabel.textColor = defaultLabelTextColor self.errorLabel.textAlignment = NSTextAlignment.right self.errorLabel.numberOfLines = 1 self.errorLabel.layer.masksToBounds = false self.addSubview(self.errorLabel) self.activeBorder = UIView(frame: CGRect.zero) - self.activeBorder.backgroundColor = kDefaultActiveColor + self.activeBorder.backgroundColor = defaultActiveColor self.activeBorder.layer.opacity = 0 self.addSubview(self.activeBorder) @@ -231,7 +285,7 @@ open class EGFloatingTextField: UITextField { self.floating = true } } else { - self.label.textColor = kDefaultActiveColor + self.label.textColor = defaultActiveColor self.label.layer.opacity = 0 } self.showActiveBorder() @@ -250,7 +304,7 @@ open class EGFloatingTextField: UITextField { self.label.layer.opacity = 1 } } - self.label.textColor = kDefaultInactiveColor + self.label.textColor = defaultInactiveColor self.showInactiveBorder() self.validate() return super.resignFirstResponder() @@ -258,7 +312,7 @@ open class EGFloatingTextField: UITextField { override open func draw(_ rect: CGRect){ super.draw(rect) - var borderColor = self.hasError! ? kDefaultErrorColor : kDefaultInactiveColor + var borderColor = self.hasError! ? defaultErrorColor : defaultInactiveColor var sView: UIView? = superview while sView != nil { if let effectView = sView as? UIVisualEffectView{ @@ -301,7 +355,7 @@ open class EGFloatingTextField: UITextField { CATransaction.begin() if active { CATransaction.setCompletionBlock { () -> Void in - self.label.textColor = self.kDefaultActiveColor + self.label.textColor = self.defaultActiveColor } } let anim2 = CABasicAnimation(keyPath: "transform") @@ -325,7 +379,7 @@ open class EGFloatingTextField: UITextField { if errorLabel.layer.animation(forKey: "_floatingLabel") == nil { errorLabel.layoutIfNeeded() CATransaction.begin() - errorLabel.textColor = kDefaultErrorColor + errorLabel.textColor = defaultErrorColor let anim2 = CABasicAnimation(keyPath: "transform") let fromTransform = CATransform3DMakeScale(CGFloat(1.0), CGFloat(1.0), CGFloat(1)) var toTransform = CATransform3DMakeScale(CGFloat(0.5), CGFloat(0.5), CGFloat(1)) @@ -371,7 +425,7 @@ open class EGFloatingTextField: UITextField { label.layoutIfNeeded() CATransaction.begin() CATransaction.setCompletionBlock { () -> Void in - self.label.textColor = self.kDefaultInactiveColor + self.label.textColor = self.defaultInactiveColor } let anim2 = CABasicAnimation(keyPath: "transform") var fromTransform = CATransform3DMakeScale(0.5, 0.5, 1) @@ -412,15 +466,13 @@ open class EGFloatingTextField: UITextField { func performValidation(){ if hasError { floatErrorLabelToTop() - self.labelTextColor = kDefaultErrorColor - self.activeBorder.backgroundColor = kDefaultErrorColor + self.activeBorder.backgroundColor = defaultErrorColor errorLabel.text = errorMessage errorLabel.isHidden = false self.setNeedsDisplay() } else { removeAnimationForErrorLabel() - self.labelTextColor = kDefaultActiveColor - self.activeBorder.backgroundColor = kDefaultActiveColor + self.activeBorder.backgroundColor = defaultActiveColor errorLabel.text = nil errorLabel.isHidden = true self.setNeedsDisplay() From 0119c73630b965251705ad2a39cf95c200bd1301 Mon Sep 17 00:00:00 2001 From: Patrick Date: Sat, 1 Sep 2018 11:53:48 +0200 Subject: [PATCH 27/29] now supporting swift 4.2 --- EGFloatingTextField.podspec | 2 +- .../EGFloatingTextField.swift | 39 +++++++++++-------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/EGFloatingTextField.podspec b/EGFloatingTextField.podspec index 7a5948c..a31c93d 100644 --- a/EGFloatingTextField.podspec +++ b/EGFloatingTextField.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "EGFloatingTextField" - s.version = "0.1.5" + s.version = "0.1.7" s.summary = "Implementation of Google's 'Floating labels' of Material design." s.homepage = "https://github.com/enisgayretli/EGFloatingTextField" s.license = 'MIT' diff --git a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift index 1d0dd29..a265fbb 100644 --- a/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift +++ b/EGFloatingTextField/EGFloatingTextField/EGFloatingTextField.swift @@ -9,6 +9,13 @@ import UIKit import Foundation import PureLayout +#if swift(>=4.2) +fileprivate let mediaTimingFunctionEaseOut = CAMediaTimingFunctionName.easeOut +fileprivate let fillModeForwards = CAMediaTimingFillMode.forwards +#else +fileprivate let mediaTimingFunctionEaseOut = kCAMediaTimingFunctionEaseOut +fileprivate let fillModeForwards = kCAFillModeForwards +#endif public enum EGFloatingTextFieldValidationType: String { case Default @@ -39,7 +46,7 @@ open class EGFloatingTextField: UITextField { } } - fileprivate typealias EGFloatingTextFieldValidationBlock = ((_ text:String,_ message:inout String)-> Bool)! + fileprivate typealias EGFloatingTextFieldValidationBlock = (_ text:String,_ message:inout String)-> Bool open var validationType : EGFloatingTextFieldValidationType!{ didSet{ @@ -97,11 +104,11 @@ open class EGFloatingTextField: UITextField { } } - fileprivate var emailValidationBlock : EGFloatingTextFieldValidationBlock - fileprivate var integerValidationBlock : EGFloatingTextFieldValidationBlock - fileprivate var decimalValidationBlock : EGFloatingTextFieldValidationBlock - fileprivate var phoneNumberValidationBlock : EGFloatingTextFieldValidationBlock - fileprivate var urlValidationBlock : EGFloatingTextFieldValidationBlock + fileprivate var emailValidationBlock : EGFloatingTextFieldValidationBlock! + fileprivate var integerValidationBlock : EGFloatingTextFieldValidationBlock! + fileprivate var decimalValidationBlock : EGFloatingTextFieldValidationBlock! + fileprivate var phoneNumberValidationBlock : EGFloatingTextFieldValidationBlock! + fileprivate var urlValidationBlock : EGFloatingTextFieldValidationBlock! public var defaultInactiveColor = UIColor(white: CGFloat(0), alpha: CGFloat(0.54)) { willSet{ @@ -364,11 +371,11 @@ open class EGFloatingTextField: UITextField { toTransform = CATransform3DTranslate(toTransform, -label.frame.width/2, -label.frame.height, 0) anim2.fromValue = NSValue(caTransform3D: fromTransform) anim2.toValue = NSValue(caTransform3D: toTransform) - anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) + anim2.timingFunction = CAMediaTimingFunction(name: mediaTimingFunctionEaseOut) let animGroup = CAAnimationGroup() animGroup.animations = [anim2] animGroup.duration = animated ? 0.3 : 0.0 - animGroup.fillMode = kCAFillModeForwards + animGroup.fillMode = fillModeForwards animGroup.isRemovedOnCompletion = false self.label.layer.add(animGroup, forKey: "_floatingLabel") self.clipsToBounds = false @@ -386,11 +393,11 @@ open class EGFloatingTextField: UITextField { toTransform = CATransform3DTranslate(toTransform, errorLabel.frame.width/2, -errorLabel.frame.height, 0) anim2.fromValue = NSValue(caTransform3D: fromTransform) anim2.toValue = NSValue(caTransform3D: toTransform) - anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) + anim2.timingFunction = CAMediaTimingFunction(name: mediaTimingFunctionEaseOut) let animGroup = CAAnimationGroup() animGroup.animations = [anim2] animGroup.duration = 0.3 - animGroup.fillMode = kCAFillModeForwards + animGroup.fillMode = fillModeForwards animGroup.isRemovedOnCompletion = false errorLabel.layer.add(animGroup, forKey: "_floatingLabel") clipsToBounds = false @@ -414,8 +421,8 @@ open class EGFloatingTextField: UITextField { let toTransform = CATransform3DMakeScale(CGFloat(1.0), CGFloat(1.0), 1) anim2.fromValue = NSValue(caTransform3D: fromTransform) anim2.toValue = NSValue(caTransform3D: toTransform) - anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) - anim2.fillMode = kCAFillModeForwards + anim2.timingFunction = CAMediaTimingFunction(name: mediaTimingFunctionEaseOut) + anim2.fillMode = fillModeForwards anim2.isRemovedOnCompletion = false self.activeBorder.layer.add(anim2, forKey: "_activeBorder") CATransaction.commit() @@ -433,12 +440,12 @@ open class EGFloatingTextField: UITextField { let toTransform = CATransform3DMakeScale(1.0, 1.0, 1) anim2.fromValue = NSValue(caTransform3D: fromTransform) anim2.toValue = NSValue(caTransform3D: toTransform) - anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) + anim2.timingFunction = CAMediaTimingFunction(name: mediaTimingFunctionEaseOut) let animGroup = CAAnimationGroup() animGroup.animations = [anim2] animGroup.duration = 0.3 - animGroup.fillMode = kCAFillModeForwards + animGroup.fillMode = fillModeForwards animGroup.isRemovedOnCompletion = false self.label.layer.add(animGroup, forKey: "_animateLabelBack") @@ -456,8 +463,8 @@ open class EGFloatingTextField: UITextField { let toTransform = CATransform3DMakeScale(0.01, 1.0, 1) anim2.fromValue = NSValue(caTransform3D: fromTransform) anim2.toValue = NSValue(caTransform3D: toTransform) - anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) - anim2.fillMode = kCAFillModeForwards + anim2.timingFunction = CAMediaTimingFunction(name: mediaTimingFunctionEaseOut) + anim2.fillMode = fillModeForwards anim2.isRemovedOnCompletion = false self.activeBorder.layer.add(anim2, forKey: "_activeBorder") CATransaction.commit() From a17e3eb8be79d669d331dcc014a903258a114905 Mon Sep 17 00:00:00 2001 From: Patrick Date: Sat, 1 Sep 2018 13:38:20 +0200 Subject: [PATCH 28/29] fix pod spec --- EGFloatingTextField.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EGFloatingTextField.podspec b/EGFloatingTextField.podspec index a31c93d..f0d41ab 100644 --- a/EGFloatingTextField.podspec +++ b/EGFloatingTextField.podspec @@ -2,10 +2,10 @@ Pod::Spec.new do |s| s.name = "EGFloatingTextField" s.version = "0.1.7" s.summary = "Implementation of Google's 'Floating labels' of Material design." - s.homepage = "https://github.com/enisgayretli/EGFloatingTextField" + s.homepage = "https://github.com/LaserPatrick/EGFloatingTextField" s.license = 'MIT' s.author = { "Enis Gayretli" => "enisgayretli@gmail.com" } - s.source = { :git => "https://github.com/LaserPatrick/EGFloatingTextField.git" } + s.source = { :git => "https://github.com/LaserPatrick/EGFloatingTextField.git", :tag => "#{s.version}" } s.social_media_url = 'https://twitter.com/enisgayretli' s.platform = :ios, '8.0' s.requires_arc = true From 786778005a040868cf83082263e5bbdccc48acac Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 14 Nov 2018 17:22:18 +0100 Subject: [PATCH 29/29] fix spec --- EGFloatingTextField.podspec | 16 ---------------- LaserFloatingTextField.podspec | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 16 deletions(-) delete mode 100644 EGFloatingTextField.podspec create mode 100644 LaserFloatingTextField.podspec diff --git a/EGFloatingTextField.podspec b/EGFloatingTextField.podspec deleted file mode 100644 index f0d41ab..0000000 --- a/EGFloatingTextField.podspec +++ /dev/null @@ -1,16 +0,0 @@ -Pod::Spec.new do |s| - s.name = "EGFloatingTextField" - s.version = "0.1.7" - s.summary = "Implementation of Google's 'Floating labels' of Material design." - s.homepage = "https://github.com/LaserPatrick/EGFloatingTextField" - s.license = 'MIT' - s.author = { "Enis Gayretli" => "enisgayretli@gmail.com" } - s.source = { :git => "https://github.com/LaserPatrick/EGFloatingTextField.git", :tag => "#{s.version}" } - s.social_media_url = 'https://twitter.com/enisgayretli' - s.platform = :ios, '8.0' - s.requires_arc = true - s.dependency 'PureLayout', '~>3.0' - s.source_files = 'EGFloatingTextField/EGFloatingTextField/*.swift' - s.resource = 'EGFloatingTextField/EGFloatingTextField/**/*.{lproj}' -end - diff --git a/LaserFloatingTextField.podspec b/LaserFloatingTextField.podspec new file mode 100644 index 0000000..5a9f19b --- /dev/null +++ b/LaserFloatingTextField.podspec @@ -0,0 +1,16 @@ +Pod::Spec.new do |s| + s.name = "LaserFloatingTextField" + s.version = "1.0.0" + s.summary = "Implementation of Google's 'Floating labels' of Material design." + s.homepage = "https://github.com/LaserSrl/LaserFloatingTextField" + s.license = 'MIT' + s.author = { "Patrick Laser" => "patrick.negretto@laser-group.com" } + s.source = { :git => "https://github.com/LaserSrl/LaserFloatingTextField.git", :tag => "#{s.version}" } + s.social_media_url = 'https://twitter.com/' + s.platform = :ios, '8.0' + s.requires_arc = true + s.dependency 'PureLayout', '~>3.0' + s.source_files = 'EGFloatingTextField/EGFloatingTextField/*.swift' + s.resource = 'EGFloatingTextField/EGFloatingTextField/**/*.{lproj}' +end +