Created
March 10, 2017 22:46
-
-
Save ranmyfriend/6e731bf4bd268528112c6e97d8ec5ad4 to your computer and use it in GitHub Desktop.
Phone Number - OneTimePassword Inputview design code and the fancy here is cursor going forward and backward is awesome.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
protocol OTPInputViewProtocol:class { | |
func digitsInputViewCompletion() | |
} | |
fileprivate let MAX_COUNT_DOWN_TIME:Int = 120 | |
class ADOTPInputView: UIView,UITextFieldDelegate { | |
@IBOutlet weak var digit1: DigitTextField! | |
@IBOutlet weak var digit2: DigitTextField! | |
@IBOutlet weak var digit3: DigitTextField! | |
@IBOutlet weak var digit4: DigitTextField! | |
@IBOutlet weak var countDownView: UIView! | |
private var timer:Timer? | |
private var max_Time = MAX_COUNT_DOWN_TIME | |
public weak var delegate:OTPInputViewProtocol? | |
//MARK: - Custom Getters and Setters | |
lazy var countDownLabel: UILabel = { | |
let label = UILabel() | |
label.frame = CGRect(x:0,y:0,width:self.countDownView.frame.width,height:self.countDownView.frame.height) | |
label.font = Utilities.appThemeLightFontWithSize(size: 14) | |
label.textColor = UIColor.rgb(fromHex: 0x6A1B9A) | |
label.text = "2:00" | |
label.textAlignment = .center | |
label.addKernAttribute() | |
label.addGestureRecognizer(self.tapper) | |
return label | |
}() | |
lazy var tapper: UITapGestureRecognizer = { | |
let tapGesture = UITapGestureRecognizer.init(target: self, action: #selector(startOTPTimer)) | |
tapGesture.numberOfTapsRequired = 1 | |
return tapGesture | |
}() | |
// if appropriate, make sure to stop your timer in `deinit` | |
deinit { | |
stopTimer() | |
} | |
//MARK: - Public functions | |
public func startOTPTimer() { | |
self.countDownLabel.isUserInteractionEnabled = false | |
self.timer = Timer.scheduledTimer(timeInterval: 0.25, target: self, selector: #selector(self.update), userInfo: nil, repeats: true) | |
} | |
public func stopTimer() { | |
timer?.invalidate() | |
} | |
public func initalViewSetup() { | |
self.digit1.delegate = self | |
self.digit2.delegate = self | |
self.digit3.delegate = self | |
self.digit4.delegate = self | |
self.digit1.addTarget(self, action: #selector(textFieldDidChange), for: UIControlEvents.editingChanged) | |
self.digit2.addTarget(self, action: #selector(textFieldDidChange), for: UIControlEvents.editingChanged) | |
self.digit3.addTarget(self, action: #selector(textFieldDidChange), for: UIControlEvents.editingChanged) | |
self.digit4.addTarget(self, action: #selector(textFieldDidChange), for: UIControlEvents.editingChanged) | |
self.digit1.becomeFirstResponder() | |
self.digit2.isEnabled = false | |
self.digit3.isEnabled = false | |
self.digit4.isEnabled = false | |
self.countDownView.addSubview(countDownLabel) | |
NotificationCenter.default.addObserver(self, selector: #selector(gotoPreviousDigits), name: NSNotification.Name(rawValue: "deletePressed"), object: nil) | |
} | |
//MARK: - Private functions | |
@objc private func update() { | |
max_Time -= 1 | |
if(max_Time > 0){ | |
let minutes = String(max_Time / 60) | |
let seconds = String(max_Time % 60) | |
DispatchQueue.main.async { | |
self.countDownLabel.text = minutes + " : " + seconds | |
} | |
} | |
if max_Time == 1 { | |
self.countDownLabel.isUserInteractionEnabled = true | |
self.timer?.invalidate() | |
self.max_Time = MAX_COUNT_DOWN_TIME | |
DispatchQueue.main.async { | |
self.countDownLabel.attributedText = self.attributedString(from: "Time elapsed. Resend code", resendCodeColorRange: NSMakeRange(0, 13)) | |
} | |
} | |
} | |
//MARK: - Private functions | |
private func attributedString(from string: String, resendCodeColorRange: NSRange?) -> NSAttributedString { | |
let attrs = [ | |
NSForegroundColorAttributeName:self.countDownLabel.textColor | |
] | |
let blackColorAttr = [ | |
NSForegroundColorAttributeName: UIColor.rgb(fromHex: 0x2D4059), | |
] | |
let attrStr = NSMutableAttributedString(string: string, attributes: attrs) | |
attrStr.setAttributes(blackColorAttr, range: resendCodeColorRange!) | |
return attrStr | |
} | |
//MARK: - UITextField Delegates | |
func textFieldDidChange(textField: UITextField){ | |
let text = textField.text | |
if text?.utf16.count==1{ | |
switch textField{ | |
case self.digit1: | |
self.digit2.isEnabled = true | |
self.digit2.becomeFirstResponder() | |
case self.digit2: | |
self.digit3.isEnabled = true | |
self.digit3.becomeFirstResponder() | |
case self.digit3: | |
self.digit4.isEnabled = true | |
self.digit4.becomeFirstResponder() | |
case self.digit4: | |
self.digit4.isEnabled = false | |
self.digit4.resignFirstResponder() | |
self.delegate?.digitsInputViewCompletion() | |
default: | |
break | |
} | |
}else{ | |
} | |
} | |
//MARK: - Observers | |
func gotoPreviousDigits() { | |
if digit2.isFirstResponder { | |
digit2.isEnabled = false | |
digit1.isEnabled = true | |
digit1.becomeFirstResponder() | |
} else if digit3.isFirstResponder { | |
digit3.isEnabled = false | |
digit2.isEnabled = true | |
digit2.becomeFirstResponder() | |
} else if digit4.isFirstResponder { | |
digit4.isEnabled = false | |
digit3.isEnabled = true | |
digit3.becomeFirstResponder() | |
} | |
} | |
} | |
class DigitTextField: UITextField { | |
override func deleteBackward() { | |
super.deleteBackward() | |
NotificationCenter.default.post(name: Notification.Name(rawValue: "deletePressed"), object: nil) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment