From 611d131bd107155c1f55a5604c4ae767330ea5e6 Mon Sep 17 00:00:00 2001 From: Khoren Markosyan Date: Sun, 28 Jul 2019 15:26:32 +0400 Subject: [PATCH 1/9] Allow to set example phone number type --- Sources/FPNTextField.swift | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Sources/FPNTextField.swift b/Sources/FPNTextField.swift index 4750c559..6335e3ee 100644 --- a/Sources/FPNTextField.swift +++ b/Sources/FPNTextField.swift @@ -37,6 +37,7 @@ open class FPNTextField: UITextField, FPNCountryPickerDelegate, FPNDelegate { private lazy var phoneUtil: NBPhoneNumberUtil = NBPhoneNumberUtil() private var nbPhoneNumber: NBPhoneNumber? private var formatter: NBAsYouTypeFormatter? + private var exampleNumberType: NBEPhoneNumberType = .MOBILE public var flagButton: UIButton = UIButton() @@ -283,6 +284,13 @@ open class FPNTextField: UITextField, FPNCountryPickerDelegate, FPNDelegate { countryPicker.setup(with: countryCodes) } + /// Set the example phone number type + public func set(exampleNumberType: NBEPhoneNumberType) { + self.exampleNumberType = exampleNumberType + + updatePlaceholder() + } + // Private @objc private func didEditText() { @@ -408,7 +416,7 @@ open class FPNTextField: UITextField, FPNCountryPickerDelegate, FPNDelegate { private func updatePlaceholder() { if let countryCode = selectedCountry?.code { do { - let example = try phoneUtil.getExampleNumber(countryCode.rawValue) + let example = try phoneUtil.getExampleNumber(forType: countryCode.rawValue, type: exampleNumberType) let phoneNumber = "+\(example.countryCode.stringValue)\(example.nationalNumber.stringValue)" if let inputString = formatter?.inputString(phoneNumber) { From 22bb965e8cb60a9c194fe2b52d653c00a88c3556 Mon Sep 17 00:00:00 2001 From: Michael Gray Date: Fri, 16 Aug 2019 13:34:13 -0400 Subject: [PATCH 2/9] Clearer constraints --- Sources/FPNTextField.swift | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Sources/FPNTextField.swift b/Sources/FPNTextField.swift index 4750c559..ba58824c 100644 --- a/Sources/FPNTextField.swift +++ b/Sources/FPNTextField.swift @@ -139,14 +139,16 @@ open class FPNTextField: UITextField, FPNCountryPickerDelegate, FPNDelegate { wrapperView.addSubview(flagButton) wrapperView.addSubview(phoneCodeTextField) - let views = ["flag": flagButton, "textField": phoneCodeTextField] - let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|[flag][textField]|", options: [], metrics: nil, views: views) - - wrapperView.addConstraints(horizontalConstraints) - - for key in views.keys { - wrapperView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[\(key)]|", options: [], metrics: nil, views: views)) - } + NSLayoutConstraint.activate([ + flagButton.leadingAnchor.constraint(equalTo: wrapperView.leadingAnchor), + flagButton.topAnchor.constraint(equalTo: wrapperView.topAnchor), + flagButton.trailingAnchor.constraint(equalTo: phoneCodeTextField.leadingAnchor), + flagButton.bottomAnchor.constraint(equalTo: wrapperView.bottomAnchor), + + phoneCodeTextField.topAnchor.constraint(equalTo: wrapperView.topAnchor), + phoneCodeTextField.trailingAnchor.constraint(equalTo: wrapperView.trailingAnchor), + phoneCodeTextField.bottomAnchor.constraint(equalTo: wrapperView.bottomAnchor) + ]) leftView = wrapperView leftViewMode = .always From 83c3a68c9cf3012700f98535c1d27ac1ed0df0c7 Mon Sep 17 00:00:00 2001 From: Michael Gray Date: Fri, 16 Aug 2019 13:34:31 -0400 Subject: [PATCH 3/9] Should never call layoutSubviews directly --- Sources/FPNTextField.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/FPNTextField.swift b/Sources/FPNTextField.swift index ba58824c..3db679fe 100644 --- a/Sources/FPNTextField.swift +++ b/Sources/FPNTextField.swift @@ -13,14 +13,14 @@ open class FPNTextField: UITextField, FPNCountryPickerDelegate, FPNDelegate { /// The size of the flag @objc public var flagSize: CGSize = CGSize(width: 32, height: 32) { didSet { - layoutSubviews() + setNeedsLayout() } } /// The edges insets of the flag button @objc public var flagButtonEdgeInsets: UIEdgeInsets = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5) { didSet { - layoutSubviews() + setNeedsLayout() } } From e334beaac5db1ccaebf28e3ae1aa8b86ce48be95 Mon Sep 17 00:00:00 2001 From: Michael Gray Date: Fri, 16 Aug 2019 13:34:54 -0400 Subject: [PATCH 4/9] Set deployment to iOS 9.0 --- FlagPhoneNumber.xcodeproj/project.pbxproj | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/FlagPhoneNumber.xcodeproj/project.pbxproj b/FlagPhoneNumber.xcodeproj/project.pbxproj index 9fc15193..41cd32e7 100644 --- a/FlagPhoneNumber.xcodeproj/project.pbxproj +++ b/FlagPhoneNumber.xcodeproj/project.pbxproj @@ -397,7 +397,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -452,7 +452,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; @@ -478,6 +478,7 @@ ); INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -509,6 +510,7 @@ ); INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", From 182113978199a567e2b89cd099e020cafc5cbcda Mon Sep 17 00:00:00 2001 From: Michael Gray Date: Tue, 20 Aug 2019 08:33:32 -0400 Subject: [PATCH 5/9] Expand button to include area code text --- Sources/FPNTextField.swift | 75 +++++++++----------------------------- 1 file changed, 18 insertions(+), 57 deletions(-) diff --git a/Sources/FPNTextField.swift b/Sources/FPNTextField.swift index 3db679fe..b84add78 100644 --- a/Sources/FPNTextField.swift +++ b/Sources/FPNTextField.swift @@ -18,21 +18,13 @@ open class FPNTextField: UITextField, FPNCountryPickerDelegate, FPNDelegate { } /// The edges insets of the flag button - @objc public var flagButtonEdgeInsets: UIEdgeInsets = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5) { + @objc public var flagButtonEdgeInsets: UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 8) { didSet { + flagButton.contentEdgeInsets = flagButtonEdgeInsets setNeedsLayout() } } - /// The size of the leftView - private var leftViewSize: CGSize { - let width = flagSize.width + flagButtonEdgeInsets.left + flagButtonEdgeInsets.right + phoneCodeTextField.frame.width - let height = bounds.height - - return CGSize(width: width, height: height) - } - - private var phoneCodeTextField: UITextField = UITextField() private lazy var countryPicker: FPNCountryPicker = FPNCountryPicker() private lazy var phoneUtil: NBPhoneNumberUtil = NBPhoneNumberUtil() private var nbPhoneNumber: NBPhoneNumber? @@ -42,13 +34,13 @@ open class FPNTextField: UITextField, FPNCountryPickerDelegate, FPNDelegate { open override var font: UIFont? { didSet { - phoneCodeTextField.font = font + flagButton.titleLabel?.font = font } } open override var textColor: UIColor? { didSet { - phoneCodeTextField.textColor = textColor + flagButton.setTitleColor(textColor, for: .normal) } } @@ -99,17 +91,15 @@ open class FPNTextField: UITextField, FPNCountryPickerDelegate, FPNDelegate { open override func layoutSubviews() { super.layoutSubviews() - - flagButton.imageEdgeInsets = flagButtonEdgeInsets - updateLeftView() } private func setup() { setupFlagButton() - setupPhoneCodeTextField() - setupLeftView() setupCountryPicker() + leftView = flagButton + leftViewMode = .always + keyboardType = .phonePad autocorrectionType = .no addTarget(self, action: #selector(didEditText), for: .editingChanged) @@ -117,51 +107,22 @@ open class FPNTextField: UITextField, FPNCountryPickerDelegate, FPNDelegate { } private func setupFlagButton() { - flagButton.contentHorizontalAlignment = .fill + flagButton.setTitleColor(.black, for: .normal) flagButton.contentVerticalAlignment = .fill flagButton.imageView?.contentMode = .scaleAspectFit + flagButton.contentEdgeInsets = flagButtonEdgeInsets + flagButton.titleEdgeInsets = UIEdgeInsets(top: 0, left: 4, bottom: 0, right: -4) flagButton.accessibilityLabel = "flagButton" flagButton.addTarget(self, action: #selector(displayCountryKeyboard), for: .touchUpInside) flagButton.translatesAutoresizingMaskIntoConstraints = false flagButton.setContentCompressionResistancePriority(UILayoutPriority.defaultLow, for: .horizontal) } - private func setupPhoneCodeTextField() { - phoneCodeTextField.isUserInteractionEnabled = false - phoneCodeTextField.translatesAutoresizingMaskIntoConstraints = false - phoneCodeTextField.setContentHuggingPriority(UILayoutPriority.defaultHigh, for: .horizontal) - phoneCodeTextField.setContentCompressionResistancePriority(UILayoutPriority.defaultHigh, for: .horizontal) - } - - private func setupLeftView() { - let wrapperView = UIView(frame: CGRect(x: 0, y: 0, width: leftViewSize.width, height: leftViewSize.height)) - - wrapperView.addSubview(flagButton) - wrapperView.addSubview(phoneCodeTextField) - - NSLayoutConstraint.activate([ - flagButton.leadingAnchor.constraint(equalTo: wrapperView.leadingAnchor), - flagButton.topAnchor.constraint(equalTo: wrapperView.topAnchor), - flagButton.trailingAnchor.constraint(equalTo: phoneCodeTextField.leadingAnchor), - flagButton.bottomAnchor.constraint(equalTo: wrapperView.bottomAnchor), - - phoneCodeTextField.topAnchor.constraint(equalTo: wrapperView.topAnchor), - phoneCodeTextField.trailingAnchor.constraint(equalTo: wrapperView.trailingAnchor), - phoneCodeTextField.bottomAnchor.constraint(equalTo: wrapperView.bottomAnchor) - ]) - - leftView = wrapperView - leftViewMode = .always - } - - private func updateLeftView() { - let leftViewFrame: CGRect = leftView?.frame ?? .zero - let width: CGFloat = min(bounds.size.width, leftViewSize.width) - let height: CGFloat = min(bounds.size.height, leftViewSize.height) - let newRect: CGRect = CGRect(x: leftViewFrame.minX, y: leftViewFrame.minY, width: width, height: height) - - leftView?.frame = newRect - } + open override func leftViewRect(forBounds bounds: CGRect) -> CGRect { + var rect = super.leftViewRect(forBounds: bounds) + rect.size.width = flagButton.intrinsicContentSize.width + return rect + } private func setupCountryPicker() { countryPicker.countryPickerDelegate = self @@ -334,9 +295,9 @@ open class FPNTextField: UITextField, FPNCountryPickerDelegate, FPNDelegate { flagButton.setImage(selectedCountry?.flag, for: .normal) if let phoneCode = selectedCountry?.phoneCode { - phoneCodeTextField.text = phoneCode - phoneCodeTextField.sizeToFit() - layoutSubviews() + flagButton.setTitle(phoneCode, for: .normal) + flagButton.sizeToFit() + setNeedsLayout() } if hasPhoneNumberExample == true { From a73f9c85cfbdf2a311fe87d57e07a87ce0600215 Mon Sep 17 00:00:00 2001 From: Michael Gray Date: Wed, 21 Aug 2019 10:03:41 -0400 Subject: [PATCH 6/9] Add done button to phone keyboard Fix ambiguous layout issues --- Sources/FPNTextField.swift | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Sources/FPNTextField.swift b/Sources/FPNTextField.swift index b84add78..b0738855 100644 --- a/Sources/FPNTextField.swift +++ b/Sources/FPNTextField.swift @@ -64,9 +64,6 @@ open class FPNTextField: UITextField, FPNCountryPickerDelegate, FPNDelegate { /// If set, a search button appears in the picker inputAccessoryView to present a country search view controller @IBOutlet public var parentViewController: UIViewController? - /// Input Accessory View for the texfield - @objc public var textFieldInputAccessoryView: UIView? - init() { super.init(frame: .zero) @@ -114,7 +111,6 @@ open class FPNTextField: UITextField, FPNCountryPickerDelegate, FPNDelegate { flagButton.titleEdgeInsets = UIEdgeInsets(top: 0, left: 4, bottom: 0, right: -4) flagButton.accessibilityLabel = "flagButton" flagButton.addTarget(self, action: #selector(displayCountryKeyboard), for: .touchUpInside) - flagButton.translatesAutoresizingMaskIntoConstraints = false flagButton.setContentCompressionResistancePriority(UILayoutPriority.defaultLow, for: .horizontal) } @@ -138,7 +134,7 @@ open class FPNTextField: UITextField, FPNCountryPickerDelegate, FPNDelegate { @objc private func displayNumberKeyBoard() { inputView = nil - inputAccessoryView = textFieldInputAccessoryView + inputAccessoryView = getToolBar(with: getInputBarButtonItems()) tintColor = .gray reloadInputViews() } @@ -368,6 +364,15 @@ open class FPNTextField: UITextField, FPNCountryPickerDelegate, FPNDelegate { return [space, doneButton] } + private func getInputBarButtonItems() -> [UIBarButtonItem] { + let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) + let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(resetKeyBoard)) + + doneButton.accessibilityLabel = "doneButton" + + return [space, doneButton] + } + private func updatePlaceholder() { if let countryCode = selectedCountry?.code { do { From 6b0c51b3aa57ccca80a64f65956f0886999cb434 Mon Sep 17 00:00:00 2001 From: Michael Gray Date: Thu, 22 Aug 2019 07:13:03 -0400 Subject: [PATCH 7/9] Unnecessary and causes linker errors Already inherits from NSObjectProtocol so doesn't need @objc notation --- Sources/FPNTextFieldDelegate.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/FPNTextFieldDelegate.swift b/Sources/FPNTextFieldDelegate.swift index 42036c70..38e28a75 100644 --- a/Sources/FPNTextFieldDelegate.swift +++ b/Sources/FPNTextFieldDelegate.swift @@ -8,7 +8,6 @@ import UIKit -@objc public protocol FPNTextFieldDelegate: UITextFieldDelegate { func fpnDidSelectCountry(name: String, dialCode: String, code: String) func fpnDidValidatePhoneNumber(textField: FPNTextField, isValid: Bool) From 01952d93383e9f3b6d9c31e2efab52bdb964681a Mon Sep 17 00:00:00 2001 From: Michael Gray Date: Thu, 5 Sep 2019 10:06:19 -0400 Subject: [PATCH 8/9] Add some accessibility values --- Sources/FPNCountryPicker/FPNCountryPicker.swift | 7 ++++++- Sources/FPNCountryPicker/FPNCountryView.swift | 4 ++++ Sources/FPNTextField.swift | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Sources/FPNCountryPicker/FPNCountryPicker.swift b/Sources/FPNCountryPicker/FPNCountryPicker.swift index 9b2ccd18..5af7d434 100644 --- a/Sources/FPNCountryPicker/FPNCountryPicker.swift +++ b/Sources/FPNCountryPicker/FPNCountryPicker.swift @@ -1,6 +1,7 @@ import UIKit -open class FPNCountryPicker: UIPickerView, UIPickerViewDelegate, UIPickerViewDataSource { +open class FPNCountryPicker: UIPickerView, UIPickerViewAccessibilityDelegate, + UIPickerViewDataSource { var countries: [FPNCountry]! { didSet { @@ -192,4 +193,8 @@ open class FPNCountryPicker: UIPickerView, UIPickerViewDelegate, UIPickerViewDat countryPickerDelegate?.countryPhoneCodePicker(self, didSelectCountry: country) } } + + public func pickerView(_ pickerView: UIPickerView, accessibilityLabelForComponent component: Int) -> String? { + return "Country selector" + } } diff --git a/Sources/FPNCountryPicker/FPNCountryView.swift b/Sources/FPNCountryPicker/FPNCountryView.swift index aed0c73d..986302a1 100644 --- a/Sources/FPNCountryPicker/FPNCountryView.swift +++ b/Sources/FPNCountryPicker/FPNCountryView.swift @@ -18,5 +18,9 @@ class FPNCountryView: NibLoadingView { flagImageView.image = country.flag countryCodeLabel.text = country.phoneCode countryNameLabel.text = country.name + + isAccessibilityElement = true + accessibilityLabel = country.name + accessibilityValue = country.phoneCode } } diff --git a/Sources/FPNTextField.swift b/Sources/FPNTextField.swift index 4d56bc34..0068b1ed 100644 --- a/Sources/FPNTextField.swift +++ b/Sources/FPNTextField.swift @@ -301,6 +301,7 @@ open class FPNTextField: UITextField, FPNCountryPickerDelegate, FPNDelegate { if let phoneCode = selectedCountry?.phoneCode { flagButton.setTitle(phoneCode, for: .normal) flagButton.sizeToFit() + flagButton.accessibilityValue = phoneCode setNeedsLayout() } From 3d50268ea363f707bae728ddf83ea7ac0c52456b Mon Sep 17 00:00:00 2001 From: Michael Gray Date: Thu, 5 Sep 2019 10:07:55 -0400 Subject: [PATCH 9/9] Adjust position of country picker button Better text alignment between button and the textfield --- Sources/FPNTextField.swift | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Sources/FPNTextField.swift b/Sources/FPNTextField.swift index 0068b1ed..8a7cca78 100644 --- a/Sources/FPNTextField.swift +++ b/Sources/FPNTextField.swift @@ -87,10 +87,6 @@ open class FPNTextField: UITextField, FPNCountryPickerDelegate, FPNDelegate { parentViewController = nil } - open override func layoutSubviews() { - super.layoutSubviews() - } - private func setup() { setupFlagButton() setupCountryPicker() @@ -116,9 +112,10 @@ open class FPNTextField: UITextField, FPNCountryPickerDelegate, FPNDelegate { } open override func leftViewRect(forBounds bounds: CGRect) -> CGRect { - var rect = super.leftViewRect(forBounds: bounds) - rect.size.width = flagButton.intrinsicContentSize.width - return rect + return CGRect( + x: 0, y: 0, + width: flagButton.intrinsicContentSize.width, + height: bounds.height - 0.5) } private func setupCountryPicker() {