├── misc
├── preview.gif
└── IBScreenshot.png
├── ACAnimatedTextFieldDemo
├── ACAnimatedTextFieldDemo
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── locked.imageset
│ │ │ ├── key195.png
│ │ │ ├── key195@2x.png
│ │ │ ├── key195@3x.png
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── ViewController.swift
│ ├── Info.plist
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── AppDelegate.swift
│ └── ACAnimatedTextField.swift
└── ACAnimatedTextFieldDemo.xcodeproj
│ ├── project.xcworkspace
│ └── contents.xcworkspacedata
│ ├── xcshareddata
│ └── xcschemes
│ │ └── ACAnimatedTextFieldDemo.xcscheme
│ └── project.pbxproj
├── .gitignore
├── LICENSE.md
├── README.md
└── ACAnimatedTextField
└── ACAnimatedTextField.swift
/misc/preview.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlexCatch/ACAnimatedTextField/HEAD/misc/preview.gif
--------------------------------------------------------------------------------
/misc/IBScreenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlexCatch/ACAnimatedTextField/HEAD/misc/IBScreenshot.png
--------------------------------------------------------------------------------
/ACAnimatedTextFieldDemo/ACAnimatedTextFieldDemo/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/ACAnimatedTextFieldDemo/ACAnimatedTextFieldDemo/Assets.xcassets/locked.imageset/key195.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlexCatch/ACAnimatedTextField/HEAD/ACAnimatedTextFieldDemo/ACAnimatedTextFieldDemo/Assets.xcassets/locked.imageset/key195.png
--------------------------------------------------------------------------------
/ACAnimatedTextFieldDemo/ACAnimatedTextFieldDemo/Assets.xcassets/locked.imageset/key195@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlexCatch/ACAnimatedTextField/HEAD/ACAnimatedTextFieldDemo/ACAnimatedTextFieldDemo/Assets.xcassets/locked.imageset/key195@2x.png
--------------------------------------------------------------------------------
/ACAnimatedTextFieldDemo/ACAnimatedTextFieldDemo/Assets.xcassets/locked.imageset/key195@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlexCatch/ACAnimatedTextField/HEAD/ACAnimatedTextFieldDemo/ACAnimatedTextFieldDemo/Assets.xcassets/locked.imageset/key195@3x.png
--------------------------------------------------------------------------------
/ACAnimatedTextFieldDemo/ACAnimatedTextFieldDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ACAnimatedTextFieldDemo/ACAnimatedTextFieldDemo/Assets.xcassets/locked.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "key195.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "key195@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "key195@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | build/
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | xcuserdata
13 | *.xccheckout
14 | *.moved-aside
15 | DerivedData
16 | *.hmap
17 | *.ipa
18 | *.xcuserstate
19 |
20 | # CocoaPods
21 | #
22 | # We recommend against adding the Pods directory to your .gitignore. However
23 | # you should judge for yourself, the pros and cons are mentioned at:
24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
25 | #
26 | # Pods/
27 |
28 | # Carthage
29 | #
30 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
31 | # Carthage/Checkouts
32 |
33 | Carthage/Build
34 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Alex Catchpole
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 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ACAnimatedTextField
2 |
3 | ACAnimatedTextField is a subclass of UITextField which replaces a text placeholder with an image.
4 |
5 | ## Installation
6 | ACAnimatedTextField is one file, simply drag and drop `ACAnimatedTextField/ACAnimatedTextField.swift` into your project and set the class of a UITextField to ACAnimatedTextField
7 |
8 | ## Preview
9 | 
10 |
11 | ## Customization
12 | 4 things are currently able to be customized.
13 |
14 | - Image
15 | - Active colour
16 | - Inactive colour
17 | - Size of UIImageView
18 |
19 | You can either set them via code or user attributes
20 |
21 | ### Interface Builder
22 | 
23 |
24 | ### Code
25 | ```swift
26 | demoTextField.activeColour = UIColor.redColor()
27 | demoTextField.inactiveColour = UIColor.greenColor()
28 | demoTextField.textFieldImage = UIImage(named: "locked")
29 | demoTextField.imageWidth = 24
30 | demoTextField.imageHeight = 24
31 | ```
32 |
33 | ## Todo
34 |
35 | - [ ] Make textRect change based on size of UIImageView
36 |
37 | ## License
38 | ACAnimatedTextField is under the MIT license. Please check out LICENSE.md for more information
39 |
--------------------------------------------------------------------------------
/ACAnimatedTextFieldDemo/ACAnimatedTextFieldDemo/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // ACAnimatedTextFieldDemo
4 | //
5 | // Created by Alex Catchpole on 20/10/2015.
6 | // Copyright © 2015 AlexCatchpole. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ViewController: UIViewController, UITextFieldDelegate {
12 |
13 | @IBOutlet var demoTextField: ACAnimatedTextField!
14 | override func viewDidLoad() {
15 | super.viewDidLoad()
16 | // Do any additional setup after loading the view, typically from a nib.
17 |
18 | //demoTextField.textFieldImageView.image = UIImage(named: "locked")
19 | demoTextField.layer.cornerRadius = 18
20 | demoTextField.tintColor = self.view.backgroundColor
21 | demoTextField.textColor = self.view.backgroundColor
22 | demoTextField.delegate = self
23 |
24 | //demoTextField.textFieldImageViewFrame = CGRectMake(10, 10, 32, 32)
25 |
26 | }
27 |
28 | override func didReceiveMemoryWarning() {
29 | super.didReceiveMemoryWarning()
30 | // Dispose of any resources that can be recreated.
31 | }
32 |
33 | func textFieldShouldReturn(textField: UITextField) -> Bool {
34 | self.view.endEditing(true)
35 | return true
36 | }
37 |
38 |
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/ACAnimatedTextFieldDemo/ACAnimatedTextFieldDemo/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "29x29",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "29x29",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "40x40",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "40x40",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "76x76",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "76x76",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/ACAnimatedTextFieldDemo/ACAnimatedTextFieldDemo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/ACAnimatedTextFieldDemo/ACAnimatedTextFieldDemo/Base.lproj/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 |
--------------------------------------------------------------------------------
/ACAnimatedTextFieldDemo/ACAnimatedTextFieldDemo/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // ACAnimatedTextFieldDemo
4 | //
5 | // Created by Alex Catchpole on 20/10/2015.
6 | // Copyright © 2015 AlexCatchpole. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(application: UIApplication) {
33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/ACAnimatedTextFieldDemo/ACAnimatedTextFieldDemo.xcodeproj/xcshareddata/xcschemes/ACAnimatedTextFieldDemo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/ACAnimatedTextFieldDemo/ACAnimatedTextFieldDemo/Base.lproj/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 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/ACAnimatedTextField/ACAnimatedTextField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ACAnimatedTextField.swift
3 | // RA4WVPN
4 | //
5 | // Created by Alex Catchpole on 19/10/2015.
6 | // Copyright © 2015 Alex Catchpole. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ACAnimatedTextField: UITextField {
12 |
13 | //Global reference to the uiimageview
14 | //Default frame of image, can be customized
15 | private var textFieldImageView: UIImageView = UIImageView(frame: CGRectMake(0, 0, 24, 24))
16 | @IBInspectable var textFieldImage: UIImage? {
17 |
18 | didSet {
19 | textFieldImageView.image = textFieldImage!
20 | }
21 |
22 | }
23 | @IBInspectable var activeColour: UIColor?
24 | @IBInspectable var inactiveColour: UIColor?
25 |
26 | @IBInspectable var imageWidth: NSNumber? {
27 | didSet {
28 | textFieldImageView.frame.size.width = CGFloat(imageWidth!)
29 |
30 | }
31 | }
32 | @IBInspectable var imageHeight: NSNumber? {
33 | didSet {
34 | textFieldImageView.frame.size.height = CGFloat(imageHeight!)
35 |
36 | }
37 | }
38 |
39 | //called after init, when the rect of the textfield is being drawing
40 | override func drawRect(rect: CGRect) {
41 |
42 | //Default corner radius
43 | self.borderStyle = UITextBorderStyle.None
44 | self.textAlignment = NSTextAlignment.Center
45 |
46 | //add uiimageview which was initialized in init?()
47 | self.addSubview(textFieldImageView)
48 |
49 | //set image rendering mode so we can change colour of vector
50 | if textFieldImageView.image != nil {
51 | textFieldImageView.image = textFieldImageView.image!.imageWithRenderingMode(.AlwaysTemplate)
52 | }else {
53 | print("ACAnimatedTextField -- Image Not Set")
54 | }
55 |
56 | //initial colour
57 | if inactiveColour != nil {
58 | textFieldImageView.tintColor = inactiveColour
59 | }else {
60 | textFieldImageView.tintColor = UIColor(red: 205 / 255, green: 205 / 255, blue: 205 / 255, alpha: 1)
61 | }
62 |
63 | //set the center of the uiimageview to self
64 | textFieldImageView.center = CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2)
65 |
66 | //Remove placeholder text because the placeholder is an image
67 | self.placeholder = ""
68 |
69 | }
70 |
71 | override func textRectForBounds(bounds: CGRect) -> CGRect {
72 |
73 | return CGRectInset(bounds, 50, 0)
74 | }
75 |
76 | override func editingRectForBounds(bounds: CGRect) -> CGRect {
77 | return CGRectInset(bounds, 50, 0)
78 | }
79 |
80 | required init?(coder aDecoder: NSCoder) {
81 | super.init(coder: aDecoder)
82 |
83 | //I didn't want to interfere with delegates so the user can use the built in delegates so I'll use targets instead
84 | self.addTarget(self, action: "didBeginEditing", forControlEvents: UIControlEvents.EditingDidBegin)
85 | self.addTarget(self, action: "didEndEditing", forControlEvents: UIControlEvents.EditingDidEnd)
86 |
87 | }
88 |
89 | func didBeginEditing() {
90 | //on edit run animation
91 | UIView.animateWithDuration(0.4, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: { () -> Void in
92 | self.textFieldImageView.center = CGPointMake(30, self.bounds.size.height / 2)
93 | if self.activeColour != nil {
94 | //make sure active colour is set
95 | self.textFieldImageView.tintColor = self.activeColour
96 | }else {
97 | self.textFieldImageView.tintColor = UIColor(red: 50 / 255, green: 50 / 255, blue: 50 / 255, alpha: 1)
98 | }
99 | }) { (success: Bool) -> Void in
100 | }
101 | }
102 |
103 | func didEndEditing() {
104 | //remove whitespace
105 | self.text = self.text?.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
106 | if !self.text!.isEmpty {
107 | UIView.animateWithDuration(0.4, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: { () -> Void in
108 |
109 | if self.inactiveColour != nil {
110 | self.textFieldImageView.tintColor = self.inactiveColour
111 | }else {
112 | self.textFieldImageView.tintColor = UIColor(red: 205 / 255, green: 205 / 255, blue: 205 / 255, alpha: 1)
113 | }
114 |
115 | }) { (success: Bool) -> Void in
116 | //done
117 |
118 | }
119 | }else {
120 | UIView.animateWithDuration(0.4, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: { () -> Void in
121 | self.textFieldImageView.center = CGPointMake(self.bounds.width / 2, self.bounds.size.height / 2);
122 | if self.inactiveColour != nil {
123 | self.textFieldImageView.tintColor = self.inactiveColour
124 | }else {
125 | self.textFieldImageView.tintColor = UIColor(red: 205 / 255, green: 205 / 255, blue: 205 / 255, alpha: 1)
126 | }
127 | }) { (success: Bool) -> Void in
128 | //done
129 | }
130 | }
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/ACAnimatedTextFieldDemo/ACAnimatedTextFieldDemo/ACAnimatedTextField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ACAnimatedTextField.swift
3 | // RA4WVPN
4 | //
5 | // Created by Alex Catchpole on 19/10/2015.
6 | // Copyright © 2015 Alex Catchpole. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ACAnimatedTextField: UITextField {
12 |
13 | //Global reference to the uiimageview
14 | //Default frame of image, can be customized
15 | private var textFieldImageView: UIImageView = UIImageView(frame: CGRectMake(0, 0, 24, 24))
16 | @IBInspectable var textFieldImage: UIImage? {
17 |
18 | didSet {
19 | textFieldImageView.image = textFieldImage!
20 | }
21 |
22 | }
23 | @IBInspectable var activeColour: UIColor?
24 | @IBInspectable var inactiveColour: UIColor?
25 |
26 | @IBInspectable var imageWidth: NSNumber? {
27 | didSet {
28 | textFieldImageView.frame.size.width = CGFloat(imageWidth!)
29 |
30 | }
31 | }
32 | @IBInspectable var imageHeight: NSNumber? {
33 | didSet {
34 | textFieldImageView.frame.size.height = CGFloat(imageHeight!)
35 |
36 | }
37 | }
38 |
39 | //called after init, when the rect of the textfield is being drawing
40 | override func drawRect(rect: CGRect) {
41 |
42 | //Default corner radius
43 | self.borderStyle = UITextBorderStyle.None
44 | self.textAlignment = NSTextAlignment.Center
45 |
46 | //add uiimageview which was initialized in init?()
47 | self.addSubview(textFieldImageView)
48 |
49 | //set image rendering mode so we can change colour of vector
50 | if textFieldImageView.image != nil {
51 | textFieldImageView.image = textFieldImageView.image!.imageWithRenderingMode(.AlwaysTemplate)
52 | }else {
53 | print("ACAnimatedTextField -- Image Not Set")
54 | }
55 |
56 | //initial colour
57 | if inactiveColour != nil {
58 | textFieldImageView.tintColor = inactiveColour
59 | }else {
60 | textFieldImageView.tintColor = UIColor(red: 205 / 255, green: 205 / 255, blue: 205 / 255, alpha: 1)
61 | }
62 |
63 | //set the center of the uiimageview to self
64 | textFieldImageView.center = CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2)
65 |
66 | //Remove placeholder text because the placeholder is an image
67 | self.placeholder = ""
68 |
69 | }
70 |
71 | override func textRectForBounds(bounds: CGRect) -> CGRect {
72 |
73 | return CGRectInset(bounds, 50, 0)
74 | }
75 |
76 | override func editingRectForBounds(bounds: CGRect) -> CGRect {
77 | return CGRectInset(bounds, 50, 0)
78 | }
79 |
80 | required init?(coder aDecoder: NSCoder) {
81 | super.init(coder: aDecoder)
82 |
83 | //I didn't want to interfere with delegates so the user can use the built in delegates so I'll use targets instead
84 | self.addTarget(self, action: "didBeginEditing", forControlEvents: UIControlEvents.EditingDidBegin)
85 | self.addTarget(self, action: "didEndEditing", forControlEvents: UIControlEvents.EditingDidEnd)
86 |
87 | }
88 |
89 | func didBeginEditing() {
90 | //on edit run animation
91 | UIView.animateWithDuration(0.4, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: { () -> Void in
92 | self.textFieldImageView.center = CGPointMake(30, self.bounds.size.height / 2)
93 | if self.activeColour != nil {
94 | //make sure active colour is set
95 | self.textFieldImageView.tintColor = self.activeColour
96 | }else {
97 | self.textFieldImageView.tintColor = UIColor(red: 50 / 255, green: 50 / 255, blue: 50 / 255, alpha: 1)
98 | }
99 | }) { (success: Bool) -> Void in
100 | }
101 | }
102 |
103 | func didEndEditing() {
104 | //remove whitespace
105 | self.text = self.text?.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
106 | if !self.text!.isEmpty {
107 | UIView.animateWithDuration(0.4, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: { () -> Void in
108 |
109 | if self.inactiveColour != nil {
110 | self.textFieldImageView.tintColor = self.inactiveColour
111 | }else {
112 | self.textFieldImageView.tintColor = UIColor(red: 205 / 255, green: 205 / 255, blue: 205 / 255, alpha: 1)
113 | }
114 |
115 | }) { (success: Bool) -> Void in
116 | //done
117 |
118 | }
119 | }else {
120 | UIView.animateWithDuration(0.4, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: { () -> Void in
121 | self.textFieldImageView.center = CGPointMake(self.bounds.width / 2, self.bounds.size.height / 2);
122 | if self.inactiveColour != nil {
123 | self.textFieldImageView.tintColor = self.inactiveColour
124 | }else {
125 | self.textFieldImageView.tintColor = UIColor(red: 205 / 255, green: 205 / 255, blue: 205 / 255, alpha: 1)
126 | }
127 | }) { (success: Bool) -> Void in
128 | //done
129 | }
130 | }
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/ACAnimatedTextFieldDemo/ACAnimatedTextFieldDemo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1510FA031BD6CA9800AA4DC9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1510FA021BD6CA9800AA4DC9 /* AppDelegate.swift */; };
11 | 1510FA051BD6CA9800AA4DC9 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1510FA041BD6CA9800AA4DC9 /* ViewController.swift */; };
12 | 1510FA081BD6CA9800AA4DC9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1510FA061BD6CA9800AA4DC9 /* Main.storyboard */; };
13 | 1510FA0A1BD6CA9800AA4DC9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1510FA091BD6CA9800AA4DC9 /* Assets.xcassets */; };
14 | 1510FA0D1BD6CA9800AA4DC9 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1510FA0B1BD6CA9800AA4DC9 /* LaunchScreen.storyboard */; };
15 | 1510FA161BD6CAD000AA4DC9 /* ACAnimatedTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1510FA151BD6CAD000AA4DC9 /* ACAnimatedTextField.swift */; settings = {ASSET_TAGS = (); }; };
16 | /* End PBXBuildFile section */
17 |
18 | /* Begin PBXFileReference section */
19 | 1510F9FF1BD6CA9800AA4DC9 /* ACAnimatedTextFieldDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ACAnimatedTextFieldDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
20 | 1510FA021BD6CA9800AA4DC9 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
21 | 1510FA041BD6CA9800AA4DC9 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
22 | 1510FA071BD6CA9800AA4DC9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
23 | 1510FA091BD6CA9800AA4DC9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
24 | 1510FA0C1BD6CA9800AA4DC9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
25 | 1510FA0E1BD6CA9800AA4DC9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
26 | 1510FA151BD6CAD000AA4DC9 /* ACAnimatedTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ACAnimatedTextField.swift; sourceTree = ""; };
27 | /* End PBXFileReference section */
28 |
29 | /* Begin PBXFrameworksBuildPhase section */
30 | 1510F9FC1BD6CA9800AA4DC9 /* Frameworks */ = {
31 | isa = PBXFrameworksBuildPhase;
32 | buildActionMask = 2147483647;
33 | files = (
34 | );
35 | runOnlyForDeploymentPostprocessing = 0;
36 | };
37 | /* End PBXFrameworksBuildPhase section */
38 |
39 | /* Begin PBXGroup section */
40 | 1510F9F61BD6CA9800AA4DC9 = {
41 | isa = PBXGroup;
42 | children = (
43 | 1510FA011BD6CA9800AA4DC9 /* ACAnimatedTextFieldDemo */,
44 | 1510FA001BD6CA9800AA4DC9 /* Products */,
45 | );
46 | sourceTree = "";
47 | };
48 | 1510FA001BD6CA9800AA4DC9 /* Products */ = {
49 | isa = PBXGroup;
50 | children = (
51 | 1510F9FF1BD6CA9800AA4DC9 /* ACAnimatedTextFieldDemo.app */,
52 | );
53 | name = Products;
54 | sourceTree = "";
55 | };
56 | 1510FA011BD6CA9800AA4DC9 /* ACAnimatedTextFieldDemo */ = {
57 | isa = PBXGroup;
58 | children = (
59 | 1510FA141BD6CAA400AA4DC9 /* ACAnimatedTextField */,
60 | 1510FA021BD6CA9800AA4DC9 /* AppDelegate.swift */,
61 | 1510FA041BD6CA9800AA4DC9 /* ViewController.swift */,
62 | 1510FA061BD6CA9800AA4DC9 /* Main.storyboard */,
63 | 1510FA091BD6CA9800AA4DC9 /* Assets.xcassets */,
64 | 1510FA0B1BD6CA9800AA4DC9 /* LaunchScreen.storyboard */,
65 | 1510FA0E1BD6CA9800AA4DC9 /* Info.plist */,
66 | );
67 | path = ACAnimatedTextFieldDemo;
68 | sourceTree = "";
69 | };
70 | 1510FA141BD6CAA400AA4DC9 /* ACAnimatedTextField */ = {
71 | isa = PBXGroup;
72 | children = (
73 | 1510FA151BD6CAD000AA4DC9 /* ACAnimatedTextField.swift */,
74 | );
75 | name = ACAnimatedTextField;
76 | sourceTree = "";
77 | };
78 | /* End PBXGroup section */
79 |
80 | /* Begin PBXNativeTarget section */
81 | 1510F9FE1BD6CA9800AA4DC9 /* ACAnimatedTextFieldDemo */ = {
82 | isa = PBXNativeTarget;
83 | buildConfigurationList = 1510FA111BD6CA9800AA4DC9 /* Build configuration list for PBXNativeTarget "ACAnimatedTextFieldDemo" */;
84 | buildPhases = (
85 | 1510F9FB1BD6CA9800AA4DC9 /* Sources */,
86 | 1510F9FC1BD6CA9800AA4DC9 /* Frameworks */,
87 | 1510F9FD1BD6CA9800AA4DC9 /* Resources */,
88 | );
89 | buildRules = (
90 | );
91 | dependencies = (
92 | );
93 | name = ACAnimatedTextFieldDemo;
94 | productName = ACAnimatedTextFieldDemo;
95 | productReference = 1510F9FF1BD6CA9800AA4DC9 /* ACAnimatedTextFieldDemo.app */;
96 | productType = "com.apple.product-type.application";
97 | };
98 | /* End PBXNativeTarget section */
99 |
100 | /* Begin PBXProject section */
101 | 1510F9F71BD6CA9800AA4DC9 /* Project object */ = {
102 | isa = PBXProject;
103 | attributes = {
104 | LastUpgradeCheck = 0700;
105 | ORGANIZATIONNAME = AlexCatchpole;
106 | TargetAttributes = {
107 | 1510F9FE1BD6CA9800AA4DC9 = {
108 | CreatedOnToolsVersion = 7.0;
109 | };
110 | };
111 | };
112 | buildConfigurationList = 1510F9FA1BD6CA9800AA4DC9 /* Build configuration list for PBXProject "ACAnimatedTextFieldDemo" */;
113 | compatibilityVersion = "Xcode 3.2";
114 | developmentRegion = English;
115 | hasScannedForEncodings = 0;
116 | knownRegions = (
117 | en,
118 | Base,
119 | );
120 | mainGroup = 1510F9F61BD6CA9800AA4DC9;
121 | productRefGroup = 1510FA001BD6CA9800AA4DC9 /* Products */;
122 | projectDirPath = "";
123 | projectRoot = "";
124 | targets = (
125 | 1510F9FE1BD6CA9800AA4DC9 /* ACAnimatedTextFieldDemo */,
126 | );
127 | };
128 | /* End PBXProject section */
129 |
130 | /* Begin PBXResourcesBuildPhase section */
131 | 1510F9FD1BD6CA9800AA4DC9 /* Resources */ = {
132 | isa = PBXResourcesBuildPhase;
133 | buildActionMask = 2147483647;
134 | files = (
135 | 1510FA0D1BD6CA9800AA4DC9 /* LaunchScreen.storyboard in Resources */,
136 | 1510FA0A1BD6CA9800AA4DC9 /* Assets.xcassets in Resources */,
137 | 1510FA081BD6CA9800AA4DC9 /* Main.storyboard in Resources */,
138 | );
139 | runOnlyForDeploymentPostprocessing = 0;
140 | };
141 | /* End PBXResourcesBuildPhase section */
142 |
143 | /* Begin PBXSourcesBuildPhase section */
144 | 1510F9FB1BD6CA9800AA4DC9 /* Sources */ = {
145 | isa = PBXSourcesBuildPhase;
146 | buildActionMask = 2147483647;
147 | files = (
148 | 1510FA051BD6CA9800AA4DC9 /* ViewController.swift in Sources */,
149 | 1510FA031BD6CA9800AA4DC9 /* AppDelegate.swift in Sources */,
150 | 1510FA161BD6CAD000AA4DC9 /* ACAnimatedTextField.swift in Sources */,
151 | );
152 | runOnlyForDeploymentPostprocessing = 0;
153 | };
154 | /* End PBXSourcesBuildPhase section */
155 |
156 | /* Begin PBXVariantGroup section */
157 | 1510FA061BD6CA9800AA4DC9 /* Main.storyboard */ = {
158 | isa = PBXVariantGroup;
159 | children = (
160 | 1510FA071BD6CA9800AA4DC9 /* Base */,
161 | );
162 | name = Main.storyboard;
163 | sourceTree = "";
164 | };
165 | 1510FA0B1BD6CA9800AA4DC9 /* LaunchScreen.storyboard */ = {
166 | isa = PBXVariantGroup;
167 | children = (
168 | 1510FA0C1BD6CA9800AA4DC9 /* Base */,
169 | );
170 | name = LaunchScreen.storyboard;
171 | sourceTree = "";
172 | };
173 | /* End PBXVariantGroup section */
174 |
175 | /* Begin XCBuildConfiguration section */
176 | 1510FA0F1BD6CA9800AA4DC9 /* Debug */ = {
177 | isa = XCBuildConfiguration;
178 | buildSettings = {
179 | ALWAYS_SEARCH_USER_PATHS = NO;
180 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
181 | CLANG_CXX_LIBRARY = "libc++";
182 | CLANG_ENABLE_MODULES = YES;
183 | CLANG_ENABLE_OBJC_ARC = YES;
184 | CLANG_WARN_BOOL_CONVERSION = YES;
185 | CLANG_WARN_CONSTANT_CONVERSION = YES;
186 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
187 | CLANG_WARN_EMPTY_BODY = YES;
188 | CLANG_WARN_ENUM_CONVERSION = YES;
189 | CLANG_WARN_INT_CONVERSION = YES;
190 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
191 | CLANG_WARN_UNREACHABLE_CODE = YES;
192 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
193 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
194 | COPY_PHASE_STRIP = NO;
195 | DEBUG_INFORMATION_FORMAT = dwarf;
196 | ENABLE_STRICT_OBJC_MSGSEND = YES;
197 | ENABLE_TESTABILITY = YES;
198 | GCC_C_LANGUAGE_STANDARD = gnu99;
199 | GCC_DYNAMIC_NO_PIC = NO;
200 | GCC_NO_COMMON_BLOCKS = YES;
201 | GCC_OPTIMIZATION_LEVEL = 0;
202 | GCC_PREPROCESSOR_DEFINITIONS = (
203 | "DEBUG=1",
204 | "$(inherited)",
205 | );
206 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
207 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
208 | GCC_WARN_UNDECLARED_SELECTOR = YES;
209 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
210 | GCC_WARN_UNUSED_FUNCTION = YES;
211 | GCC_WARN_UNUSED_VARIABLE = YES;
212 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
213 | MTL_ENABLE_DEBUG_INFO = YES;
214 | ONLY_ACTIVE_ARCH = YES;
215 | SDKROOT = iphoneos;
216 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
217 | TARGETED_DEVICE_FAMILY = "1,2";
218 | };
219 | name = Debug;
220 | };
221 | 1510FA101BD6CA9800AA4DC9 /* Release */ = {
222 | isa = XCBuildConfiguration;
223 | buildSettings = {
224 | ALWAYS_SEARCH_USER_PATHS = NO;
225 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
226 | CLANG_CXX_LIBRARY = "libc++";
227 | CLANG_ENABLE_MODULES = YES;
228 | CLANG_ENABLE_OBJC_ARC = YES;
229 | CLANG_WARN_BOOL_CONVERSION = YES;
230 | CLANG_WARN_CONSTANT_CONVERSION = YES;
231 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
232 | CLANG_WARN_EMPTY_BODY = YES;
233 | CLANG_WARN_ENUM_CONVERSION = YES;
234 | CLANG_WARN_INT_CONVERSION = YES;
235 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
236 | CLANG_WARN_UNREACHABLE_CODE = YES;
237 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
238 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
239 | COPY_PHASE_STRIP = NO;
240 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
241 | ENABLE_NS_ASSERTIONS = NO;
242 | ENABLE_STRICT_OBJC_MSGSEND = YES;
243 | GCC_C_LANGUAGE_STANDARD = gnu99;
244 | GCC_NO_COMMON_BLOCKS = YES;
245 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
246 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
247 | GCC_WARN_UNDECLARED_SELECTOR = YES;
248 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
249 | GCC_WARN_UNUSED_FUNCTION = YES;
250 | GCC_WARN_UNUSED_VARIABLE = YES;
251 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
252 | MTL_ENABLE_DEBUG_INFO = NO;
253 | SDKROOT = iphoneos;
254 | TARGETED_DEVICE_FAMILY = "1,2";
255 | VALIDATE_PRODUCT = YES;
256 | };
257 | name = Release;
258 | };
259 | 1510FA121BD6CA9800AA4DC9 /* Debug */ = {
260 | isa = XCBuildConfiguration;
261 | buildSettings = {
262 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
263 | INFOPLIST_FILE = ACAnimatedTextFieldDemo/Info.plist;
264 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
265 | PRODUCT_BUNDLE_IDENTIFIER = uk.co.alexcatchpole.ACAnimatedTextFieldDemo;
266 | PRODUCT_NAME = "$(TARGET_NAME)";
267 | };
268 | name = Debug;
269 | };
270 | 1510FA131BD6CA9800AA4DC9 /* Release */ = {
271 | isa = XCBuildConfiguration;
272 | buildSettings = {
273 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
274 | INFOPLIST_FILE = ACAnimatedTextFieldDemo/Info.plist;
275 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
276 | PRODUCT_BUNDLE_IDENTIFIER = uk.co.alexcatchpole.ACAnimatedTextFieldDemo;
277 | PRODUCT_NAME = "$(TARGET_NAME)";
278 | };
279 | name = Release;
280 | };
281 | /* End XCBuildConfiguration section */
282 |
283 | /* Begin XCConfigurationList section */
284 | 1510F9FA1BD6CA9800AA4DC9 /* Build configuration list for PBXProject "ACAnimatedTextFieldDemo" */ = {
285 | isa = XCConfigurationList;
286 | buildConfigurations = (
287 | 1510FA0F1BD6CA9800AA4DC9 /* Debug */,
288 | 1510FA101BD6CA9800AA4DC9 /* Release */,
289 | );
290 | defaultConfigurationIsVisible = 0;
291 | defaultConfigurationName = Release;
292 | };
293 | 1510FA111BD6CA9800AA4DC9 /* Build configuration list for PBXNativeTarget "ACAnimatedTextFieldDemo" */ = {
294 | isa = XCConfigurationList;
295 | buildConfigurations = (
296 | 1510FA121BD6CA9800AA4DC9 /* Debug */,
297 | 1510FA131BD6CA9800AA4DC9 /* Release */,
298 | );
299 | defaultConfigurationIsVisible = 0;
300 | };
301 | /* End XCConfigurationList section */
302 | };
303 | rootObject = 1510F9F71BD6CA9800AA4DC9 /* Project object */;
304 | }
305 |
--------------------------------------------------------------------------------