├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING ├── LICENSE ├── README.md ├── SSFloatingLabelTextField.podspec ├── SSFloatingLabelTextField ├── Assests │ └── Images.xcassets │ │ ├── Contents.json │ │ ├── eyeClose.imageset │ │ ├── Contents.json │ │ └── visibility.png │ │ └── eyeOpen.imageset │ │ ├── Contents.json │ │ └── view.png └── Classes │ ├── Constants + Enums.swift │ ├── SSFloatingLabelTextField.swift │ └── StringExtension.swift ├── SSFloatingTextFieldDemo ├── Podfile ├── SSFloatingTextFieldDemo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── SSFloatingTextFieldDemo.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── SSFloatingTextFieldDemo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Info.plist │ ├── LaunchScreen.storyboard │ ├── Main.storyboard │ └── ViewController.swift └── screenshots ├── Installation.png ├── SSFloatingTextField.gif └── simformBanner.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Add any directories, files, or patterns you don't want to be tracked by version control 2 | # Xcode 3 | # 4 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 5 | 6 | 7 | 8 | ## Build generated 9 | build/ 10 | DerivedData/ 11 | 12 | 13 | 14 | ## Various settings 15 | *.pbxuser 16 | !default.pbxuser 17 | *.mode1v3 18 | !default.mode1v3 19 | *.mode2v3 20 | !default.mode2v3 21 | *.perspectivev3 22 | !default.perspectivev3 23 | xcuserdata/ 24 | *.generated.swift 25 | 26 | 27 | ## Other 28 | *.moved-aside 29 | *.xccheckout 30 | *.xcscmblueprint 31 | 32 | 33 | 34 | ## Obj-C/Swift specific 35 | *.hmap 36 | *.ipa 37 | *.dSYM.zip 38 | *.dSYM 39 | 40 | 41 | 42 | ## Playgrounds 43 | timeline.xctimeline 44 | playground.xcworkspace 45 | 46 | 47 | 48 | # Swift Package Manager 49 | # 50 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 51 | # Packages/ 52 | # Package.pins 53 | # Package.resolved 54 | .build/ 55 | 56 | 57 | 58 | # CocoaPods 59 | # 60 | # We recommend against adding the Pods directory to your .gitignore. However 61 | # you should judge for yourself, the pros and cons are mentioned at: 62 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 63 | # 64 | Pods/ 65 | 66 | 67 | 68 | # Carthage 69 | # 70 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 71 | # Carthage/Checkouts 72 | 73 | 74 | 75 | Carthage/Build 76 | 77 | 78 | 79 | # fastlane 80 | # 81 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 82 | # screenshots whenever they are needed. 83 | # For more information about the recommended setup visit: 84 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 85 | 86 | 87 | 88 | fastlane/report.xml 89 | fastlane/Preview.html 90 | fastlane/screenshots 91 | fastlane/test_output 92 | .DS_Store 93 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at mohammed.h@simformsolutions.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | # Way to contribute 2 | 3 | 1. Fork the repo and create your branch from `master`. 4 | 2. Clone the project to your own machine. (Please have a look at [**Readme.md**](https://github.com/SimformSolutionsPvtLtd/Kotlin-multiplatform-sample/blob/master/README.md) to understand how to run this project on your machine) 5 | 3. Commit changes to your own branch 6 | 4. Make sure your code lints. 7 | 5. Push your work back up to your fork. 8 | 6. Issue that pull request! 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 mobile-simformsolutions 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [![Platform][platform-image]][platform-url] 4 | [![Swift Version][swift-image]][swift-url] 5 | [![License][license-image]][license-url] 6 | [![PRs Welcome][PR-image]][PR-url] 7 | 8 | # SSFloatingLabelTextField 9 | 10 | SSFloatingLabelTextField is a small library for iOS which supports Floating labels and errors with different kind of validations. Also user can add/customise own validation and error messages. 11 | 12 | ![Alt text](https://github.com/mobile-simformsolutions/SSFloatingLabelTextField/blob/main/screenshots/SSFloatingTextField.gif?raw=true) 13 | 14 | # Features! 15 | 16 | Main Features include :- 17 | - Floating Placeholder label 18 | - Set different validations type 19 | - Set Custom regex for validation or for phone number formatter 20 | - Check if text is valid or not and display error message 21 | 22 | All Attributes :- 23 | | Attribute | Description | 24 | | --- | --- | 25 | | `floatingLabelText` | Floating Placeholder label 26 | | `selectedLabelColor` | Color of Floating label when textfield is active 27 | | `unSelectedLabelColor` | Color of Floating label when textfield is active 28 | | `errorText` | Error message when text is not valid 29 | | `errorTextColor` | Color in which error message is shown 30 | | `type` | Set Validation type 31 | | `customValidationRegex` | Set Custom Regex for Validation 32 | | `isPasswordToggleEnable` | Toggle show hide password 33 | | `showPasswordImage` | Toggle image when password is visible 34 | | `hidePasswordImage` | Toggle image when password is visible 35 | 36 | # Requirements 37 | - iOS 11.0+ 38 | - Xcode 11+ 39 | 40 | # Installation 41 | #### CocoaPods 42 | 43 | - You can use CocoaPods to install `SSFloatingLabelTextField` by adding it to your Podfile: 44 | 45 | use_frameworks! 46 | pod 'SSFloatingLabelTextField' 47 | 48 | - Import SSFloatingLabelTextField in your file: 49 | 50 | import SSFloatingLabelTextField 51 | 52 | **Manually** 53 | - Download and drop **SSFloatingLabelTextField/Sources** folder in your project. 54 | - Congratulations! 55 | 56 | 57 | # Usage example 58 | 59 | In the storyboard add a UITextField and change its class to SSFloatingLabelTextField 60 | 61 | 62 | 63 | Import SSFloatingLabelTextField 64 | 65 | import SSFloatingLabelTextField 66 | 67 | Set text type in your View Controller file :- 68 | 69 | @IBOutlet weak var txtUsername: SSFloatingLabelTextField! // Add IBOutlet 70 | txtEmail.type = .email // Assign type as email 71 | txtPassword.type = .password(passwordRule: .medium) // Assign type as password 72 | txtPhoneNumber.type = .phoneNumber(formatterString: nil) // Assign type as phone number (Params :- Phone number formatter default :- XXX-XXX-XXXX ) 73 | 74 | Check if given text field is valid or not :- 75 | 76 | txtUsername.isValid() 77 | 78 | 79 | ## Find this library useful? :heart: 80 | Support it by joining __[stargazers](https://github.com/mobile-simformsolutions/SSFloatingLabelTextField/stargazers)__ for this repository. :star: 81 | 82 | ## 🤝 How to Contribute 83 | 84 | Whether you're helping us fix bugs, improve the docs, or a feature request, we'd love to have you! :muscle: 85 | 86 | Check out our [**Contributing Guide**](https://github.com/mobile-simformsolutions/SSFloatingLabelTextField/blob/master/CONTRIBUTING.md) for ideas on contributing. 87 | 88 | ## Bugs and Feedback 89 | 90 | For bugs, feature requests, and discussion please use [GitHub Issues](https://github.com/mobile-simformsolutions/SSFloatingLabelTextField/issues). 91 | 92 | 93 | # Meta 94 | - This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details 95 | 96 | 97 | [swift-image]:https://img.shields.io/badge/swift-5.0-orange.svg 98 | [swift-url]: https://swift.org/ 99 | [license-image]: https://img.shields.io/badge/License-MIT-blue.svg 100 | [license-url]: LICENSE 101 | [platform-image]:https://img.shields.io/cocoapods/p/LFAlertController.svg?style=flat 102 | [platform-url]:https://github.com/mobile-simformsolutions/SSSwiftUISpinnerButton 103 | [PR-image]:https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square 104 | [PR-url]:http://makeapullrequest.com 105 | -------------------------------------------------------------------------------- /SSFloatingLabelTextField.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint SSFloatingLabelTextField.podspec' to ensure this is a 3 | # valid spec and to remove all comments including this before submitting the spec. 4 | # 5 | # To learn more about Podspec attributes see https://guides.cocoapods.org/syntax/podspec.html 6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ 7 | # 8 | 9 | Pod::Spec.new do |spec| 10 | 11 | spec.name = "SSFloatingLabelTextField" 12 | spec.version = "1.0.0" 13 | spec.summary = "A small framework to use Floating label and show errors of SSFloatingLabelTextField." 14 | spec.description = "A small framework to use Floating label and show errors of SSFloatingLabelTextField." 15 | 16 | spec.homepage = "https://github.com/mobile-simformsolutions/SSFloatingLabelTextField" 17 | spec.license = { :type => "MIT", :file => "LICENSE" } 18 | spec.author = { 'Simform Solutions' => 'developer@simform.com' } 19 | spec.platform = :ios 20 | spec.ios.deployment_target = "11.0" 21 | spec.swift_versions = '5.0' 22 | 23 | spec.source = { :git => "https://github.com/mobile-simformsolutions/SSFloatingLabelTextField", :tag => "#{spec.version}" } 24 | 25 | spec.source_files = "SSFloatingLabelTextField/Classes/**" 26 | spec.framework = 'UIKit' 27 | 28 | end 29 | -------------------------------------------------------------------------------- /SSFloatingLabelTextField/Assests/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SSFloatingLabelTextField/Assests/Images.xcassets/eyeClose.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "visibility.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SSFloatingLabelTextField/Assests/Images.xcassets/eyeClose.imageset/visibility.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/SSFloatingLabelTextField/3b425b141df546d19bf726525e10caa04c699172/SSFloatingLabelTextField/Assests/Images.xcassets/eyeClose.imageset/visibility.png -------------------------------------------------------------------------------- /SSFloatingLabelTextField/Assests/Images.xcassets/eyeOpen.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "view.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SSFloatingLabelTextField/Assests/Images.xcassets/eyeOpen.imageset/view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/SSFloatingLabelTextField/3b425b141df546d19bf726525e10caa04c699172/SSFloatingLabelTextField/Assests/Images.xcassets/eyeOpen.imageset/view.png -------------------------------------------------------------------------------- /SSFloatingLabelTextField/Classes/Constants + Enums.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Constants + Enums.swift 3 | // SSFloatingLabelTextField 4 | // 5 | // Created by Mohammed Hanif on 30/06/21. 6 | // 7 | 8 | import Foundation 9 | 10 | public class Constants { 11 | static let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}" 12 | // Minimum eight characters, at least one letter, one number and one special character: 13 | static let weakPasswordRegex = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@$!%*#?&])[A-Za-z\\d@$!%*#?&]{8,}$" 14 | // Minimum eight characters, at least one uppercase letter, one lowercase letter, one number and one special character: 15 | static let mediumPasswordRegex = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$" 16 | // Minimum eight and maximum 10 characters, at least one uppercase letter, one lowercase letter, one number and one special character: 17 | static let strongPasswordRegex = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,10}$" 18 | // Phone number formatter mask 19 | static var phoneNumberMask = "XXX-XXX-XXXX" 20 | } 21 | 22 | public enum Type { 23 | case email 24 | case password(passwordRule: PasswordRule) 25 | case phoneNumber(formatterString: String?) 26 | } 27 | 28 | public enum PasswordRule { 29 | case weak 30 | case medium 31 | case strong 32 | } 33 | -------------------------------------------------------------------------------- /SSFloatingLabelTextField/Classes/SSFloatingLabelTextField.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SSFloatingLabelTextField.swift 3 | // SSFloatingLabelTextField 4 | // 5 | // Created by Mohammed Hanif on 21/06/21. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | import Combine 11 | 12 | open class SSFloatingLabelTextField: UITextField { 13 | 14 | // MARK:- Variables 15 | /// placeholder label 16 | var placeholderLabel: UILabel = UILabel(frame: CGRect.zero) 17 | /// Error Label 18 | var errorLabel: UILabel = UILabel(frame: CGRect.zero) 19 | // Default height 20 | var placeholderLabelHeight: CGFloat = 14 21 | // Set any predefine validation type 22 | open var type: Type? { 23 | didSet { 24 | switch type { 25 | case .email: 26 | self.keyboardType = .emailAddress 27 | case .phoneNumber: 28 | self.keyboardType = .numberPad 29 | default: 30 | break 31 | } 32 | } 33 | } 34 | // Button for toggle password 35 | let button = UIButton(type: .custom) 36 | 37 | // Defines Placeholder label text 38 | @IBInspectable 39 | open var floatingLabelText: String? 40 | 41 | // Defines error text which will be displayed when text is not valid 42 | @IBInspectable 43 | open var errorText: String? { 44 | didSet { 45 | errorLabel.text = errorText 46 | setNeedsDisplay() 47 | } 48 | } 49 | 50 | // Color of error text 51 | @IBInspectable 52 | open var errorTextColor: UIColor = UIColor.black { 53 | didSet { 54 | errorLabel.textColor = errorTextColor 55 | setNeedsDisplay() 56 | } 57 | } 58 | 59 | // Color for floating label By defaul :- Blue 60 | @IBInspectable 61 | open var selectedLabelColor: UIColor = UIColor.blue 62 | 63 | // Color for floating label By defaul :- Grey 64 | @IBInspectable 65 | open var unSelectedLabelColor: UIColor = UIColor.gray 66 | 67 | // Set Custom regex for Text Validation 68 | @IBInspectable 69 | var customValidationRegex: String? 70 | 71 | @available(iOS 13.0, *) 72 | private(set) lazy var cancellables = [AnyCancellable]() 73 | 74 | // Set if you want to show hide password with icon 75 | @IBInspectable 76 | open var isPasswordToggleEnable: Bool = false { 77 | didSet { 78 | if isPasswordToggleEnable { 79 | enablePasswordToggle() 80 | } 81 | } 82 | } 83 | 84 | // Toggle image when password is shown (Only required if password toggle is enable) 85 | @IBInspectable 86 | open var showPasswordImage: UIImage? = UIImage(named: "eyeOpen") { 87 | didSet { 88 | setPasswordToggleImage(button) 89 | } 90 | } 91 | 92 | // Toggle image when password is hidden (Only required if password toggle is enable) 93 | @IBInspectable 94 | open var hidePasswordImage: UIImage? = UIImage(named: "eyeClose") { 95 | didSet { 96 | setPasswordToggleImage(button) 97 | } 98 | } 99 | 100 | required public init?(coder aDecoder: NSCoder) { 101 | super.init(coder: aDecoder) 102 | baseSetup() 103 | } 104 | 105 | override init(frame: CGRect) { 106 | super.init(frame: frame) 107 | baseSetup() 108 | } 109 | 110 | @objc func onEditingChanged() { 111 | updateValidation() 112 | } 113 | 114 | /// On Textfield editing end 115 | @objc func onEditingEnd() { 116 | placeholderLabel.textColor = unSelectedLabelColor 117 | setNeedsDisplay() 118 | } 119 | 120 | /// /// On Textfield editing begin 121 | @objc func onEditingBegin() { 122 | placeholderLabel.textColor = selectedLabelColor 123 | setNeedsDisplay() 124 | } 125 | 126 | /// When toggle password is clicked 127 | /// - Parameter sender: UIButton used for toggle 128 | @IBAction func togglePasswordView(_ sender: UIButton) { 129 | self.isSecureTextEntry = !self.isSecureTextEntry 130 | setPasswordToggleImage(sender) 131 | } 132 | 133 | /// Initial Setup 134 | fileprivate func baseSetup() { 135 | placeholderLabel = UILabel(frame: CGRect.zero) 136 | addTarget(self, action: #selector(self.onEditingBegin), for: .editingDidBegin) 137 | addTarget(self, action: #selector(self.onEditingEnd), for: .editingDidEnd) 138 | addError() 139 | if #available(iOS 13.0, *) { 140 | setUpValidations() 141 | } else { 142 | addTarget(self, action: #selector(self.onEditingChanged), for: .editingChanged) 143 | } 144 | } 145 | 146 | /// Add Validations 147 | @available(iOS 13.0, *) 148 | func setUpValidations() { 149 | NotificationCenter.default.publisher(for: SSFloatingLabelTextField.textDidChangeNotification, object: self) 150 | .sink { (text) in 151 | self.updateValidation() 152 | }.store(in: &cancellables) 153 | } 154 | 155 | /// Set password toggle images 156 | /// - Parameter button: UI Button which is used for toggle 157 | func setPasswordToggleImage(_ button: UIButton) { 158 | if(isSecureTextEntry) { 159 | button.setImage(hidePasswordImage, for: .normal) 160 | } else { 161 | button.setImage(showPasswordImage, for: .normal) 162 | } 163 | } 164 | 165 | /// Enable password toggle 166 | func enablePasswordToggle(){ 167 | button.imageEdgeInsets = UIEdgeInsets(top: 0, left: -16, bottom: 0, right: 0) 168 | button.frame = CGRect(x: CGFloat(self.frame.size.width - 25), y: CGFloat(5), width: CGFloat(25), height: CGFloat(25)) 169 | button.addTarget(self, action: #selector(self.togglePasswordView), for: .touchUpInside) 170 | self.rightView = button 171 | self.rightViewMode = .always 172 | setPasswordToggleImage(button) 173 | } 174 | 175 | /// Validate text according to the validation types 176 | func updateValidation() { 177 | self.addFloatingLabel() 178 | guard let _validationType = self.type else { 179 | self.validate(regex: nil) 180 | return 181 | } 182 | switch _validationType { 183 | case .phoneNumber(let formatterString): 184 | text = text?.format(with: formatterString ?? Constants.phoneNumberMask) 185 | self.addFloatingLabel() 186 | default: 187 | break 188 | } 189 | if self.customValidationRegex != nil { 190 | self.validate(regex: self.customValidationRegex) 191 | } else { 192 | switch _validationType { 193 | case .email: 194 | self.validate(regex: Constants.emailRegex) 195 | case .password(let rule): 196 | switch rule { 197 | case .weak: 198 | self.validate(regex: Constants.weakPasswordRegex) 199 | case .medium: 200 | self.validate(regex: Constants.mediumPasswordRegex) 201 | case .strong: 202 | self.validate(regex: Constants.strongPasswordRegex) 203 | } 204 | case .phoneNumber(let mask): 205 | if self.text?.count == (mask?.count ?? Constants.phoneNumberMask.count) { 206 | remmoveError() 207 | } else { 208 | addError() 209 | } 210 | } 211 | } 212 | } 213 | 214 | /// Validate any regex ans show hide error 215 | /// - Parameter regex: regex which needs to be validated 216 | func validate(regex: String?) { 217 | if text?.isValidRegex(regex: regex) ?? false { 218 | remmoveError() 219 | } else { 220 | addError() 221 | } 222 | } 223 | 224 | /// Add label if not already added 225 | func addFloatingLabel() { 226 | if text != "" { 227 | if (self.subviews.contains(placeholderLabel)) { 228 | return 229 | } 230 | placeholderLabel.textColor = selectedLabelColor 231 | placeholderLabel.font = UIFont.systemFont(ofSize: 15.0) 232 | placeholderLabel.text = floatingLabelText 233 | placeholderLabel.layer.backgroundColor = UIColor.white.cgColor 234 | placeholderLabel.translatesAutoresizingMaskIntoConstraints = false 235 | placeholderLabel.clipsToBounds = true 236 | placeholderLabel.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: placeholderLabelHeight) 237 | self.addSubview(self.placeholderLabel) 238 | UIView.animate(withDuration: 0.5) { 239 | self.placeholderLabel.bottomAnchor.constraint(equalTo: self.topAnchor, constant: -10).isActive = true // Place our label 10pts above the text field 240 | } 241 | } else { 242 | self.placeholderLabel.removeFromSuperview() 243 | } 244 | self.setNeedsDisplay() 245 | } 246 | 247 | /// Add error if not already added 248 | func addError() { 249 | if (self.subviews.contains(errorLabel)) { 250 | return 251 | } 252 | errorLabel.font = UIFont.systemFont(ofSize: 15.0) 253 | errorLabel.numberOfLines = 0 254 | errorLabel.layer.backgroundColor = UIColor.white.cgColor 255 | errorLabel.translatesAutoresizingMaskIntoConstraints = false 256 | errorLabel.clipsToBounds = true 257 | errorLabel.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: placeholderLabelHeight) 258 | self.addSubview(self.errorLabel) 259 | UIView.animate(withDuration: 0.5) { 260 | self.errorLabel.topAnchor.constraint(equalTo: self.bottomAnchor, constant: 10).isActive = true // Place our label 10pts below the text field 261 | self.errorLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0).isActive = true 262 | self.errorLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0).isActive = true 263 | } 264 | setNeedsDisplay() 265 | } 266 | 267 | /// remove error 268 | func remmoveError() { 269 | if text != "" { 270 | self.errorLabel.removeFromSuperview() 271 | } 272 | setNeedsDisplay() 273 | } 274 | 275 | /// Check if current text field is valid or not 276 | /// - Parameter validationType: Validation typr if used predefine 277 | /// - Returns: return is textfield is valid or not 278 | open func isValid() -> Bool { 279 | guard let validation = type else { 280 | return !(text?.isEmpty ?? false) 281 | } 282 | if customValidationRegex != nil { 283 | return text?.isValidRegex(regex: customValidationRegex) ?? false 284 | } else { 285 | switch (validation) { 286 | case .email: 287 | return text?.isValidRegex(regex: Constants.emailRegex) ?? false 288 | case .password(let rule): 289 | switch rule { 290 | case .weak: 291 | return text?.isValidRegex(regex: Constants.weakPasswordRegex) ?? false 292 | case .medium: 293 | return text?.isValidRegex(regex: Constants.mediumPasswordRegex) ?? false 294 | case .strong: 295 | return text?.isValidRegex(regex: Constants.strongPasswordRegex) ?? false 296 | } 297 | case .phoneNumber(let mask): 298 | return text?.count == (mask?.count ?? Constants.phoneNumberMask.count) 299 | } 300 | } 301 | } 302 | 303 | } 304 | -------------------------------------------------------------------------------- /SSFloatingLabelTextField/Classes/StringExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Extension.swift 3 | // SSFloatingLabelTextField 4 | // 5 | // Created by Mohammed Hanif on 22/06/21. 6 | // 7 | 8 | import Foundation 9 | 10 | extension String { 11 | 12 | func isValidRegex(regex: String?) -> Bool { 13 | guard let regex = regex else { 14 | return !self.isEmpty 15 | } 16 | let passwordPred = NSPredicate(format: "SELF MATCHES %@", regex) 17 | return passwordPred.evaluate(with: self) 18 | } 19 | 20 | /// Phone Number Format 21 | /// - Parameters: 22 | /// - mask: Mask String 23 | /// - Returns: Formatted String 24 | func format(with mask: String) -> String { 25 | let numbers = self.replacingOccurrences(of: "[^0-9]", with: "", options: .regularExpression) 26 | var result = "" 27 | var index = numbers.startIndex 28 | for ch in mask where index < numbers.endIndex { 29 | if ch == "X" { 30 | result.append(numbers[index]) 31 | index = numbers.index(after: index) 32 | } else { 33 | result.append(ch) 34 | } 35 | } 36 | return result 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SSFloatingTextFieldDemo/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | target 'SSFloatingTextFieldDemo' do 5 | # Comment the next line if you don't want to use dynamic frameworks 6 | use_frameworks! 7 | 8 | pod 'SSFloatingLabelTextField' 9 | 10 | # Pods for SSFloatingTextFieldDemo 11 | 12 | end 13 | -------------------------------------------------------------------------------- /SSFloatingTextFieldDemo/SSFloatingTextFieldDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 51; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | AB6E00F4B3E192E39026CF21 /* Pods_SSFloatingTextFieldDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1BF543A35AC70E2F1AAB1FB2 /* Pods_SSFloatingTextFieldDemo.framework */; }; 11 | E370DC5D26958E550096A34C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E370DC5C26958E550096A34C /* AppDelegate.swift */; }; 12 | E370DC6126958E550096A34C /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E370DC6026958E550096A34C /* ViewController.swift */; }; 13 | E370DC6626958E570096A34C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E370DC6526958E570096A34C /* Assets.xcassets */; }; 14 | E3CD5D9C26AA801100AA387D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E3CD5D9B26AA801100AA387D /* LaunchScreen.storyboard */; }; 15 | E3CD5D9E26AA808900AA387D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E3CD5D9D26AA808900AA387D /* Main.storyboard */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXContainerItemProxy section */ 19 | E370DC7026958E570096A34C /* PBXContainerItemProxy */ = { 20 | isa = PBXContainerItemProxy; 21 | containerPortal = E370DC5126958E550096A34C /* Project object */; 22 | proxyType = 1; 23 | remoteGlobalIDString = E370DC5826958E550096A34C; 24 | remoteInfo = SSFloatingTextFieldDemo; 25 | }; 26 | E370DC7B26958E570096A34C /* PBXContainerItemProxy */ = { 27 | isa = PBXContainerItemProxy; 28 | containerPortal = E370DC5126958E550096A34C /* Project object */; 29 | proxyType = 1; 30 | remoteGlobalIDString = E370DC5826958E550096A34C; 31 | remoteInfo = SSFloatingTextFieldDemo; 32 | }; 33 | /* End PBXContainerItemProxy section */ 34 | 35 | /* Begin PBXFileReference section */ 36 | 1BF543A35AC70E2F1AAB1FB2 /* Pods_SSFloatingTextFieldDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SSFloatingTextFieldDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 37 | 8CBAF9393FE2B5F1C50BB5FE /* Pods-SSFloatingTextFieldDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SSFloatingTextFieldDemo.debug.xcconfig"; path = "Target Support Files/Pods-SSFloatingTextFieldDemo/Pods-SSFloatingTextFieldDemo.debug.xcconfig"; sourceTree = ""; }; 38 | E370DC5926958E550096A34C /* SSFloatingTextFieldDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SSFloatingTextFieldDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | E370DC5C26958E550096A34C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 40 | E370DC6026958E550096A34C /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 41 | E370DC6526958E570096A34C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 42 | E370DC6A26958E570096A34C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 43 | E370DC6F26958E570096A34C /* SSFloatingTextFieldDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SSFloatingTextFieldDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | E370DC7A26958E570096A34C /* SSFloatingTextFieldDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SSFloatingTextFieldDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 45 | E3CD5D9B26AA801100AA387D /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; 46 | E3CD5D9D26AA808900AA387D /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; 47 | F1B853C161B9FD0E8A891FC4 /* Pods-SSFloatingTextFieldDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SSFloatingTextFieldDemo.release.xcconfig"; path = "Target Support Files/Pods-SSFloatingTextFieldDemo/Pods-SSFloatingTextFieldDemo.release.xcconfig"; sourceTree = ""; }; 48 | /* End PBXFileReference section */ 49 | 50 | /* Begin PBXFrameworksBuildPhase section */ 51 | E370DC5626958E550096A34C /* Frameworks */ = { 52 | isa = PBXFrameworksBuildPhase; 53 | buildActionMask = 2147483647; 54 | files = ( 55 | AB6E00F4B3E192E39026CF21 /* Pods_SSFloatingTextFieldDemo.framework in Frameworks */, 56 | ); 57 | runOnlyForDeploymentPostprocessing = 0; 58 | }; 59 | E370DC6C26958E570096A34C /* Frameworks */ = { 60 | isa = PBXFrameworksBuildPhase; 61 | buildActionMask = 2147483647; 62 | files = ( 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | E370DC7726958E570096A34C /* Frameworks */ = { 67 | isa = PBXFrameworksBuildPhase; 68 | buildActionMask = 2147483647; 69 | files = ( 70 | ); 71 | runOnlyForDeploymentPostprocessing = 0; 72 | }; 73 | /* End PBXFrameworksBuildPhase section */ 74 | 75 | /* Begin PBXGroup section */ 76 | D033A6C076F3158F3840AAA7 /* Frameworks */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 1BF543A35AC70E2F1AAB1FB2 /* Pods_SSFloatingTextFieldDemo.framework */, 80 | ); 81 | name = Frameworks; 82 | sourceTree = ""; 83 | }; 84 | E370DC5026958E550096A34C = { 85 | isa = PBXGroup; 86 | children = ( 87 | E370DC5B26958E550096A34C /* SSFloatingTextFieldDemo */, 88 | E370DC5A26958E550096A34C /* Products */, 89 | FE3F0F7E902D41FE4DB75ED5 /* Pods */, 90 | D033A6C076F3158F3840AAA7 /* Frameworks */, 91 | ); 92 | sourceTree = ""; 93 | }; 94 | E370DC5A26958E550096A34C /* Products */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | E370DC5926958E550096A34C /* SSFloatingTextFieldDemo.app */, 98 | E370DC6F26958E570096A34C /* SSFloatingTextFieldDemoTests.xctest */, 99 | E370DC7A26958E570096A34C /* SSFloatingTextFieldDemoUITests.xctest */, 100 | ); 101 | name = Products; 102 | sourceTree = ""; 103 | }; 104 | E370DC5B26958E550096A34C /* SSFloatingTextFieldDemo */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | E370DC5C26958E550096A34C /* AppDelegate.swift */, 108 | E370DC6026958E550096A34C /* ViewController.swift */, 109 | E3CD5D9D26AA808900AA387D /* Main.storyboard */, 110 | E370DC6526958E570096A34C /* Assets.xcassets */, 111 | E370DC6A26958E570096A34C /* Info.plist */, 112 | E3CD5D9B26AA801100AA387D /* LaunchScreen.storyboard */, 113 | ); 114 | path = SSFloatingTextFieldDemo; 115 | sourceTree = ""; 116 | }; 117 | FE3F0F7E902D41FE4DB75ED5 /* Pods */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 8CBAF9393FE2B5F1C50BB5FE /* Pods-SSFloatingTextFieldDemo.debug.xcconfig */, 121 | F1B853C161B9FD0E8A891FC4 /* Pods-SSFloatingTextFieldDemo.release.xcconfig */, 122 | ); 123 | path = Pods; 124 | sourceTree = ""; 125 | }; 126 | /* End PBXGroup section */ 127 | 128 | /* Begin PBXNativeTarget section */ 129 | E370DC5826958E550096A34C /* SSFloatingTextFieldDemo */ = { 130 | isa = PBXNativeTarget; 131 | buildConfigurationList = E370DC8326958E570096A34C /* Build configuration list for PBXNativeTarget "SSFloatingTextFieldDemo" */; 132 | buildPhases = ( 133 | 96724D939463248AC96BA2DD /* [CP] Check Pods Manifest.lock */, 134 | E370DC5526958E550096A34C /* Sources */, 135 | E370DC5626958E550096A34C /* Frameworks */, 136 | E370DC5726958E550096A34C /* Resources */, 137 | 95493138E6514B71565C88E4 /* [CP] Embed Pods Frameworks */, 138 | ); 139 | buildRules = ( 140 | ); 141 | dependencies = ( 142 | ); 143 | name = SSFloatingTextFieldDemo; 144 | productName = SSFloatingTextFieldDemo; 145 | productReference = E370DC5926958E550096A34C /* SSFloatingTextFieldDemo.app */; 146 | productType = "com.apple.product-type.application"; 147 | }; 148 | E370DC6E26958E570096A34C /* SSFloatingTextFieldDemoTests */ = { 149 | isa = PBXNativeTarget; 150 | buildConfigurationList = E370DC8626958E570096A34C /* Build configuration list for PBXNativeTarget "SSFloatingTextFieldDemoTests" */; 151 | buildPhases = ( 152 | E370DC6B26958E570096A34C /* Sources */, 153 | E370DC6C26958E570096A34C /* Frameworks */, 154 | E370DC6D26958E570096A34C /* Resources */, 155 | ); 156 | buildRules = ( 157 | ); 158 | dependencies = ( 159 | E370DC7126958E570096A34C /* PBXTargetDependency */, 160 | ); 161 | name = SSFloatingTextFieldDemoTests; 162 | productName = SSFloatingTextFieldDemoTests; 163 | productReference = E370DC6F26958E570096A34C /* SSFloatingTextFieldDemoTests.xctest */; 164 | productType = "com.apple.product-type.bundle.unit-test"; 165 | }; 166 | E370DC7926958E570096A34C /* SSFloatingTextFieldDemoUITests */ = { 167 | isa = PBXNativeTarget; 168 | buildConfigurationList = E370DC8926958E570096A34C /* Build configuration list for PBXNativeTarget "SSFloatingTextFieldDemoUITests" */; 169 | buildPhases = ( 170 | E370DC7626958E570096A34C /* Sources */, 171 | E370DC7726958E570096A34C /* Frameworks */, 172 | E370DC7826958E570096A34C /* Resources */, 173 | ); 174 | buildRules = ( 175 | ); 176 | dependencies = ( 177 | E370DC7C26958E570096A34C /* PBXTargetDependency */, 178 | ); 179 | name = SSFloatingTextFieldDemoUITests; 180 | productName = SSFloatingTextFieldDemoUITests; 181 | productReference = E370DC7A26958E570096A34C /* SSFloatingTextFieldDemoUITests.xctest */; 182 | productType = "com.apple.product-type.bundle.ui-testing"; 183 | }; 184 | /* End PBXNativeTarget section */ 185 | 186 | /* Begin PBXProject section */ 187 | E370DC5126958E550096A34C /* Project object */ = { 188 | isa = PBXProject; 189 | attributes = { 190 | LastSwiftUpdateCheck = 1200; 191 | LastUpgradeCheck = 1200; 192 | TargetAttributes = { 193 | E370DC5826958E550096A34C = { 194 | CreatedOnToolsVersion = 12.0.1; 195 | }; 196 | E370DC6E26958E570096A34C = { 197 | CreatedOnToolsVersion = 12.0.1; 198 | TestTargetID = E370DC5826958E550096A34C; 199 | }; 200 | E370DC7926958E570096A34C = { 201 | CreatedOnToolsVersion = 12.0.1; 202 | TestTargetID = E370DC5826958E550096A34C; 203 | }; 204 | }; 205 | }; 206 | buildConfigurationList = E370DC5426958E550096A34C /* Build configuration list for PBXProject "SSFloatingTextFieldDemo" */; 207 | compatibilityVersion = "Xcode 9.3"; 208 | developmentRegion = en; 209 | hasScannedForEncodings = 0; 210 | knownRegions = ( 211 | en, 212 | Base, 213 | ); 214 | mainGroup = E370DC5026958E550096A34C; 215 | productRefGroup = E370DC5A26958E550096A34C /* Products */; 216 | projectDirPath = ""; 217 | projectRoot = ""; 218 | targets = ( 219 | E370DC5826958E550096A34C /* SSFloatingTextFieldDemo */, 220 | E370DC6E26958E570096A34C /* SSFloatingTextFieldDemoTests */, 221 | E370DC7926958E570096A34C /* SSFloatingTextFieldDemoUITests */, 222 | ); 223 | }; 224 | /* End PBXProject section */ 225 | 226 | /* Begin PBXResourcesBuildPhase section */ 227 | E370DC5726958E550096A34C /* Resources */ = { 228 | isa = PBXResourcesBuildPhase; 229 | buildActionMask = 2147483647; 230 | files = ( 231 | E3CD5D9C26AA801100AA387D /* LaunchScreen.storyboard in Resources */, 232 | E370DC6626958E570096A34C /* Assets.xcassets in Resources */, 233 | E3CD5D9E26AA808900AA387D /* Main.storyboard in Resources */, 234 | ); 235 | runOnlyForDeploymentPostprocessing = 0; 236 | }; 237 | E370DC6D26958E570096A34C /* Resources */ = { 238 | isa = PBXResourcesBuildPhase; 239 | buildActionMask = 2147483647; 240 | files = ( 241 | ); 242 | runOnlyForDeploymentPostprocessing = 0; 243 | }; 244 | E370DC7826958E570096A34C /* Resources */ = { 245 | isa = PBXResourcesBuildPhase; 246 | buildActionMask = 2147483647; 247 | files = ( 248 | ); 249 | runOnlyForDeploymentPostprocessing = 0; 250 | }; 251 | /* End PBXResourcesBuildPhase section */ 252 | 253 | /* Begin PBXShellScriptBuildPhase section */ 254 | 95493138E6514B71565C88E4 /* [CP] Embed Pods Frameworks */ = { 255 | isa = PBXShellScriptBuildPhase; 256 | buildActionMask = 2147483647; 257 | files = ( 258 | ); 259 | inputFileListPaths = ( 260 | "${PODS_ROOT}/Target Support Files/Pods-SSFloatingTextFieldDemo/Pods-SSFloatingTextFieldDemo-frameworks-${CONFIGURATION}-input-files.xcfilelist", 261 | ); 262 | name = "[CP] Embed Pods Frameworks"; 263 | outputFileListPaths = ( 264 | "${PODS_ROOT}/Target Support Files/Pods-SSFloatingTextFieldDemo/Pods-SSFloatingTextFieldDemo-frameworks-${CONFIGURATION}-output-files.xcfilelist", 265 | ); 266 | runOnlyForDeploymentPostprocessing = 0; 267 | shellPath = /bin/sh; 268 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SSFloatingTextFieldDemo/Pods-SSFloatingTextFieldDemo-frameworks.sh\"\n"; 269 | showEnvVarsInLog = 0; 270 | }; 271 | 96724D939463248AC96BA2DD /* [CP] Check Pods Manifest.lock */ = { 272 | isa = PBXShellScriptBuildPhase; 273 | buildActionMask = 2147483647; 274 | files = ( 275 | ); 276 | inputFileListPaths = ( 277 | ); 278 | inputPaths = ( 279 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 280 | "${PODS_ROOT}/Manifest.lock", 281 | ); 282 | name = "[CP] Check Pods Manifest.lock"; 283 | outputFileListPaths = ( 284 | ); 285 | outputPaths = ( 286 | "$(DERIVED_FILE_DIR)/Pods-SSFloatingTextFieldDemo-checkManifestLockResult.txt", 287 | ); 288 | runOnlyForDeploymentPostprocessing = 0; 289 | shellPath = /bin/sh; 290 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 291 | showEnvVarsInLog = 0; 292 | }; 293 | /* End PBXShellScriptBuildPhase section */ 294 | 295 | /* Begin PBXSourcesBuildPhase section */ 296 | E370DC5526958E550096A34C /* Sources */ = { 297 | isa = PBXSourcesBuildPhase; 298 | buildActionMask = 2147483647; 299 | files = ( 300 | E370DC6126958E550096A34C /* ViewController.swift in Sources */, 301 | E370DC5D26958E550096A34C /* AppDelegate.swift in Sources */, 302 | ); 303 | runOnlyForDeploymentPostprocessing = 0; 304 | }; 305 | E370DC6B26958E570096A34C /* Sources */ = { 306 | isa = PBXSourcesBuildPhase; 307 | buildActionMask = 2147483647; 308 | files = ( 309 | ); 310 | runOnlyForDeploymentPostprocessing = 0; 311 | }; 312 | E370DC7626958E570096A34C /* Sources */ = { 313 | isa = PBXSourcesBuildPhase; 314 | buildActionMask = 2147483647; 315 | files = ( 316 | ); 317 | runOnlyForDeploymentPostprocessing = 0; 318 | }; 319 | /* End PBXSourcesBuildPhase section */ 320 | 321 | /* Begin PBXTargetDependency section */ 322 | E370DC7126958E570096A34C /* PBXTargetDependency */ = { 323 | isa = PBXTargetDependency; 324 | target = E370DC5826958E550096A34C /* SSFloatingTextFieldDemo */; 325 | targetProxy = E370DC7026958E570096A34C /* PBXContainerItemProxy */; 326 | }; 327 | E370DC7C26958E570096A34C /* PBXTargetDependency */ = { 328 | isa = PBXTargetDependency; 329 | target = E370DC5826958E550096A34C /* SSFloatingTextFieldDemo */; 330 | targetProxy = E370DC7B26958E570096A34C /* PBXContainerItemProxy */; 331 | }; 332 | /* End PBXTargetDependency section */ 333 | 334 | /* Begin XCBuildConfiguration section */ 335 | E370DC8126958E570096A34C /* Debug */ = { 336 | isa = XCBuildConfiguration; 337 | buildSettings = { 338 | ALWAYS_SEARCH_USER_PATHS = NO; 339 | CLANG_ANALYZER_NONNULL = YES; 340 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 341 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 342 | CLANG_CXX_LIBRARY = "libc++"; 343 | CLANG_ENABLE_MODULES = YES; 344 | CLANG_ENABLE_OBJC_ARC = YES; 345 | CLANG_ENABLE_OBJC_WEAK = YES; 346 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 347 | CLANG_WARN_BOOL_CONVERSION = YES; 348 | CLANG_WARN_COMMA = YES; 349 | CLANG_WARN_CONSTANT_CONVERSION = YES; 350 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 351 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 352 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 353 | CLANG_WARN_EMPTY_BODY = YES; 354 | CLANG_WARN_ENUM_CONVERSION = YES; 355 | CLANG_WARN_INFINITE_RECURSION = YES; 356 | CLANG_WARN_INT_CONVERSION = YES; 357 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 358 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 359 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 360 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 361 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 362 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 363 | CLANG_WARN_STRICT_PROTOTYPES = YES; 364 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 365 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 366 | CLANG_WARN_UNREACHABLE_CODE = YES; 367 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 368 | COPY_PHASE_STRIP = NO; 369 | DEBUG_INFORMATION_FORMAT = dwarf; 370 | ENABLE_STRICT_OBJC_MSGSEND = YES; 371 | ENABLE_TESTABILITY = YES; 372 | GCC_C_LANGUAGE_STANDARD = gnu11; 373 | GCC_DYNAMIC_NO_PIC = NO; 374 | GCC_NO_COMMON_BLOCKS = YES; 375 | GCC_OPTIMIZATION_LEVEL = 0; 376 | GCC_PREPROCESSOR_DEFINITIONS = ( 377 | "DEBUG=1", 378 | "$(inherited)", 379 | ); 380 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 381 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 382 | GCC_WARN_UNDECLARED_SELECTOR = YES; 383 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 384 | GCC_WARN_UNUSED_FUNCTION = YES; 385 | GCC_WARN_UNUSED_VARIABLE = YES; 386 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 387 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 388 | MTL_FAST_MATH = YES; 389 | ONLY_ACTIVE_ARCH = YES; 390 | SDKROOT = iphoneos; 391 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 392 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 393 | }; 394 | name = Debug; 395 | }; 396 | E370DC8226958E570096A34C /* Release */ = { 397 | isa = XCBuildConfiguration; 398 | buildSettings = { 399 | ALWAYS_SEARCH_USER_PATHS = NO; 400 | CLANG_ANALYZER_NONNULL = YES; 401 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 402 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 403 | CLANG_CXX_LIBRARY = "libc++"; 404 | CLANG_ENABLE_MODULES = YES; 405 | CLANG_ENABLE_OBJC_ARC = YES; 406 | CLANG_ENABLE_OBJC_WEAK = YES; 407 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 408 | CLANG_WARN_BOOL_CONVERSION = YES; 409 | CLANG_WARN_COMMA = YES; 410 | CLANG_WARN_CONSTANT_CONVERSION = YES; 411 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 412 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 413 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 414 | CLANG_WARN_EMPTY_BODY = YES; 415 | CLANG_WARN_ENUM_CONVERSION = YES; 416 | CLANG_WARN_INFINITE_RECURSION = YES; 417 | CLANG_WARN_INT_CONVERSION = YES; 418 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 419 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 420 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 421 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 422 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 423 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 424 | CLANG_WARN_STRICT_PROTOTYPES = YES; 425 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 426 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 427 | CLANG_WARN_UNREACHABLE_CODE = YES; 428 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 429 | COPY_PHASE_STRIP = NO; 430 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 431 | ENABLE_NS_ASSERTIONS = NO; 432 | ENABLE_STRICT_OBJC_MSGSEND = YES; 433 | GCC_C_LANGUAGE_STANDARD = gnu11; 434 | GCC_NO_COMMON_BLOCKS = YES; 435 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 436 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 437 | GCC_WARN_UNDECLARED_SELECTOR = YES; 438 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 439 | GCC_WARN_UNUSED_FUNCTION = YES; 440 | GCC_WARN_UNUSED_VARIABLE = YES; 441 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 442 | MTL_ENABLE_DEBUG_INFO = NO; 443 | MTL_FAST_MATH = YES; 444 | SDKROOT = iphoneos; 445 | SWIFT_COMPILATION_MODE = wholemodule; 446 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 447 | VALIDATE_PRODUCT = YES; 448 | }; 449 | name = Release; 450 | }; 451 | E370DC8426958E570096A34C /* Debug */ = { 452 | isa = XCBuildConfiguration; 453 | baseConfigurationReference = 8CBAF9393FE2B5F1C50BB5FE /* Pods-SSFloatingTextFieldDemo.debug.xcconfig */; 454 | buildSettings = { 455 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 456 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 457 | CODE_SIGN_STYLE = Automatic; 458 | INFOPLIST_FILE = SSFloatingTextFieldDemo/Info.plist; 459 | LD_RUNPATH_SEARCH_PATHS = ( 460 | "$(inherited)", 461 | "@executable_path/Frameworks", 462 | ); 463 | PRODUCT_BUNDLE_IDENTIFIER = com.simform.SSFloatingTextFieldDemo; 464 | PRODUCT_NAME = "$(TARGET_NAME)"; 465 | SWIFT_VERSION = 5.0; 466 | TARGETED_DEVICE_FAMILY = "1,2"; 467 | }; 468 | name = Debug; 469 | }; 470 | E370DC8526958E570096A34C /* Release */ = { 471 | isa = XCBuildConfiguration; 472 | baseConfigurationReference = F1B853C161B9FD0E8A891FC4 /* Pods-SSFloatingTextFieldDemo.release.xcconfig */; 473 | buildSettings = { 474 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 475 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 476 | CODE_SIGN_STYLE = Automatic; 477 | INFOPLIST_FILE = SSFloatingTextFieldDemo/Info.plist; 478 | LD_RUNPATH_SEARCH_PATHS = ( 479 | "$(inherited)", 480 | "@executable_path/Frameworks", 481 | ); 482 | PRODUCT_BUNDLE_IDENTIFIER = com.simform.SSFloatingTextFieldDemo; 483 | PRODUCT_NAME = "$(TARGET_NAME)"; 484 | SWIFT_VERSION = 5.0; 485 | TARGETED_DEVICE_FAMILY = "1,2"; 486 | }; 487 | name = Release; 488 | }; 489 | E370DC8726958E570096A34C /* Debug */ = { 490 | isa = XCBuildConfiguration; 491 | buildSettings = { 492 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 493 | BUNDLE_LOADER = "$(TEST_HOST)"; 494 | CODE_SIGN_STYLE = Automatic; 495 | INFOPLIST_FILE = SSFloatingTextFieldDemoTests/Info.plist; 496 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 497 | LD_RUNPATH_SEARCH_PATHS = ( 498 | "$(inherited)", 499 | "@executable_path/Frameworks", 500 | "@loader_path/Frameworks", 501 | ); 502 | PRODUCT_BUNDLE_IDENTIFIER = com.simform.SSFloatingTextFieldDemoTests; 503 | PRODUCT_NAME = "$(TARGET_NAME)"; 504 | SWIFT_VERSION = 5.0; 505 | TARGETED_DEVICE_FAMILY = "1,2"; 506 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SSFloatingTextFieldDemo.app/SSFloatingTextFieldDemo"; 507 | }; 508 | name = Debug; 509 | }; 510 | E370DC8826958E570096A34C /* Release */ = { 511 | isa = XCBuildConfiguration; 512 | buildSettings = { 513 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 514 | BUNDLE_LOADER = "$(TEST_HOST)"; 515 | CODE_SIGN_STYLE = Automatic; 516 | INFOPLIST_FILE = SSFloatingTextFieldDemoTests/Info.plist; 517 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 518 | LD_RUNPATH_SEARCH_PATHS = ( 519 | "$(inherited)", 520 | "@executable_path/Frameworks", 521 | "@loader_path/Frameworks", 522 | ); 523 | PRODUCT_BUNDLE_IDENTIFIER = com.simform.SSFloatingTextFieldDemoTests; 524 | PRODUCT_NAME = "$(TARGET_NAME)"; 525 | SWIFT_VERSION = 5.0; 526 | TARGETED_DEVICE_FAMILY = "1,2"; 527 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SSFloatingTextFieldDemo.app/SSFloatingTextFieldDemo"; 528 | }; 529 | name = Release; 530 | }; 531 | E370DC8A26958E570096A34C /* Debug */ = { 532 | isa = XCBuildConfiguration; 533 | buildSettings = { 534 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 535 | CODE_SIGN_STYLE = Automatic; 536 | INFOPLIST_FILE = SSFloatingTextFieldDemoUITests/Info.plist; 537 | LD_RUNPATH_SEARCH_PATHS = ( 538 | "$(inherited)", 539 | "@executable_path/Frameworks", 540 | "@loader_path/Frameworks", 541 | ); 542 | PRODUCT_BUNDLE_IDENTIFIER = com.simform.SSFloatingTextFieldDemoUITests; 543 | PRODUCT_NAME = "$(TARGET_NAME)"; 544 | SWIFT_VERSION = 5.0; 545 | TARGETED_DEVICE_FAMILY = "1,2"; 546 | TEST_TARGET_NAME = SSFloatingTextFieldDemo; 547 | }; 548 | name = Debug; 549 | }; 550 | E370DC8B26958E570096A34C /* Release */ = { 551 | isa = XCBuildConfiguration; 552 | buildSettings = { 553 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 554 | CODE_SIGN_STYLE = Automatic; 555 | INFOPLIST_FILE = SSFloatingTextFieldDemoUITests/Info.plist; 556 | LD_RUNPATH_SEARCH_PATHS = ( 557 | "$(inherited)", 558 | "@executable_path/Frameworks", 559 | "@loader_path/Frameworks", 560 | ); 561 | PRODUCT_BUNDLE_IDENTIFIER = com.simform.SSFloatingTextFieldDemoUITests; 562 | PRODUCT_NAME = "$(TARGET_NAME)"; 563 | SWIFT_VERSION = 5.0; 564 | TARGETED_DEVICE_FAMILY = "1,2"; 565 | TEST_TARGET_NAME = SSFloatingTextFieldDemo; 566 | }; 567 | name = Release; 568 | }; 569 | /* End XCBuildConfiguration section */ 570 | 571 | /* Begin XCConfigurationList section */ 572 | E370DC5426958E550096A34C /* Build configuration list for PBXProject "SSFloatingTextFieldDemo" */ = { 573 | isa = XCConfigurationList; 574 | buildConfigurations = ( 575 | E370DC8126958E570096A34C /* Debug */, 576 | E370DC8226958E570096A34C /* Release */, 577 | ); 578 | defaultConfigurationIsVisible = 0; 579 | defaultConfigurationName = Release; 580 | }; 581 | E370DC8326958E570096A34C /* Build configuration list for PBXNativeTarget "SSFloatingTextFieldDemo" */ = { 582 | isa = XCConfigurationList; 583 | buildConfigurations = ( 584 | E370DC8426958E570096A34C /* Debug */, 585 | E370DC8526958E570096A34C /* Release */, 586 | ); 587 | defaultConfigurationIsVisible = 0; 588 | defaultConfigurationName = Release; 589 | }; 590 | E370DC8626958E570096A34C /* Build configuration list for PBXNativeTarget "SSFloatingTextFieldDemoTests" */ = { 591 | isa = XCConfigurationList; 592 | buildConfigurations = ( 593 | E370DC8726958E570096A34C /* Debug */, 594 | E370DC8826958E570096A34C /* Release */, 595 | ); 596 | defaultConfigurationIsVisible = 0; 597 | defaultConfigurationName = Release; 598 | }; 599 | E370DC8926958E570096A34C /* Build configuration list for PBXNativeTarget "SSFloatingTextFieldDemoUITests" */ = { 600 | isa = XCConfigurationList; 601 | buildConfigurations = ( 602 | E370DC8A26958E570096A34C /* Debug */, 603 | E370DC8B26958E570096A34C /* Release */, 604 | ); 605 | defaultConfigurationIsVisible = 0; 606 | defaultConfigurationName = Release; 607 | }; 608 | /* End XCConfigurationList section */ 609 | }; 610 | rootObject = E370DC5126958E550096A34C /* Project object */; 611 | } 612 | -------------------------------------------------------------------------------- /SSFloatingTextFieldDemo/SSFloatingTextFieldDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SSFloatingTextFieldDemo/SSFloatingTextFieldDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SSFloatingTextFieldDemo/SSFloatingTextFieldDemo.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SSFloatingTextFieldDemo/SSFloatingTextFieldDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SSFloatingTextFieldDemo/SSFloatingTextFieldDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SSFloatingTextFieldDemo 4 | // 5 | // Created by Mohammed Hanif on 07/07/21. 6 | // 7 | 8 | import UIKit 9 | 10 | @main 11 | class AppDelegate: UIResponder, UIApplicationDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 16 | // Override point for customization after application launch. 17 | return true 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /SSFloatingTextFieldDemo/SSFloatingTextFieldDemo/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SSFloatingTextFieldDemo/SSFloatingTextFieldDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /SSFloatingTextFieldDemo/SSFloatingTextFieldDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SSFloatingTextFieldDemo/SSFloatingTextFieldDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | UILaunchStoryboardName 22 | LaunchScreen 23 | UIMainStoryboardFile 24 | Main 25 | 26 | 27 | -------------------------------------------------------------------------------- /SSFloatingTextFieldDemo/SSFloatingTextFieldDemo/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /SSFloatingTextFieldDemo/SSFloatingTextFieldDemo/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | Password must be 8 characters long and contain atleast 1 lowercase character 1 uppercase character 1 dight and 1 special character 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /SSFloatingTextFieldDemo/SSFloatingTextFieldDemo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SSFloatingTextFieldDemo 4 | // 5 | // Created by Mohammed Hanif on 07/07/21. 6 | // 7 | 8 | import UIKit 9 | import SSFloatingLabelTextField 10 | 11 | class ViewController: UIViewController { 12 | 13 | @IBOutlet weak var txtUsername: SSFloatingLabelTextField! 14 | @IBOutlet weak var txtEmail: SSFloatingLabelTextField! 15 | @IBOutlet weak var txtPassword: SSFloatingLabelTextField! 16 | @IBOutlet weak var txtPhoneNumber: SSFloatingLabelTextField! 17 | 18 | override func viewDidLoad() { 19 | super.viewDidLoad() 20 | txtEmail.type = .email 21 | txtPassword.type = .password(passwordRule: .medium) 22 | txtPhoneNumber.type = .phoneNumber(formatterString: nil) 23 | hideKeyboardWhenTappedAround() 24 | } 25 | 26 | func hideKeyboardWhenTappedAround() { 27 | let tap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)) 28 | tap.cancelsTouchesInView = false 29 | view.addGestureRecognizer(tap) 30 | } 31 | 32 | @objc func dismissKeyboard() { 33 | view.endEditing(true) 34 | } 35 | 36 | @IBAction func btnValidate(_ sender: UIButton) { 37 | print(txtUsername.isValid()) 38 | print(txtEmail.isValid()) 39 | print(txtPassword.isValid()) 40 | print(txtPhoneNumber.isValid()) 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /screenshots/Installation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/SSFloatingLabelTextField/3b425b141df546d19bf726525e10caa04c699172/screenshots/Installation.png -------------------------------------------------------------------------------- /screenshots/SSFloatingTextField.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/SSFloatingLabelTextField/3b425b141df546d19bf726525e10caa04c699172/screenshots/SSFloatingTextField.gif -------------------------------------------------------------------------------- /screenshots/simformBanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/SSFloatingLabelTextField/3b425b141df546d19bf726525e10caa04c699172/screenshots/simformBanner.png --------------------------------------------------------------------------------