Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions AnimatedField/Classes/AnimatedField+TextFieldDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ extension AnimatedField: UITextFieldDelegate {
return shouldChange
}

let sstring = string.toEnglish()

// Copy new character
var newInput = string
var newInput = sstring

// Replace special characters in newInput
newInput = newInput.replacingOccurrences(of: "`", with: "")
Expand All @@ -43,7 +45,7 @@ extension AnimatedField: UITextFieldDelegate {
if !newInput.isValidWithRegEx(regex) && newInput != "" { return false }

// Change textfield in manual mode in case of changing newInput. Check limits also
if newInput != string {
if newInput != sstring {
textField.text = textField.text?.count ?? 0 + newInput.count <= limit ? "\(textField.text ?? "")\(newInput)" : textField.text
return false
}
Expand Down
25 changes: 20 additions & 5 deletions AnimatedField/Classes/AnimatedField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ open class AnimatedField: UIView {
private var datePicker: UIDatePicker?
private var initialDate: Date?
private var dateFormat: String?
private var isPersian: Bool = true

/// Picker values
private var numberPicker: UIPickerView?
Expand Down Expand Up @@ -109,10 +110,10 @@ open class AnimatedField: UIView {
/// Field type (default values)
public var type: AnimatedFieldType = .none {
didSet {
if case let AnimatedFieldType.datepicker(mode, defaultDate, minDate, maxDate, chooseText, format) = type {
if case let AnimatedFieldType.datepicker(mode, defaultDate, minDate, maxDate, chooseText, format, bgColor, isPersian) = type {
initialDate = defaultDate
dateFormat = format
setupDatePicker(mode: mode, minDate: minDate, maxDate: maxDate, chooseText: chooseText)
setupDatePicker(mode: mode, minDate: minDate, maxDate: maxDate, chooseText: chooseText, bgColor: bgColor, isPersian: isPersian)
}
if case let AnimatedFieldType.numberpicker(defaultNumber, minNumber, maxNumber, chooseText) = type {
setupPicker(defaultNumber: defaultNumber, minNumber: minNumber, maxNumber: maxNumber, chooseText: chooseText)
Expand Down Expand Up @@ -316,12 +317,26 @@ open class AnimatedField: UIView {
layoutIfNeeded()
}

private func setupDatePicker(mode: UIDatePicker.Mode?, minDate: Date?, maxDate: Date?, chooseText: String?) {
private func setupDatePicker(mode: UIDatePicker.Mode?, minDate: Date?, maxDate: Date?, chooseText: String?, bgColor: UIColor?, isPersian: Bool = true) {
datePicker = UIDatePicker()
datePicker?.datePickerMode = mode ?? .date
if #available(iOS 13.4, *) {
datePicker?.preferredDatePickerStyle = .wheels
} else {
// Fallback on earlier versions
}
self.isPersian = isPersian
datePicker?.maximumDate = maxDate
datePicker?.minimumDate = minDate
datePicker?.setValue(format.textColor, forKey: "textColor")
if isPersian {
datePicker?.datePickerMode = .date
datePicker?.calendar = Calendar(identifier: .persian)
datePicker?.locale = Locale(identifier: "fa_IR")
}
if let bgcolor = bgColor {
datePicker?.backgroundColor = bgcolor
}

let toolBar = UIToolbar(target: self, selector: #selector(didChooseDatePicker))

Expand Down Expand Up @@ -366,9 +381,9 @@ open class AnimatedField: UIView {
delegate?.animatedFieldDidChange(self)
}

@objc func didChooseDatePicker() {
@objc func didChooseDatePicker(sender: Any) {
let date = datePicker?.date ?? initialDate
textField.text = date?.format(dateFormat: dateFormat ?? "dd / MM / yyyy")
textField.text = date?.format(dateFormat: dateFormat ?? "dd / MM / yyyy", isPersian: isPersian)
_ = resignFirstResponder()
}

Expand Down
10 changes: 9 additions & 1 deletion AnimatedField/Classes/AnimatedFieldType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ public enum AnimatedFieldType {
case password(Int, Int) // min, max
case price(Double, Int) // max price, max decimals
case url
case datepicker(UIDatePicker.Mode?, Date?, Date?, Date?, String?, String?) // mode, default date, min date, max date, choose text, date format
case datepicker(UIDatePicker.Mode?, Date?, Date?, Date?, String?, String?, UIColor?, Bool) // mode, default date, min date, max date, choose text, date format
case numberpicker(Int, Int, Int, String?) // default number, min number, max number, choose text
case multiline
case numeric
case iranianCellphoneNumber

var decimal: String {
var separator = Locale.current.decimalSeparator ?? "\\."
Expand All @@ -31,6 +33,8 @@ public enum AnimatedFieldType {
case .email: return "[A-Z0-9a-z@_\\.]"
case .username: return "[A-Za-z0-9_.]"
case .price: return "[0-9\(decimal)]"
case .numeric: return "[0-9]"
case .iranianCellphoneNumber: return "[0-9]"
default: return ".*"
}
}
Expand All @@ -42,6 +46,8 @@ public enum AnimatedFieldType {
case .password(let min, let max): return ".{\(min),\(max)}"
case .price(_, let max): return "^(?=.*[1-9])([1-9]\\d*(?:\(decimal)\\d{1,\(max)})?|(?:0\(decimal)\\d{1,\(max)}))$"
case .url: return "https?:\\/\\/(?:www\\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|www\\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|https?:\\/\\/(?:www\\.|(?!www))[a-zA-Z0-9]+\\.[^\\s]{2,}|www\\.[a-zA-Z0-9]+\\.[^\\s]{2,}"
case .numeric: return "[0-9]"
case .iranianCellphoneNumber: return "^(0)?9\\d{9}$"
default: return ".*"
}
}
Expand All @@ -53,6 +59,8 @@ public enum AnimatedFieldType {
case .password: return "Password is not valid!"
case .price: return "Price is not valid!"
case .url: return "Url is not valid!"
case .numeric: return "Number is not valid!"
case .iranianCellphoneNumber: return "Cellphone number is not valid!"
default: return ""
}
}
Expand Down
6 changes: 5 additions & 1 deletion AnimatedField/Classes/Extensions/Date+Format.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ import Foundation

extension Date {

func format(dateFormat: String) -> String {
func format(dateFormat: String, isPersian: Bool) -> String {
let dateFormatter = DateFormatter()
if isPersian {
dateFormatter.calendar = Calendar(identifier: .persian)
dateFormatter.locale = Locale(identifier: "fa_IR")
}
dateFormatter.dateFormat = dateFormat
return dateFormatter.string(from: self)
}
Expand Down
21 changes: 21 additions & 0 deletions AnimatedField/Classes/Extensions/String+RegEx.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,25 @@ extension String {
let pred = NSPredicate(format:"SELF MATCHES %@", regEx)
return pred.evaluate(with: self)
}

func toEnglish() -> String {
let dic = [
"۰" : "0",
"۱" : "1" ,
"۲" : "2",
"۳" : "3",
"۴" : "4",
"۵" : "5" ,
"۶" : "6",
"۷" : "7",
"۸" : "8",
"۹" : "9"
] as Dictionary

var result : String = self
for (key, value) in dic {
result = result.replacingOccurrences(of: key, with: value)
}
return result
}
}
2 changes: 1 addition & 1 deletion Example/AnimatedField/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class ViewController: UIViewController {
let maxDate = Date().addingTimeInterval(-13 * 365 * 24 * 60 * 60)
let chooseText = "Choose"
let dateFormat = "dd / MM / yyyy"
birthdateAnimatedField.type = .datepicker(.dateAndTime, defaultDate, minDate, maxDate, chooseText, dateFormat)
birthdateAnimatedField.type = .datepicker(.dateAndTime, defaultDate, minDate, maxDate, chooseText, dateFormat, .black, true)
birthdateAnimatedField.tag = 2

numberAnimatedField.format = format
Expand Down