├── .gitignore
├── Custom.png
├── LICENSE
├── README.md
├── Source
└── SPTextField.swift
├── _config.yml
├── ezgif-4-67db7adf45.gif
└── file.png
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xccheckout
23 | *.xcscmblueprint
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 | *.ipa
28 | *.dSYM.zip
29 | *.dSYM
30 |
31 | ## Playgrounds
32 | timeline.xctimeline
33 | playground.xcworkspace
34 |
35 | # Swift Package Manager
36 | #
37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
38 | # Packages/
39 | # Package.pins
40 | .build/
41 |
42 | # CocoaPods
43 | #
44 | # We recommend against adding the Pods directory to your .gitignore. However
45 | # you should judge for yourself, the pros and cons are mentioned at:
46 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
47 | #
48 | # Pods/
49 |
50 | # Carthage
51 | #
52 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
53 | # Carthage/Checkouts
54 |
55 | Carthage/Build
56 |
57 | # fastlane
58 | #
59 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
60 | # screenshots whenever they are needed.
61 | # For more information about the recommended setup visit:
62 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
63 |
64 | fastlane/report.xml
65 | fastlane/Preview.html
66 | fastlane/screenshots
67 | fastlane/test_output
68 |
--------------------------------------------------------------------------------
/Custom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pranavansp/SPTextField/268ebd858f7d98ee52f6d590a28afcc01afcb8c4/Custom.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Pranavan
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 | # SPTextField
2 | A beautiful and animating text field. Written in Swift. Underlined UITextField. This project is maintained by [Pranavan](https://twitter.com/ImPrana).
3 |
4 |
5 |
6 | # SPTextField on Simulator
7 |
8 |
9 | # Usage
10 | 1. Create `UITextField` in your storyboard or programatically.
11 | 2. Set `SPTextField` as `UITextField` class.
12 | 3. Customization
13 | Customization for SPTextField:
14 | - Left Image : Text Field main Icon/Image (Set as template on Assets)
15 | - Right Padding : Spacing between text and icon
16 | - Border Inactive : Text field inactiive underline color
17 | - Border Active : Text field Active underline color
18 | - Alert Image : Right Side Alert Image Icon
19 | - Image Size : Both main and alert image icon sizes
20 |
21 |
22 |
23 | 4. Useful methods for Calling Alert Animation
24 | - Create Outlet
25 | ```swift
26 | @IBOutlet var newText: SPLoginTextField!
27 | ```
28 | - Call method for animation
29 | ```swift
30 | newText.invalidFieldAlert()!
31 | ```
32 |
33 | # Installation
34 | *Manually*
35 |
36 | Drop [SPTextField.swift](https://github.com/pranavansp/SPTextField/blob/master/Source/SPTextField.swift) in your project.
37 |
38 | *Pods is coming.
39 |
40 | ## Requirements
41 |
42 | * iOS 9.0+
43 | * Xcode 8.0+
44 |
45 | ## Author
46 |
47 | This project is maintained by [Pranavan](https://twitter.com/ImPrana). I design and build Web and iOS/Android applications.
48 |
--------------------------------------------------------------------------------
/Source/SPTextField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SPTextField.swift
3 | // SPTextField
4 | //
5 | // Created by Sivarajah Pranavan on 8/15/17.
6 | // Copyright © 2017 Pranavan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @IBDesignable
12 | open class SPTextField: UITextField {
13 |
14 | private let borderThickness: (active: CGFloat, inactive: CGFloat) = (active: 3, inactive: 1)
15 | private let inactiveBorderLayer = CALayer()
16 | private let activeBorderLayer = CALayer()
17 |
18 | @IBInspectable
19 | var leftImage : UIImage? {
20 | didSet {
21 | updateView()
22 | }
23 | }
24 | @IBInspectable
25 | var rigthPadding : CGFloat = 0 {
26 | didSet{
27 | updateView()
28 | }
29 | }
30 |
31 | @IBInspectable
32 | var borderInactiveColor : UIColor = .clear{
33 | didSet{
34 | updateBorder()
35 | }
36 | }
37 | @IBInspectable
38 | var borderActiveColor : UIColor = .clear{
39 | didSet{
40 | updateBorder()
41 | }
42 | }
43 |
44 | @IBInspectable
45 | var alertImage : UIImage? {
46 | didSet {
47 | updateView()
48 | }
49 | }
50 |
51 | @IBInspectable
52 | var ImageSize : CGFloat = 30 {
53 | didSet{
54 | updateView()
55 | }
56 | }
57 | override open func willMove(toSuperview newSuperview: UIView!) {
58 | if newSuperview != nil {
59 | NotificationCenter.default.addObserver(self, selector: #selector(textFieldDidBeginEditing), name: NSNotification.Name.UITextFieldTextDidBeginEditing, object: self)
60 |
61 | NotificationCenter.default.addObserver(self, selector: #selector(textFieldDidEndEditing), name: NSNotification.Name.UITextFieldTextDidEndEditing, object: self)
62 | } else {
63 | NotificationCenter.default.removeObserver(self)
64 | }
65 | }
66 |
67 |
68 | open func textFieldDidBeginEditing() {
69 | activeBorderLayer.frame = actionForBorder(borderThickness.active, isFilled: true)
70 | rightViewMode = .never
71 | }
72 | open func textFieldDidEndEditing() {
73 | activeBorderLayer.frame = actionForBorder(borderThickness.active, isFilled: false)
74 | rightViewMode = .never
75 | }
76 |
77 | private func actionForBorder(_ thickness: CGFloat, isFilled: Bool) -> CGRect {
78 | if isFilled {
79 | return CGRect(origin: CGPoint(x: ImageSize, y: frame.height-thickness), size: CGSize(width: frame.width, height: thickness))
80 | } else {
81 | return CGRect(origin: CGPoint(x: ImageSize, y: frame.height-thickness), size: CGSize(width: 0, height: thickness))
82 | }
83 | }
84 |
85 | private func updateBorder() {
86 | inactiveBorderLayer.frame = actionForBorder(borderThickness.inactive, isFilled: true)
87 | inactiveBorderLayer.backgroundColor = borderInactiveColor.cgColor
88 |
89 | activeBorderLayer.frame = actionForBorder(borderThickness.active, isFilled: false)
90 | activeBorderLayer.backgroundColor = borderActiveColor.cgColor
91 |
92 | layer.addSublayer(inactiveBorderLayer)
93 | layer.addSublayer(activeBorderLayer)
94 | }
95 |
96 | private func updateView() {
97 | if let icon = leftImage{
98 | leftViewMode = .always
99 | let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: ImageSize, height: ImageSize))
100 |
101 | var width = ImageSize + rigthPadding
102 |
103 | if borderStyle == UITextBorderStyle.none || borderStyle == UITextBorderStyle.line {
104 | width = width + 5
105 | }
106 | imageView.image = icon
107 | imageView.tintColor = tintColor
108 | let view = UIView(frame: CGRect(x: 0, y: 0, width: width, height: width))
109 | view.addSubview(imageView)
110 | leftView = view
111 | }else{
112 |
113 | leftViewMode = .never
114 | }
115 |
116 | if let alertIcon = alertImage {
117 | rightViewMode = .never
118 | let alertImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: ImageSize, height: ImageSize))
119 | let alertView = UIView(frame: CGRect(x: 0, y: 0, width: ImageSize+5, height: ImageSize))
120 | alertImageView.image = alertIcon
121 | alertImageView.tintColor = tintColor
122 | alertView.addSubview(alertImageView)
123 | rightView = alertView
124 | }else{
125 | rightViewMode = .never
126 | }
127 | }
128 |
129 | public func invalidFieldAlert() {
130 | rightViewMode = .unlessEditing
131 | let animation = CABasicAnimation(keyPath: "position")
132 | animation.duration = 0.05
133 | animation.repeatCount = 5
134 | animation.autoreverses = true
135 | animation.fromValue = NSValue(cgPoint : CGPoint.init(x: self.center.x - 5.0, y: self.center.y))
136 | animation.toValue = NSValue(cgPoint : CGPoint.init(x: self.center.x + 5.0, y: self.center.y))
137 | layer.add(animation, forKey: "position")
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/ezgif-4-67db7adf45.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pranavansp/SPTextField/268ebd858f7d98ee52f6d590a28afcc01afcb8c4/ezgif-4-67db7adf45.gif
--------------------------------------------------------------------------------
/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pranavansp/SPTextField/268ebd858f7d98ee52f6d590a28afcc01afcb8c4/file.png
--------------------------------------------------------------------------------