Skip to content

Instantly share code, notes, and snippets.

@ranmyfriend
Created March 10, 2017 22:46
Show Gist options
  • Save ranmyfriend/6e731bf4bd268528112c6e97d8ec5ad4 to your computer and use it in GitHub Desktop.
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.
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