├── .swift-version
├── Screenshots
├── Isao.gif
├── Jiro.gif
├── Yoko.gif
├── Akira.gif
├── Hoshi.gif
├── Kaede.gif
├── Madoka.gif
├── Minoru.gif
└── Yoshiko.gif
├── .swiftpm
└── xcode
│ └── package 2.xcworkspace
│ └── contents.xcworkspacedata
├── TextFieldEffects
├── TextFieldEffects.xcodeproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ ├── xcshareddata
│ │ └── xcschemes
│ │ │ └── TextFieldEffects.xcscheme
│ └── project.pbxproj
├── TextFieldEffects
│ ├── TextFieldEffects.h
│ ├── Info.plist
│ ├── TextFieldEffects.swift
│ ├── AkiraTextField.swift
│ ├── KaedeTextField.swift
│ ├── MinoruTextField.swift
│ ├── JiroTextField.swift
│ ├── IsaoTextField.swift
│ ├── MadokaTextField.swift
│ ├── HoshiTextField.swift
│ ├── YoshikoTextField.swift
│ └── YokoTextField.swift
└── TextFieldsDemo
│ ├── Images.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
│ ├── ExampleTableViewController.swift
│ ├── Info.plist
│ ├── AppDelegate.swift
│ └── Base.lproj
│ ├── LaunchScreen.xib
│ └── Main.storyboard
├── .travis.yml
├── Package.swift
├── .gitignore
├── .github
└── stale.yml
├── LICENSE
├── CHANGELOG.md
├── README.md
└── TextFieldEffects.podspec
/.swift-version:
--------------------------------------------------------------------------------
1 | 5.0
2 |
--------------------------------------------------------------------------------
/Screenshots/Isao.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raulriera/TextFieldEffects/HEAD/Screenshots/Isao.gif
--------------------------------------------------------------------------------
/Screenshots/Jiro.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raulriera/TextFieldEffects/HEAD/Screenshots/Jiro.gif
--------------------------------------------------------------------------------
/Screenshots/Yoko.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raulriera/TextFieldEffects/HEAD/Screenshots/Yoko.gif
--------------------------------------------------------------------------------
/Screenshots/Akira.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raulriera/TextFieldEffects/HEAD/Screenshots/Akira.gif
--------------------------------------------------------------------------------
/Screenshots/Hoshi.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raulriera/TextFieldEffects/HEAD/Screenshots/Hoshi.gif
--------------------------------------------------------------------------------
/Screenshots/Kaede.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raulriera/TextFieldEffects/HEAD/Screenshots/Kaede.gif
--------------------------------------------------------------------------------
/Screenshots/Madoka.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raulriera/TextFieldEffects/HEAD/Screenshots/Madoka.gif
--------------------------------------------------------------------------------
/Screenshots/Minoru.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raulriera/TextFieldEffects/HEAD/Screenshots/Minoru.gif
--------------------------------------------------------------------------------
/Screenshots/Yoshiko.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raulriera/TextFieldEffects/HEAD/Screenshots/Yoshiko.gif
--------------------------------------------------------------------------------
/.swiftpm/xcode/package 2.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldEffects.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: swift
2 | osx_image: xcode10
3 | xcode_project: TextFieldEffects/TextFieldEffects.xcodeproj
4 | xcode_schema: TextFieldEffects
5 | notifications:
6 | disabled: true
7 | script:
8 | - xcodebuild -scheme TextFieldEffects -destination "OS=12.0,name=iPhone SE" -sdk iphonesimulator12.0 | xcpretty -c
9 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldEffects.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.2
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "TextFieldEffects",
8 | products: [
9 | .library(name: "TextFieldEffects", targets: ["TextFieldEffects"]),
10 | ],
11 | targets: [
12 | .target(name: "TextFieldEffects", path: "TextFieldEffects/TextFieldEffects")
13 | ]
14 | )
15 |
--------------------------------------------------------------------------------
/.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 | .DS_Store
28 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldEffects/TextFieldEffects.h:
--------------------------------------------------------------------------------
1 | //
2 | // TextFieldEffects.h
3 | // TextFieldEffects
4 | //
5 | // Created by Raúl Riera on 05/03/2015.
6 | // Copyright (c) 2015 Raul Riera. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for TextFieldEffects.
12 | FOUNDATION_EXPORT double TextFieldEffectsVersionNumber;
13 |
14 | //! Project version string for TextFieldEffects.
15 | FOUNDATION_EXPORT const unsigned char TextFieldEffectsVersionString[];
16 |
17 | // In this header, you should import all the open headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Number of days of inactivity before an issue becomes stale
2 | daysUntilStale: 21
3 | # Number of days of inactivity before a stale issue is closed
4 | daysUntilClose: 3
5 | # Issues with these labels will never be considered stale
6 | exemptLabels:
7 | - pinned
8 | # Label to use when marking an issue as stale
9 | staleLabel: stale
10 | # Comment to post when marking an issue as stale. Set to `false` to disable
11 | markComment: >
12 | This issue has been automatically marked as stale because it has not had
13 | recent activity. It will be closed in 3 days if no further activity occurs.
14 | # Comment to post when closing a stale issue. Set to `false` to disable
15 | closeComment: false
16 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldsDemo/Images.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 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldsDemo/ExampleTableViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExampleTableViewController.swift
3 | // TextFieldEffects
4 | //
5 | // Created by Raúl Riera on 28/08/2015.
6 | // Copyright © 2015 Raul Riera. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import TextFieldEffects
11 |
12 | class ExampleTableViewController : UITableViewController {
13 |
14 | @IBOutlet private var textFields: [TextFieldEffects]!
15 |
16 | /**
17 | Set this value to true if you want to see all the "firstName"
18 | textFields prepopulated with the name "Raul" (for testing purposes)
19 | */
20 | let prefillTextFields = false
21 |
22 | override func viewDidLoad() {
23 | super.viewDidLoad()
24 |
25 | guard prefillTextFields == true else { return }
26 |
27 | _ = textFields.map { $0.text = "Raul" }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldEffects/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 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Raul Riera
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 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## Version 1.6.0
4 | * Support for Swift 5 and Xcode 11
5 |
6 | ## Version 1.5.1
7 | * Syntax improvements
8 | * Removed old Swift 4.2 migration code
9 |
10 | ## Version 1.5.0
11 | * Support for iOS 12
12 |
13 | ## Version 1.4.0
14 | * Support for iOS 11
15 |
16 | ## Version 1.3.3
17 | * Fixes https://github.com/raulriera/TextFieldEffects/issues/118
18 |
19 | ## Version 1.3.2
20 | * Renaming broke the project
21 | * Fixes https://github.com/raulriera/TextFieldEffects/issues/120
22 |
23 | ## Version 1.3.1
24 | * Fixes https://github.com/raulriera/TextFieldEffects/issues/67
25 | * Remove all project's warnings
26 |
27 | ## Version 1.3.0
28 | * Swift 3.0 support
29 |
30 | ## Version 1.2.0
31 | * Swift 2.2 support
32 | * Support for animation completion blocks
33 |
34 | ## Version 1.1.1
35 | * Fixes bug #57 in Yoshiko
36 |
37 | ## Version 1.1.0
38 | * Support to change the placeholder font via the `placeholderFontScale` property.
39 | * Fixed some minor issues with the example project.
40 |
41 | ## Version 1.0.0
42 | * Initial release with 9 different UITextField effects.
43 | * Full Interface Builder support.
44 | * Full code only support.
45 | * Cocoapods support.
46 | * Carthage support.
47 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldsDemo/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 | UIInterfaceOrientationPortraitUpsideDown
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldsDemo/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // TextFieldsDemo
4 | //
5 | // Created by Raúl Riera on 22/01/2015.
6 | // Copyright (c) 2015 Raul Riera. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | @nonobjc 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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TextFieldEffects [](https://travis-ci.org/raulriera/TextFieldEffects)
2 |
3 | I fell in love with the text inputs effects in [this article](http://tympanus.net/codrops/2015/01/08/inspiration-text-input-effects/). As an exercise I decided to recreate as many of them as I can using Swift *(some of them have a personal touch)*.
4 |
5 | Currently it features the following effects from the article:
6 |
7 | - [x] Kaede
8 | - [x] Hoshi
9 | - [x] Jiro
10 | - [x] Isao
11 | - [x] Minoru
12 | - [x] Yoko
13 | - [x] Madoka
14 | - [x] Akira
15 | - [x] Yoshiko
16 |
17 | ## How they look
18 |
19 | ### Kaede
20 |
21 |
22 | ### Hoshi
23 |
24 |
25 | ### Jiro
26 |
27 |
28 | ### Isao
29 |
30 |
31 | ### Minoru
32 |
33 |
34 | ### Yoko
35 |
36 |
37 | ### Madoka
38 |
39 |
40 | ### Akira
41 |
42 |
43 | ### Yoshiko
44 |
45 |
46 | ## Installation
47 |
48 | - Looking for Swift 2.3 support? Check out the [1.2.0](https://github.com/raulriera/TextFieldEffects/releases/tag/1.2.0) tag.
49 | - Looking for Swift 2.1 support? Check out the [1.1.1](https://github.com/raulriera/TextFieldEffects/releases/tag/1.1.1) tag.
50 | - Looking for Swift 1.2 support? Check out the `swift-1.2` branch.
51 |
52 | ### Manual
53 |
54 | The easiest way to install this framework is to drag and drop the `TextFieldEffects/TextFieldEffects` folder into your project. This also prevents the `frameworks` [problem in iOS](http://www.openradar.me/21258097) where the IBInspectable and IBDesignable are stripped out.
55 |
56 | ### CocoaPods
57 |
58 | Add the following to your Podfile:
59 |
60 | ``` ruby
61 | use_frameworks!
62 | pod 'TextFieldEffects'
63 | ```
64 |
65 | ### Carthage
66 |
67 | Add the following to your Cartfile:
68 |
69 | ``` ruby
70 | github 'raulriera/TextFieldEffects'
71 | ```
72 |
73 | ## How to use them
74 |
75 | Every effect is properly documented in the source code, this is the best way to both understand and see what they do. There is also an example project included with all the effects and their settings.
76 |
77 | ### Interface Builder
78 |
79 | The library is a simple drop-in, as soon as you set your subclass to one of the effects and your module to `TextFieldEffects` you will be able to see all the IBDesignable settings in the storyboard.
80 |
81 | ### Code
82 |
83 | If you like to get your hands dirty, you can use them just like you would normally use any `UITextField`
84 |
85 | ``` swift
86 | let textField = KaedeTextField(frame: textFieldFrame)
87 | textField.placeholderColor = .darkGrayColor()
88 | textField.foregroundColor = .lightGrayColor()
89 |
90 | view.addSubView(textField)
91 | ```
92 |
93 | Is that simple.
94 |
95 | ## Created by
96 | Raul Riera, [@raulriera](http://twitter.com/raulriera)
97 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldsDemo/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
21 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/TextFieldEffects.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # Be sure to run `pod spec lint TextFieldEffects.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 http://docs.cocoapods.org/specification.html
6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
7 | #
8 |
9 | Pod::Spec.new do |s|
10 |
11 | # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
12 | #
13 | # These will help people to find your library, and whilst it
14 | # can feel like a chore to fill in it's definitely to your advantage. The
15 | # summary should be tweet-length, and the description more in depth.
16 | #
17 |
18 | s.name = "TextFieldEffects"
19 | s.version = "1.7.0"
20 | s.summary = "Custom drop in UITextFields effects."
21 |
22 | s.description = <<-DESC
23 | TextFieldEffects enables a collection of drop in effects to standard UITextFields.
24 | DESC
25 |
26 | s.homepage = "http://github.com/raulriera/TextFieldEffects"
27 | s.screenshots = "https://raw.githubusercontent.com/raulriera/TextFieldEffects/master/Screenshots/Kaede.gif", "https://raw.githubusercontent.com/raulriera/TextFieldEffects/master/Screenshots/Hoshi.gif", "https://raw.githubusercontent.com/raulriera/TextFieldEffects/master/Screenshots/Jiro.gif", "https://raw.githubusercontent.com/raulriera/TextFieldEffects/master/Screenshots/Isao.gif", "https://raw.githubusercontent.com/raulriera/TextFieldEffects/master/Screenshots/Minoru.gif", "https://raw.githubusercontent.com/raulriera/TextFieldEffects/master/Screenshots/Yoko.gif", "https://raw.githubusercontent.com/raulriera/TextFieldEffects/master/Screenshots/Madoka.gif",
28 | "https://raw.githubusercontent.com/raulriera/TextFieldEffects/master/Screenshots/Akira.gif",
29 | "https://raw.githubusercontent.com/raulriera/TextFieldEffects/master/Screenshots/Yoshiko.gif"
30 |
31 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
32 | #
33 | # Licensing your code is important. See http://choosealicense.com for more info.
34 | # CocoaPods will detect a license file if there is a named LICENSE*
35 | # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'.
36 | #
37 |
38 | s.license = "MIT"
39 |
40 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
41 | #
42 | # Specify the authors of the library, with email addresses. Email addresses
43 | # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also
44 | # accepts just a name if you'd rather not provide an email address.
45 | #
46 | # Specify a social_media_url where others can refer to, for example a twitter
47 | # profile URL.
48 | #
49 |
50 | s.author = { "Raul Riera" => "rieraraul@gmail.com" }
51 | s.social_media_url = "http://twitter.com/raulriera"
52 |
53 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
54 | #
55 | # If this Pod runs only on iOS or OS X, then specify the platform and
56 | # the deployment target. You can optionally include the target after the platform.
57 | #
58 |
59 | s.platform = :ios, '8.0'
60 | s.swift_version = '5.0'
61 |
62 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
63 | #
64 | # Specify the location from where the source should be retrieved.
65 | # Supports git, hg, bzr, svn and HTTP.
66 | #
67 |
68 | s.source = { :git => "https://github.com/raulriera/TextFieldEffects.git", :tag => s.version.to_s }
69 |
70 | # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
71 | #
72 | # CocoaPods is smart about how it includes source code. For source files
73 | # giving a folder will include any h, m, mm, c & cpp files. For header
74 | # files it will include any header in the folder.
75 | # Not including the public_header_files will make all headers public.
76 | #
77 |
78 | s.source_files = 'TextFieldEffects/TextFieldEffects/*.swift'
79 | end
80 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldEffects.xcodeproj/xcshareddata/xcschemes/TextFieldEffects.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
56 |
57 |
67 |
68 |
74 |
75 |
76 |
77 |
83 |
84 |
90 |
91 |
92 |
93 |
95 |
96 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldEffects/TextFieldEffects.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TextFieldEffects.swift
3 | // TextFieldEffects
4 | //
5 | // Created by Raúl Riera on 24/01/2015.
6 | // Copyright (c) 2015 Raul Riera. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension String {
12 | /**
13 | true if self contains characters.
14 | */
15 | var isNotEmpty: Bool {
16 | return !isEmpty
17 | }
18 | }
19 |
20 | /**
21 | A TextFieldEffects object is a control that displays editable text and contains the boilerplates to setup unique animations for text entry and display. You typically use this class the same way you use UITextField.
22 | */
23 | open class TextFieldEffects : UITextField {
24 | /**
25 | The type of animation a TextFieldEffect can perform.
26 |
27 | - TextEntry: animation that takes effect when the textfield has focus.
28 | - TextDisplay: animation that takes effect when the textfield loses focus.
29 | */
30 | public enum AnimationType: Int {
31 | case textEntry
32 | case textDisplay
33 | }
34 |
35 | /**
36 | Closure executed when an animation has been completed.
37 | */
38 | public typealias AnimationCompletionHandler = (_ type: AnimationType)->()
39 |
40 | /**
41 | UILabel that holds all the placeholder information
42 | */
43 | public let placeholderLabel = UILabel()
44 |
45 | /**
46 | Creates all the animations that are used to leave the textfield in the "entering text" state.
47 | */
48 | open func animateViewsForTextEntry() {
49 | fatalError("\(#function) must be overridden")
50 | }
51 |
52 | /**
53 | Creates all the animations that are used to leave the textfield in the "display input text" state.
54 | */
55 | open func animateViewsForTextDisplay() {
56 | fatalError("\(#function) must be overridden")
57 | }
58 |
59 | /**
60 | The animation completion handler is the best place to be notified when the text field animation has ended.
61 | */
62 | open var animationCompletionHandler: AnimationCompletionHandler?
63 |
64 | /**
65 | Draws the receiver’s image within the passed-in rectangle.
66 |
67 | - parameter rect: The portion of the view’s bounds that needs to be updated.
68 | */
69 | open func drawViewsForRect(_ rect: CGRect) {
70 | fatalError("\(#function) must be overridden")
71 | }
72 |
73 | open func updateViewsForBoundsChange(_ bounds: CGRect) {
74 | fatalError("\(#function) must be overridden")
75 | }
76 |
77 | // MARK: - Overrides
78 |
79 | override open func draw(_ rect: CGRect) {
80 | // FIXME: Short-circuit if the view is currently selected. iOS 11 introduced
81 | // a setNeedsDisplay when you focus on a textfield, calling this method again
82 | // and messing up some of the effects due to the logic contained inside these
83 | // methods.
84 | // This is just a "quick fix", something better needs to come along.
85 | guard isFirstResponder == false else { return }
86 | drawViewsForRect(rect)
87 | }
88 |
89 | override open func drawPlaceholder(in rect: CGRect) {
90 | // Don't draw any placeholders
91 | }
92 |
93 | override open var text: String? {
94 | didSet {
95 | if let text = text, text.isNotEmpty || isFirstResponder {
96 | animateViewsForTextEntry()
97 | } else {
98 | animateViewsForTextDisplay()
99 | }
100 | }
101 | }
102 |
103 | // MARK: - UITextField Observing
104 |
105 | override open func willMove(toSuperview newSuperview: UIView!) {
106 | if newSuperview != nil {
107 | NotificationCenter.default.addObserver(self, selector: #selector(textFieldDidEndEditing), name: UITextField.textDidEndEditingNotification, object: self)
108 |
109 | NotificationCenter.default.addObserver(self, selector: #selector(textFieldDidBeginEditing), name: UITextField.textDidBeginEditingNotification, object: self)
110 | } else {
111 | NotificationCenter.default.removeObserver(self)
112 | }
113 | }
114 |
115 | /**
116 | The textfield has started an editing session.
117 | */
118 | @objc open func textFieldDidBeginEditing() {
119 | animateViewsForTextEntry()
120 | }
121 |
122 | /**
123 | The textfield has ended an editing session.
124 | */
125 | @objc open func textFieldDidEndEditing() {
126 | animateViewsForTextDisplay()
127 | }
128 |
129 | // MARK: - Interface Builder
130 |
131 | override open func prepareForInterfaceBuilder() {
132 | drawViewsForRect(frame)
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldEffects/AkiraTextField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AkiraTextField.swift
3 | // TextFieldEffects
4 | //
5 | // Created by Mihaela Miches on 5/31/15.
6 | // Copyright (c) 2015 Raul Riera. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /**
12 | An AkiraTextField is a subclass of the TextFieldEffects object, is a control that displays an UITextField with a customizable visual effect around the edges of the control.
13 | */
14 | @IBDesignable open class AkiraTextField : TextFieldEffects {
15 | private let borderSize: (active: CGFloat, inactive: CGFloat) = (1, 2)
16 | private let borderLayer = CALayer()
17 | private let textFieldInsets = CGPoint(x: 6, y: 0)
18 | private let placeholderInsets = CGPoint(x: 6, y: 0)
19 |
20 | /**
21 | The color of the border.
22 |
23 | This property applies a color to the bounds of the control. The default value for this property is a clear color.
24 | */
25 | @IBInspectable dynamic open var borderColor: UIColor? {
26 | didSet {
27 | updateBorder()
28 | }
29 | }
30 |
31 | /**
32 | The color of the placeholder text.
33 |
34 | This property applies a color to the complete placeholder string. The default value for this property is a black color.
35 | */
36 | @IBInspectable dynamic open var placeholderColor: UIColor = .black {
37 | didSet {
38 | updatePlaceholder()
39 | }
40 | }
41 |
42 | /**
43 | The scale of the placeholder font.
44 |
45 | This property determines the size of the placeholder label relative to the font size of the text field.
46 | */
47 | @IBInspectable dynamic open var placeholderFontScale: CGFloat = 0.7 {
48 | didSet {
49 | updatePlaceholder()
50 | }
51 | }
52 |
53 | override open var placeholder: String? {
54 | didSet {
55 | updatePlaceholder()
56 | }
57 | }
58 |
59 | override open var bounds: CGRect {
60 | didSet {
61 | updateBorder()
62 | }
63 | }
64 |
65 | // MARK: TextFieldEffects
66 |
67 | override open func drawViewsForRect(_ rect: CGRect) {
68 | updateBorder()
69 | updatePlaceholder()
70 |
71 | addSubview(placeholderLabel)
72 | layer.addSublayer(borderLayer)
73 | }
74 |
75 | override open func animateViewsForTextEntry() {
76 | UIView.animate(withDuration: 0.3, animations: {
77 | self.updateBorder()
78 | self.updatePlaceholder()
79 | }, completion: { _ in
80 | self.animationCompletionHandler?(.textEntry)
81 | })
82 | }
83 |
84 | override open func animateViewsForTextDisplay() {
85 | UIView.animate(withDuration: 0.3, animations: {
86 | self.updateBorder()
87 | self.updatePlaceholder()
88 | }, completion: { _ in
89 | self.animationCompletionHandler?(.textDisplay)
90 | })
91 | }
92 |
93 | // MARK: Private
94 |
95 | private func updatePlaceholder() {
96 | placeholderLabel.frame = placeholderRect(forBounds: bounds)
97 | placeholderLabel.text = placeholder
98 | placeholderLabel.font = placeholderFontFromFont(font!)
99 | placeholderLabel.textColor = placeholderColor
100 | placeholderLabel.textAlignment = textAlignment
101 | }
102 |
103 | private func updateBorder() {
104 | borderLayer.frame = rectForBounds(bounds)
105 | borderLayer.borderWidth = (isFirstResponder || text!.isNotEmpty) ? borderSize.active : borderSize.inactive
106 | borderLayer.borderColor = borderColor?.cgColor
107 | }
108 |
109 | private func placeholderFontFromFont(_ font: UIFont) -> UIFont! {
110 | let smallerFont = UIFont(descriptor: font.fontDescriptor, size: font.pointSize * placeholderFontScale)
111 | return smallerFont
112 | }
113 |
114 | private var placeholderHeight : CGFloat {
115 | return placeholderInsets.y + placeholderFontFromFont(font!).lineHeight
116 | }
117 |
118 | private func rectForBounds(_ bounds: CGRect) -> CGRect {
119 | return CGRect(x: bounds.origin.x, y: bounds.origin.y + placeholderHeight, width: bounds.size.width, height: bounds.size.height - placeholderHeight)
120 | }
121 |
122 | // MARK: - Overrides
123 |
124 | open override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
125 | if isFirstResponder || text!.isNotEmpty {
126 | return CGRect(x: placeholderInsets.x, y: placeholderInsets.y, width: bounds.width, height: placeholderHeight)
127 | } else {
128 | return textRect(forBounds: bounds)
129 | }
130 | }
131 |
132 | open override func editingRect(forBounds bounds: CGRect) -> CGRect {
133 | return textRect(forBounds: bounds)
134 | }
135 |
136 | override open func textRect(forBounds bounds: CGRect) -> CGRect {
137 | return bounds.offsetBy(dx: textFieldInsets.x, dy: textFieldInsets.y + placeholderHeight/2)
138 | }
139 | }
140 |
141 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldEffects/KaedeTextField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // KaedeTextField.swift
3 | // Swish
4 | //
5 | // Created by Raúl Riera on 20/01/2015.
6 | // Copyright (c) 2015 com.raulriera.swishapp. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /**
12 | A KaedeTextField is a subclass of the TextFieldEffects object, is a control that displays an UITextField with a customizable visual effect around the foreground of the control.
13 | */
14 | @IBDesignable open class KaedeTextField: TextFieldEffects {
15 | /**
16 | The color of the placeholder text.
17 |
18 | This property applies a color to the complete placeholder string. The default value for this property is a black color.
19 | */
20 | @IBInspectable dynamic open var placeholderColor: UIColor? {
21 | didSet {
22 | updatePlaceholder()
23 | }
24 | }
25 |
26 | /**
27 | The scale of the placeholder font.
28 |
29 | This property determines the size of the placeholder label relative to the font size of the text field.
30 | */
31 | @IBInspectable dynamic open var placeholderFontScale: CGFloat = 0.8 {
32 | didSet {
33 | updatePlaceholder()
34 | }
35 | }
36 |
37 | /**
38 | The view’s foreground color.
39 |
40 | The default value for this property is a clear color.
41 | */
42 | @IBInspectable dynamic open var foregroundColor: UIColor? {
43 | didSet {
44 | updateForegroundColor()
45 | }
46 | }
47 |
48 | /**
49 | The starting x position (as a percentage) of the placeholder area.
50 | */
51 | @IBInspectable dynamic open var placeholderSplit: CGFloat = 0.6
52 |
53 | override open var placeholder: String? {
54 | didSet {
55 | updatePlaceholder()
56 | }
57 | }
58 |
59 | override open var bounds: CGRect {
60 | didSet {
61 | drawViewsForRect(bounds)
62 | }
63 | }
64 |
65 | private let foregroundView = UIView()
66 | private let placeholderInsets = CGPoint(x: 10, y: 5)
67 | private let textFieldInsets = CGPoint(x: 10, y: 0)
68 |
69 | // MARK: - TextFieldEffects
70 |
71 | override open func drawViewsForRect(_ rect: CGRect) {
72 | let frame = CGRect(origin: .zero, size: CGSize(width: rect.size.width, height: rect.size.height))
73 |
74 | foregroundView.frame = frame
75 | foregroundView.isUserInteractionEnabled = false
76 | placeholderLabel.frame = frame.insetBy(dx: placeholderInsets.x, dy: placeholderInsets.y)
77 | placeholderLabel.font = placeholderFontFromFont(font!)
78 |
79 | updateForegroundColor()
80 | updatePlaceholder()
81 |
82 | if text!.isNotEmpty || isFirstResponder {
83 | animateViewsForTextEntry()
84 | }
85 |
86 | addSubview(foregroundView)
87 | addSubview(placeholderLabel)
88 | }
89 |
90 | override open func animateViewsForTextEntry() {
91 | let directionOverride: CGFloat
92 |
93 | if #available(iOS 9.0, *) {
94 | directionOverride = UIView.userInterfaceLayoutDirection(for: semanticContentAttribute) == .rightToLeft ? -1.0 : 1.0
95 | } else {
96 | directionOverride = 1.0
97 | }
98 |
99 | UIView.animate(withDuration: 0.35, delay: 0.0, usingSpringWithDamping: 0.8, initialSpringVelocity: 2.0, options: .beginFromCurrentState, animations: ({
100 | self.placeholderLabel.frame.origin = CGPoint(x: self.frame.size.width * (self.placeholderSplit + 0.05) * directionOverride, y: self.placeholderInsets.y)
101 | }), completion: nil)
102 |
103 | UIView.animate(withDuration: 0.45, delay: 0.0, usingSpringWithDamping: 0.8, initialSpringVelocity: 1.5, options: .beginFromCurrentState, animations: ({
104 | self.foregroundView.frame.origin = CGPoint(x: self.frame.size.width * self.placeholderSplit * directionOverride, y: 0)
105 | }), completion: { _ in
106 | self.animationCompletionHandler?(.textEntry)
107 | })
108 | }
109 |
110 | override open func animateViewsForTextDisplay() {
111 | if text!.isEmpty {
112 | UIView.animate(withDuration: 0.3, delay: 0.0, usingSpringWithDamping: 0.8, initialSpringVelocity: 2.0, options: .beginFromCurrentState, animations: ({
113 | self.placeholderLabel.frame.origin = self.placeholderInsets
114 | }), completion: nil)
115 |
116 | UIView.animate(withDuration: 0.3, delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 2.0, options: .beginFromCurrentState, animations: ({
117 | self.foregroundView.frame.origin = CGPoint.zero
118 | }), completion: { _ in
119 | self.animationCompletionHandler?(.textDisplay)
120 | })
121 | }
122 | }
123 |
124 | // MARK: - Private
125 |
126 | private func updateForegroundColor() {
127 | foregroundView.backgroundColor = foregroundColor
128 | }
129 |
130 | private func updatePlaceholder() {
131 | placeholderLabel.text = placeholder
132 | placeholderLabel.textColor = placeholderColor
133 | }
134 |
135 | private func placeholderFontFromFont(_ font: UIFont) -> UIFont! {
136 | let smallerFont = UIFont(descriptor: font.fontDescriptor, size: font.pointSize * placeholderFontScale)
137 | return smallerFont
138 | }
139 |
140 | // MARK: - Overrides
141 |
142 | override open func editingRect(forBounds bounds: CGRect) -> CGRect {
143 | var frame = CGRect(origin: bounds.origin, size: CGSize(width: bounds.size.width * placeholderSplit, height: bounds.size.height))
144 |
145 | if #available(iOS 9.0, *) {
146 | if UIView.userInterfaceLayoutDirection(for: semanticContentAttribute) == .rightToLeft {
147 | frame.origin = CGPoint(x: bounds.size.width - frame.size.width, y: frame.origin.y)
148 | }
149 | }
150 |
151 | return frame.insetBy(dx: textFieldInsets.x, dy: textFieldInsets.y)
152 | }
153 |
154 | override open func textRect(forBounds bounds: CGRect) -> CGRect {
155 | return editingRect(forBounds: bounds)
156 | }
157 |
158 | }
159 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldEffects/MinoruTextField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MinoruTextField.swift
3 | // TextFieldEffects
4 | //
5 | // Created by Raúl Riera on 27/01/2015.
6 | // Copyright (c) 2015 Raul Riera. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /**
12 | A MinoruTextField is a subclass of the TextFieldEffects object, is a control that displays an UITextField with a customizable visual effect around the edges of the control.
13 | */
14 | @IBDesignable open class MinoruTextField: TextFieldEffects {
15 | /**
16 | The color of the placeholder text.
17 |
18 | This property applies a color to the complete placeholder string. The default value for this property is a black color.
19 | */
20 | @IBInspectable dynamic open var placeholderColor: UIColor = .black {
21 | didSet {
22 | updatePlaceholder()
23 | }
24 | }
25 |
26 | override open var backgroundColor: UIColor? {
27 | set {
28 | backgroundLayerColor = newValue
29 | }
30 | get {
31 | return backgroundLayerColor
32 | }
33 | }
34 |
35 | /**
36 | The scale of the placeholder font.
37 |
38 | This property determines the size of the placeholder label relative to the font size of the text field.
39 | */
40 | @IBInspectable dynamic open var placeholderFontScale: CGFloat = 0.65 {
41 | didSet {
42 | updatePlaceholder()
43 | }
44 | }
45 |
46 | override open var placeholder: String? {
47 | didSet {
48 | updatePlaceholder()
49 | }
50 | }
51 |
52 | override open var bounds: CGRect {
53 | didSet {
54 | updateBorder()
55 | updatePlaceholder()
56 | }
57 | }
58 |
59 | private let borderThickness: CGFloat = 1
60 | private let placeholderInsets = CGPoint(x: 6, y: 6)
61 | private let textFieldInsets = CGPoint(x: 6, y: 6)
62 | private let borderLayer = CALayer()
63 | private var backgroundLayerColor: UIColor?
64 |
65 | // MARK: - TextFieldEffects
66 |
67 | override open func drawViewsForRect(_ rect: CGRect) {
68 | let frame = CGRect(origin: CGPoint.zero, size: CGSize(width: rect.size.width, height: rect.size.height))
69 |
70 | placeholderLabel.frame = frame.insetBy(dx: placeholderInsets.x, dy: placeholderInsets.y)
71 | placeholderLabel.font = placeholderFontFromFont(font!)
72 |
73 | updateBorder()
74 | updatePlaceholder()
75 |
76 | layer.insertSublayer(borderLayer, at: 0)
77 | addSubview(placeholderLabel)
78 | }
79 |
80 | override open func animateViewsForTextEntry() {
81 | UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.6, options: .beginFromCurrentState, animations: {
82 |
83 | self.borderLayer.borderColor = self.textColor?.cgColor
84 | self.borderLayer.shadowOffset = CGSize.zero
85 | self.borderLayer.borderWidth = self.borderThickness
86 | self.borderLayer.shadowColor = self.textColor?.cgColor
87 | self.borderLayer.shadowOpacity = 0.5
88 | self.borderLayer.shadowRadius = 1
89 |
90 | }, completion: { _ in
91 | self.animationCompletionHandler?(.textEntry)
92 | })
93 | }
94 |
95 | override open func animateViewsForTextDisplay() {
96 | if text!.isEmpty {
97 | UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.6, options: .beginFromCurrentState, animations: {
98 |
99 | self.borderLayer.borderColor = nil
100 | self.borderLayer.shadowOffset = CGSize.zero
101 | self.borderLayer.borderWidth = 0
102 | self.borderLayer.shadowColor = nil
103 | self.borderLayer.shadowOpacity = 0
104 | self.borderLayer.shadowRadius = 0
105 | }, completion: { _ in
106 |
107 | self.animationCompletionHandler?(.textDisplay)
108 | })
109 |
110 | }
111 | }
112 |
113 | // MARK: - Private
114 |
115 | private func updateBorder() {
116 | borderLayer.frame = rectForBorder(frame)
117 | borderLayer.backgroundColor = backgroundColor?.cgColor
118 | }
119 |
120 | private func updatePlaceholder() {
121 | placeholderLabel.text = placeholder
122 | placeholderLabel.textColor = placeholderColor
123 | placeholderLabel.sizeToFit()
124 | layoutPlaceholderInTextRect()
125 |
126 | if isFirstResponder {
127 | animateViewsForTextEntry()
128 | }
129 | }
130 |
131 | private func placeholderFontFromFont(_ font: UIFont) -> UIFont! {
132 | let smallerFont = UIFont(descriptor: font.fontDescriptor, size: font.pointSize * placeholderFontScale)
133 | return smallerFont
134 | }
135 |
136 | private func rectForBorder(_ bounds: CGRect) -> CGRect {
137 | let newRect = CGRect(x: 0, y: 0, width: bounds.size.width, height: bounds.size.height - font!.lineHeight + textFieldInsets.y)
138 |
139 | return newRect
140 | }
141 |
142 | private func layoutPlaceholderInTextRect() {
143 |
144 | let textRect = self.textRect(forBounds: bounds)
145 | var originX = textRect.origin.x
146 | switch textAlignment {
147 | case .center:
148 | originX += textRect.size.width/2 - placeholderLabel.bounds.width/2
149 | case .right:
150 | originX += textRect.size.width - placeholderLabel.bounds.width
151 | default:
152 | break
153 | }
154 | placeholderLabel.frame = CGRect(x: originX, y: bounds.height - placeholderLabel.frame.height,
155 | width: placeholderLabel.frame.size.width, height: placeholderLabel.frame.size.height)
156 | }
157 |
158 | // MARK: - Overrides
159 |
160 | override open func editingRect(forBounds bounds: CGRect) -> CGRect {
161 | let newBounds = rectForBorder(bounds)
162 | return newBounds.insetBy(dx: textFieldInsets.x, dy: 0)
163 | }
164 |
165 | override open func textRect(forBounds bounds: CGRect) -> CGRect {
166 | let newBounds = rectForBorder(bounds)
167 |
168 | return newBounds.insetBy(dx: textFieldInsets.x, dy: 0)
169 | }
170 |
171 | }
172 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldEffects/JiroTextField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // JiroTextField.swift
3 | // TextFieldEffects
4 | //
5 | // Created by Raúl Riera on 24/01/2015.
6 | // Copyright (c) 2015 Raul Riera. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /**
12 | A JiroTextField is a subclass of the TextFieldEffects object, is a control that displays an UITextField with a customizable visual effect around the background of the control.
13 | */
14 | @IBDesignable open class JiroTextField: TextFieldEffects {
15 | /**
16 | The color of the border.
17 |
18 | This property applies a color to the lower edge of the control. The default value for this property is a clear color.
19 | */
20 | @IBInspectable dynamic open var borderColor: UIColor? {
21 | didSet {
22 | updateBorder()
23 | }
24 | }
25 |
26 | /**
27 | The color of the placeholder text.
28 |
29 | This property applies a color to the complete placeholder string. The default value for this property is a black color.
30 | */
31 | @IBInspectable dynamic open var placeholderColor: UIColor = .black {
32 | didSet {
33 | updatePlaceholder()
34 | }
35 | }
36 |
37 | /**
38 | The scale of the placeholder font.
39 |
40 | This property determines the size of the placeholder label relative to the font size of the text field.
41 | */
42 | @IBInspectable dynamic open var placeholderFontScale: CGFloat = 0.65 {
43 | didSet {
44 | updatePlaceholder()
45 | }
46 | }
47 |
48 | override open var placeholder: String? {
49 | didSet {
50 | updatePlaceholder()
51 | }
52 | }
53 |
54 | override open var bounds: CGRect {
55 | didSet {
56 | updateBorder()
57 | updatePlaceholder()
58 | }
59 | }
60 |
61 | private let borderThickness: CGFloat = 2
62 | private let placeholderInsets = CGPoint(x: 8, y: 8)
63 | private let textFieldInsets = CGPoint(x: 8, y: 12)
64 | private let borderLayer = CALayer()
65 |
66 | // MARK: - TextFieldEffects
67 |
68 | override open func drawViewsForRect(_ rect: CGRect) {
69 | let frame = CGRect(origin: CGPoint.zero, size: CGSize(width: rect.size.width, height: rect.size.height))
70 |
71 | placeholderLabel.frame = frame.insetBy(dx: placeholderInsets.x, dy: placeholderInsets.y)
72 | placeholderLabel.font = placeholderFontFromFont(font!)
73 |
74 | updateBorder()
75 | updatePlaceholder()
76 |
77 | layer.insertSublayer(borderLayer, at: 0)
78 | addSubview(placeholderLabel)
79 | }
80 |
81 | override open func animateViewsForTextEntry() {
82 | borderLayer.frame.origin = CGPoint(x: 0, y: font!.lineHeight)
83 |
84 | UIView.animate(withDuration: 0.2, delay: 0.3, usingSpringWithDamping: 0.8, initialSpringVelocity: 1.0, options: .beginFromCurrentState, animations: ({
85 |
86 | self.placeholderLabel.frame.origin = CGPoint(x: self.placeholderInsets.x, y: self.borderLayer.frame.origin.y - self.placeholderLabel.bounds.height)
87 | self.borderLayer.frame = self.rectForBorder(self.borderThickness, isFilled: true)
88 |
89 | }), completion: { _ in
90 | self.animationCompletionHandler?(.textEntry)
91 | })
92 | }
93 |
94 | override open func animateViewsForTextDisplay() {
95 | if text!.isEmpty {
96 | UIView.animate(withDuration: 0.35, delay: 0.0, usingSpringWithDamping: 0.8, initialSpringVelocity: 2.0, options: .beginFromCurrentState, animations: ({
97 | self.layoutPlaceholderInTextRect()
98 | self.placeholderLabel.alpha = 1
99 | }), completion: { _ in
100 | self.animationCompletionHandler?(.textDisplay)
101 | })
102 |
103 | borderLayer.frame = rectForBorder(borderThickness, isFilled: false)
104 | }
105 | }
106 |
107 | // MARK: - Private
108 |
109 | private func updateBorder() {
110 | borderLayer.frame = rectForBorder(borderThickness, isFilled: false)
111 | borderLayer.backgroundColor = borderColor?.cgColor
112 | }
113 |
114 | private func updatePlaceholder() {
115 | placeholderLabel.text = placeholder
116 | placeholderLabel.textColor = placeholderColor
117 | placeholderLabel.sizeToFit()
118 | layoutPlaceholderInTextRect()
119 |
120 | if isFirstResponder || text!.isNotEmpty {
121 | animateViewsForTextEntry()
122 | }
123 | }
124 |
125 | private func placeholderFontFromFont(_ font: UIFont) -> UIFont! {
126 | let smallerFont = UIFont(descriptor: font.fontDescriptor, size: font.pointSize * placeholderFontScale)
127 | return smallerFont
128 | }
129 |
130 | private func rectForBorder(_ thickness: CGFloat, isFilled: Bool) -> CGRect {
131 | if isFilled {
132 | return CGRect(origin: CGPoint(x: 0, y: placeholderLabel.frame.origin.y + placeholderLabel.font.lineHeight), size: CGSize(width: frame.width, height: frame.height))
133 | } else {
134 | return CGRect(origin: CGPoint(x: 0, y: frame.height-thickness), size: CGSize(width: frame.width, height: thickness))
135 | }
136 | }
137 |
138 | private func layoutPlaceholderInTextRect() {
139 |
140 | if text!.isNotEmpty {
141 | return
142 | }
143 |
144 | let textRect = self.textRect(forBounds: bounds)
145 | var originX = textRect.origin.x
146 | switch self.textAlignment {
147 | case .center:
148 | originX += textRect.size.width/2 - placeholderLabel.bounds.width/2
149 | case .right:
150 | originX += textRect.size.width - placeholderLabel.bounds.width
151 | default:
152 | break
153 | }
154 | placeholderLabel.frame = CGRect(x: originX, y: textRect.size.height/2,
155 | width: placeholderLabel.frame.size.width, height: placeholderLabel.frame.size.height)
156 | }
157 |
158 | // MARK: - Overrides
159 |
160 | override open func editingRect(forBounds bounds: CGRect) -> CGRect {
161 | return bounds.offsetBy(dx: textFieldInsets.x, dy: textFieldInsets.y)
162 | }
163 |
164 | override open func textRect(forBounds bounds: CGRect) -> CGRect {
165 | return bounds.offsetBy(dx: textFieldInsets.x, dy: textFieldInsets.y)
166 | }
167 |
168 | }
169 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldEffects/IsaoTextField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // IsaoTextField.swift
3 | // TextFieldEffects
4 | //
5 | // Created by Raúl Riera on 29/01/2015.
6 | // Copyright (c) 2015 Raul Riera. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /**
12 | An IsaoTextField is a subclass of the TextFieldEffects object, is a control that displays an UITextField with a customizable visual effect around the lower edge of the control.
13 | */
14 | @IBDesignable open class IsaoTextField: TextFieldEffects {
15 | /**
16 | The color of the border when it has no content.
17 |
18 | This property applies a color to the lower edge of the control. The default value for this property is a clear color. This value is also applied to the placeholder color.
19 | */
20 | @IBInspectable dynamic open var inactiveColor: UIColor? {
21 | didSet {
22 | updateBorder()
23 | }
24 | }
25 |
26 | /**
27 | The color of the border when it has content.
28 |
29 | This property applies a color to the lower edge of the control. The default value for this property is a clear color.
30 | */
31 | @IBInspectable dynamic open var activeColor: UIColor? {
32 | didSet {
33 | updateBorder()
34 | }
35 | }
36 |
37 | /**
38 | The scale of the placeholder font.
39 |
40 | This property determines the size of the placeholder label relative to the font size of the text field.
41 | */
42 | @IBInspectable dynamic open var placeholderFontScale: CGFloat = 0.7 {
43 | didSet {
44 | updatePlaceholder()
45 | }
46 | }
47 |
48 | override open var placeholder: String? {
49 | didSet {
50 | updatePlaceholder()
51 | }
52 | }
53 |
54 | override open var bounds: CGRect {
55 | didSet {
56 | updateBorder()
57 | updatePlaceholder()
58 | }
59 | }
60 |
61 | private let borderThickness: (active: CGFloat, inactive: CGFloat) = (4, 2)
62 | private let placeholderInsets = CGPoint(x: 6, y: 6)
63 | private let textFieldInsets = CGPoint(x: 6, y: 6)
64 | private let borderLayer = CALayer()
65 |
66 | // MARK: - TextFieldEffects
67 |
68 | override open func drawViewsForRect(_ rect: CGRect) {
69 | let frame = CGRect(origin: .zero, size: CGSize(width: rect.size.width, height: rect.size.height))
70 |
71 | placeholderLabel.frame = frame.insetBy(dx: placeholderInsets.x, dy: placeholderInsets.y)
72 | placeholderLabel.font = placeholderFontFromFont(font!)
73 |
74 | updateBorder()
75 | updatePlaceholder()
76 |
77 | layer.addSublayer(borderLayer)
78 | addSubview(placeholderLabel)
79 | }
80 |
81 | override open func animateViewsForTextEntry() {
82 | updateBorder()
83 | if let activeColor = activeColor {
84 | performPlaceholderAnimationWithColor(activeColor)
85 | }
86 | }
87 |
88 | override open func animateViewsForTextDisplay() {
89 | updateBorder()
90 | if let inactiveColor = inactiveColor {
91 | performPlaceholderAnimationWithColor(inactiveColor)
92 | }
93 | }
94 |
95 | // MARK: - Private
96 |
97 | private func updateBorder() {
98 | borderLayer.frame = rectForBorder(frame)
99 | borderLayer.backgroundColor = isFirstResponder ? activeColor?.cgColor : inactiveColor?.cgColor
100 | }
101 |
102 | private func updatePlaceholder() {
103 | placeholderLabel.text = placeholder
104 | placeholderLabel.textColor = inactiveColor
105 | placeholderLabel.sizeToFit()
106 | layoutPlaceholderInTextRect()
107 |
108 | if isFirstResponder {
109 | animateViewsForTextEntry()
110 | }
111 | }
112 |
113 | private func placeholderFontFromFont(_ font: UIFont) -> UIFont! {
114 | let smallerFont = UIFont(descriptor: font.fontDescriptor, size: font.pointSize * placeholderFontScale)
115 | return smallerFont
116 | }
117 |
118 | private func rectForBorder(_ bounds: CGRect) -> CGRect {
119 | var newRect:CGRect
120 |
121 | if isFirstResponder {
122 | newRect = CGRect(x: 0, y: bounds.size.height - font!.lineHeight + textFieldInsets.y - borderThickness.active, width: bounds.size.width, height: borderThickness.active)
123 | } else {
124 | newRect = CGRect(x: 0, y: bounds.size.height - font!.lineHeight + textFieldInsets.y - borderThickness.inactive, width: bounds.size.width, height: borderThickness.inactive)
125 | }
126 |
127 | return newRect
128 | }
129 |
130 | private func layoutPlaceholderInTextRect() {
131 | let textRect = self.textRect(forBounds: bounds)
132 | var originX = textRect.origin.x
133 | switch textAlignment {
134 | case .center:
135 | originX += textRect.size.width/2 - placeholderLabel.bounds.width/2
136 | case .right:
137 | originX += textRect.size.width - placeholderLabel.bounds.width
138 | default:
139 | break
140 | }
141 | placeholderLabel.frame = CGRect(x: originX, y: bounds.height - placeholderLabel.frame.height,
142 | width: placeholderLabel.frame.size.width, height: placeholderLabel.frame.size.height)
143 | }
144 |
145 | private func performPlaceholderAnimationWithColor(_ color: UIColor) {
146 | let yOffset: CGFloat = 4
147 |
148 | UIView.animate(withDuration: 0.15, animations: {
149 | self.placeholderLabel.transform = CGAffineTransform(translationX: 0, y: -yOffset)
150 | self.placeholderLabel.alpha = 0
151 | }) { _ in
152 | self.placeholderLabel.transform = .identity
153 | self.placeholderLabel.transform = CGAffineTransform(translationX: 0, y: yOffset)
154 |
155 | UIView.animate(withDuration: 0.15, animations: {
156 | self.placeholderLabel.textColor = color
157 | self.placeholderLabel.transform = .identity
158 | self.placeholderLabel.alpha = 1
159 | }) { _ in
160 | self.animationCompletionHandler?(self.isFirstResponder ? .textEntry : .textDisplay)
161 | }
162 | }
163 | }
164 |
165 | // MARK: - Overrides
166 |
167 | override open func editingRect(forBounds bounds: CGRect) -> CGRect {
168 | let newBounds = CGRect(x: 0, y: 0, width: bounds.size.width, height: bounds.size.height - font!.lineHeight + textFieldInsets.y)
169 | return newBounds.insetBy(dx: textFieldInsets.x, dy: 0)
170 | }
171 |
172 | override open func textRect(forBounds bounds: CGRect) -> CGRect {
173 | let newBounds = CGRect(x: 0, y: 0, width: bounds.size.width, height: bounds.size.height - font!.lineHeight + textFieldInsets.y)
174 |
175 | return newBounds.insetBy(dx: textFieldInsets.x, dy: 0)
176 | }
177 |
178 | }
179 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldEffects/MadokaTextField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MadokaTextField.swift
3 | // TextFieldEffects
4 | //
5 | // Created by Raúl Riera on 05/02/2015.
6 | // Copyright (c) 2015 Raul Riera. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /**
12 | A MadokaTextField is a subclass of the TextFieldEffects object, is a control that displays an UITextField with a customizable visual effect around the edges of the control.
13 | */
14 | @IBDesignable open class MadokaTextField: TextFieldEffects {
15 | /**
16 | The color of the placeholder text.
17 |
18 | This property applies a color to the complete placeholder string. The default value for this property is a black color.
19 | */
20 | @IBInspectable dynamic open var placeholderColor: UIColor = .black {
21 | didSet {
22 | updatePlaceholder()
23 | }
24 | }
25 |
26 | /**
27 | The color of the border.
28 |
29 | This property applies a color to the lower edge of the control. The default value for this property is a clear color.
30 | */
31 | @IBInspectable dynamic open var borderColor: UIColor? {
32 | didSet {
33 | updateBorder()
34 | }
35 | }
36 |
37 | /**
38 | The scale of the placeholder font.
39 |
40 | This property determines the size of the placeholder label relative to the font size of the text field.
41 | */
42 | @IBInspectable dynamic open var placeholderFontScale: CGFloat = 0.65 {
43 | didSet {
44 | updatePlaceholder()
45 | }
46 | }
47 |
48 | override open var placeholder: String? {
49 | didSet {
50 | updatePlaceholder()
51 | }
52 | }
53 |
54 | override open var bounds: CGRect {
55 | didSet {
56 | updateBorder()
57 | updatePlaceholder()
58 | }
59 | }
60 |
61 | private let borderThickness: CGFloat = 1
62 | private let placeholderInsets = CGPoint(x: 6, y: 6)
63 | private let textFieldInsets = CGPoint(x: 6, y: 6)
64 | private let borderLayer = CAShapeLayer()
65 | private var backgroundLayerColor: UIColor?
66 |
67 | // MARK: - TextFieldEffects
68 |
69 | override open func drawViewsForRect(_ rect: CGRect) {
70 | let frame = CGRect(origin: CGPoint.zero, size: CGSize(width: rect.size.width, height: rect.size.height))
71 |
72 | placeholderLabel.frame = frame.insetBy(dx: placeholderInsets.x, dy: placeholderInsets.y)
73 | placeholderLabel.font = placeholderFontFromFont(font!)
74 |
75 | updateBorder()
76 | updatePlaceholder()
77 |
78 | layer.addSublayer(borderLayer)
79 | addSubview(placeholderLabel)
80 | }
81 |
82 | override open func animateViewsForTextEntry() {
83 | borderLayer.strokeEnd = 1
84 |
85 | UIView.animate(withDuration: 0.3, animations: {
86 | let translate = CGAffineTransform(translationX: -self.placeholderInsets.x, y: self.placeholderLabel.bounds.height + (self.placeholderInsets.y * 2))
87 | let scale = CGAffineTransform(scaleX: 0.9, y: 0.9)
88 |
89 | self.placeholderLabel.transform = translate.concatenating(scale)
90 | }) { _ in
91 | self.animationCompletionHandler?(.textEntry)
92 | }
93 | }
94 |
95 | override open func animateViewsForTextDisplay() {
96 | if text!.isEmpty {
97 | borderLayer.strokeEnd = percentageForBottomBorder()
98 |
99 | UIView.animate(withDuration: 0.3, animations: {
100 | self.placeholderLabel.transform = .identity
101 | }) { _ in
102 | self.animationCompletionHandler?(.textDisplay)
103 | }
104 | }
105 | }
106 |
107 | // MARK: - Private
108 |
109 | private func updateBorder() {
110 | let rect = rectForBorder(bounds)
111 | let path = UIBezierPath()
112 | path.move(to: CGPoint(x: rect.origin.x + borderThickness, y: rect.height - borderThickness))
113 | path.addLine(to: CGPoint(x: rect.width - borderThickness, y: rect.height - borderThickness))
114 | path.addLine(to: CGPoint(x: rect.width - borderThickness, y: rect.origin.y + borderThickness))
115 | path.addLine(to: CGPoint(x: rect.origin.x + borderThickness, y: rect.origin.y + borderThickness))
116 | path.close()
117 | borderLayer.path = path.cgPath
118 | borderLayer.lineCap = .square
119 | borderLayer.lineWidth = borderThickness
120 | borderLayer.fillColor = nil
121 | borderLayer.strokeColor = borderColor?.cgColor
122 | borderLayer.strokeEnd = percentageForBottomBorder()
123 | }
124 |
125 | private func percentageForBottomBorder() -> CGFloat {
126 | let borderRect = rectForBorder(bounds)
127 | let sumOfSides = (borderRect.width * 2) + (borderRect.height * 2)
128 | return (borderRect.width * 100 / sumOfSides) / 100
129 | }
130 |
131 | private func updatePlaceholder() {
132 | placeholderLabel.text = placeholder
133 | placeholderLabel.textColor = placeholderColor
134 | placeholderLabel.sizeToFit()
135 | layoutPlaceholderInTextRect()
136 |
137 | if isFirstResponder || text!.isNotEmpty {
138 | animateViewsForTextEntry()
139 | }
140 | }
141 |
142 | private func placeholderFontFromFont(_ font: UIFont) -> UIFont! {
143 | let smallerFont = UIFont(descriptor: font.fontDescriptor, size: font.pointSize * placeholderFontScale)
144 | return smallerFont
145 | }
146 |
147 | private func rectForBorder(_ bounds: CGRect) -> CGRect {
148 | let newRect = CGRect(x: 0, y: 0, width: bounds.size.width, height: bounds.size.height - font!.lineHeight + textFieldInsets.y)
149 |
150 | return newRect
151 | }
152 |
153 | private func layoutPlaceholderInTextRect() {
154 | placeholderLabel.transform = CGAffineTransform.identity
155 |
156 | let textRect = self.textRect(forBounds: bounds)
157 | var originX = textRect.origin.x
158 | switch textAlignment {
159 | case .center:
160 | originX += textRect.size.width/2 - placeholderLabel.bounds.width/2
161 | case .right:
162 | originX += textRect.size.width - placeholderLabel.bounds.width
163 | default:
164 | break
165 | }
166 |
167 | placeholderLabel.frame = CGRect(x: originX, y: textRect.height - placeholderLabel.bounds.height - placeholderInsets.y,
168 | width: placeholderLabel.bounds.width, height: placeholderLabel.bounds.height)
169 | }
170 |
171 | // MARK: - Overrides
172 |
173 | override open func editingRect(forBounds bounds: CGRect) -> CGRect {
174 | let newBounds = rectForBorder(bounds)
175 | return newBounds.insetBy(dx: textFieldInsets.x, dy: 0)
176 | }
177 |
178 | override open func textRect(forBounds bounds: CGRect) -> CGRect {
179 | let newBounds = rectForBorder(bounds)
180 | return newBounds.insetBy(dx: textFieldInsets.x, dy: 0)
181 | }
182 |
183 | }
184 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldEffects/HoshiTextField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HoshiTextField.swift
3 | // TextFieldEffects
4 | //
5 | // Created by Raúl Riera on 24/01/2015.
6 | // Copyright (c) 2015 Raul Riera. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /**
12 | An HoshiTextField is a subclass of the TextFieldEffects object, is a control that displays an UITextField with a customizable visual effect around the lower edge of the control.
13 | */
14 | @IBDesignable open class HoshiTextField: TextFieldEffects {
15 | /**
16 | The color of the border when it has no content.
17 |
18 | This property applies a color to the lower edge of the control. The default value for this property is a clear color.
19 | */
20 | @IBInspectable dynamic open var borderInactiveColor: UIColor? {
21 | didSet {
22 | updateBorder()
23 | }
24 | }
25 |
26 | /**
27 | The color of the border when it has content.
28 |
29 | This property applies a color to the lower edge of the control. The default value for this property is a clear color.
30 | */
31 | @IBInspectable dynamic open var borderActiveColor: UIColor? {
32 | didSet {
33 | updateBorder()
34 | }
35 | }
36 |
37 | /**
38 | The color of the placeholder text.
39 |
40 | This property applies a color to the complete placeholder string. The default value for this property is a black color.
41 | */
42 | @IBInspectable dynamic open var placeholderColor: UIColor = .black {
43 | didSet {
44 | updatePlaceholder()
45 | }
46 | }
47 |
48 | /**
49 | The scale of the placeholder font.
50 |
51 | This property determines the size of the placeholder label relative to the font size of the text field.
52 | */
53 | @IBInspectable dynamic open var placeholderFontScale: CGFloat = 0.65 {
54 | didSet {
55 | updatePlaceholder()
56 | }
57 | }
58 |
59 | override open var placeholder: String? {
60 | didSet {
61 | updatePlaceholder()
62 | }
63 | }
64 |
65 | override open var bounds: CGRect {
66 | didSet {
67 | updateBorder()
68 | updatePlaceholder()
69 | }
70 | }
71 |
72 | private let borderThickness: (active: CGFloat, inactive: CGFloat) = (active: 2, inactive: 0.5)
73 | private let placeholderInsets = CGPoint(x: 0, y: 6)
74 | private let textFieldInsets = CGPoint(x: 0, y: 12)
75 | private let inactiveBorderLayer = CALayer()
76 | private let activeBorderLayer = CALayer()
77 | private var activePlaceholderPoint: CGPoint = CGPoint.zero
78 |
79 | // MARK: - TextFieldEffects
80 |
81 | override open func drawViewsForRect(_ rect: CGRect) {
82 | let frame = CGRect(origin: CGPoint.zero, size: CGSize(width: rect.size.width, height: rect.size.height))
83 |
84 | placeholderLabel.frame = frame.insetBy(dx: placeholderInsets.x, dy: placeholderInsets.y)
85 | placeholderLabel.font = placeholderFontFromFont(font!)
86 |
87 | updateBorder()
88 | updatePlaceholder()
89 |
90 | layer.addSublayer(inactiveBorderLayer)
91 | layer.addSublayer(activeBorderLayer)
92 | addSubview(placeholderLabel)
93 | }
94 |
95 | override open func animateViewsForTextEntry() {
96 | if text!.isEmpty {
97 | UIView.animate(withDuration: 0.3, delay: 0.0, usingSpringWithDamping: 0.8, initialSpringVelocity: 1.0, options: .beginFromCurrentState, animations: ({
98 | self.placeholderLabel.frame.origin = CGPoint(x: 10, y: self.placeholderLabel.frame.origin.y)
99 | self.placeholderLabel.alpha = 0
100 | }), completion: { _ in
101 | self.animationCompletionHandler?(.textEntry)
102 | })
103 | }
104 |
105 | layoutPlaceholderInTextRect()
106 | placeholderLabel.frame.origin = activePlaceholderPoint
107 |
108 | UIView.animate(withDuration: 0.4, animations: {
109 | self.placeholderLabel.alpha = 1.0
110 | })
111 |
112 | activeBorderLayer.frame = rectForBorder(borderThickness.active, isFilled: true)
113 | }
114 |
115 | override open func animateViewsForTextDisplay() {
116 | if let text = text, text.isEmpty {
117 | UIView.animate(withDuration: 0.35, delay: 0.0, usingSpringWithDamping: 0.8, initialSpringVelocity: 2.0, options: .beginFromCurrentState, animations: ({
118 | self.layoutPlaceholderInTextRect()
119 | self.placeholderLabel.alpha = 1
120 | }), completion: { _ in
121 | self.animationCompletionHandler?(.textDisplay)
122 | })
123 |
124 | activeBorderLayer.frame = self.rectForBorder(self.borderThickness.active, isFilled: false)
125 | inactiveBorderLayer.frame = self.rectForBorder(self.borderThickness.inactive, isFilled: true)
126 |
127 | }
128 | }
129 |
130 | // MARK: - Private
131 |
132 | private func updateBorder() {
133 | inactiveBorderLayer.frame = rectForBorder(borderThickness.inactive, isFilled: !isFirstResponder)
134 | inactiveBorderLayer.backgroundColor = borderInactiveColor?.cgColor
135 |
136 | activeBorderLayer.frame = rectForBorder(borderThickness.active, isFilled: isFirstResponder)
137 | activeBorderLayer.backgroundColor = borderActiveColor?.cgColor
138 | }
139 |
140 | private func updatePlaceholder() {
141 | placeholderLabel.text = placeholder
142 | placeholderLabel.textColor = placeholderColor
143 | placeholderLabel.sizeToFit()
144 | layoutPlaceholderInTextRect()
145 |
146 | if isFirstResponder || text!.isNotEmpty {
147 | animateViewsForTextEntry()
148 | }
149 | }
150 |
151 | private func placeholderFontFromFont(_ font: UIFont) -> UIFont! {
152 | let smallerFont = UIFont(descriptor: font.fontDescriptor, size: font.pointSize * placeholderFontScale)
153 | return smallerFont
154 | }
155 |
156 | private func rectForBorder(_ thickness: CGFloat, isFilled: Bool) -> CGRect {
157 | if isFilled {
158 | return CGRect(origin: CGPoint(x: 0, y: frame.height-thickness), size: CGSize(width: frame.width, height: thickness))
159 | } else {
160 | return CGRect(origin: CGPoint(x: 0, y: frame.height-thickness), size: CGSize(width: 0, height: thickness))
161 | }
162 | }
163 |
164 | private func layoutPlaceholderInTextRect() {
165 | let textRect = self.textRect(forBounds: bounds)
166 | var originX = textRect.origin.x
167 | switch self.textAlignment {
168 | case .center:
169 | originX += textRect.size.width/2 - placeholderLabel.bounds.width/2
170 | case .right:
171 | originX += textRect.size.width - placeholderLabel.bounds.width
172 | default:
173 | break
174 | }
175 | placeholderLabel.frame = CGRect(x: originX, y: textRect.height/2,
176 | width: placeholderLabel.bounds.width, height: placeholderLabel.bounds.height)
177 | activePlaceholderPoint = CGPoint(x: placeholderLabel.frame.origin.x, y: placeholderLabel.frame.origin.y - placeholderLabel.frame.size.height - placeholderInsets.y)
178 |
179 | }
180 |
181 | // MARK: - Overrides
182 |
183 | override open func editingRect(forBounds bounds: CGRect) -> CGRect {
184 | return bounds.offsetBy(dx: textFieldInsets.x, dy: textFieldInsets.y)
185 | }
186 |
187 | override open func textRect(forBounds bounds: CGRect) -> CGRect {
188 | return bounds.offsetBy(dx: textFieldInsets.x, dy: textFieldInsets.y)
189 | }
190 |
191 | }
192 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldEffects/YoshikoTextField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // YoshikoTextField.swift
3 | // TextFieldEffects
4 | //
5 | // Created by Keenan Cassidy on 01/10/2015.
6 | // Copyright © 2015 Raul Riera. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /**
12 | An YoshikoTextField is a subclass of the TextFieldEffects object, is a control that displays an UITextField with a customizable visual effect around the edges and background of the control.
13 | */
14 | @IBDesignable open class YoshikoTextField: TextFieldEffects {
15 | private let borderLayer = CALayer()
16 | private let textFieldInsets = CGPoint(x: 6, y: 0)
17 | private let placeHolderInsets = CGPoint(x: 6, y: 0)
18 |
19 | /**
20 | The size of the border.
21 |
22 | This property applies a thickness to the border of the control. The default value for this property is 2 points.
23 | */
24 | @IBInspectable open var borderSize: CGFloat = 2.0 {
25 | didSet {
26 | updateBorder()
27 | }
28 | }
29 |
30 | /**
31 | The color of the border when it has content.
32 |
33 | This property applies a color to the edges of the control. The default value for this property is a clear color.
34 | */
35 | @IBInspectable dynamic open var activeBorderColor: UIColor = .clear {
36 | didSet {
37 | updateBorder()
38 | updateBackground()
39 | updatePlaceholder()
40 | }
41 | }
42 |
43 | /**
44 | The color of the border when it has no content.
45 |
46 | This property applies a color to the edges of the control. The default value for this property is a clear color.
47 | */
48 | @IBInspectable dynamic open var inactiveBorderColor: UIColor = .clear {
49 | didSet {
50 | updateBorder()
51 | updateBackground()
52 | updatePlaceholder()
53 | }
54 | }
55 |
56 | /**
57 | The color of the input's background when it has content. When it's not focused it reverts to the color of the `inactiveBorderColor`
58 |
59 | This property applies a color to the background of the input.
60 | */
61 | @IBInspectable dynamic open var activeBackgroundColor: UIColor = .clear {
62 | didSet {
63 | updateBackground()
64 | }
65 | }
66 |
67 | /**
68 | The color of the placeholder text.
69 |
70 | This property applies a color to the complete placeholder string. The default value for this property is a dark gray color.
71 | */
72 | @IBInspectable dynamic open var placeholderColor: UIColor = .darkGray {
73 | didSet {
74 | updatePlaceholder()
75 | }
76 | }
77 |
78 | /**
79 | The scale of the placeholder font.
80 |
81 | This property determines the size of the placeholder label relative to the font size of the text field.
82 | */
83 | @IBInspectable dynamic open var placeholderFontScale: CGFloat = 0.7 {
84 | didSet {
85 | updatePlaceholder()
86 | }
87 | }
88 |
89 | override open var placeholder: String? {
90 | didSet {
91 | updatePlaceholder()
92 | }
93 | }
94 |
95 | // MARK: Private
96 |
97 | private func updateBorder() {
98 | borderLayer.frame = rectForBounds(bounds)
99 | borderLayer.borderWidth = borderSize
100 | borderLayer.borderColor = (isFirstResponder || text!.isNotEmpty) ? activeBorderColor.cgColor : inactiveBorderColor.cgColor
101 | }
102 |
103 | private func updateBackground() {
104 | if isFirstResponder || text!.isNotEmpty {
105 | borderLayer.backgroundColor = activeBackgroundColor.cgColor
106 | } else {
107 | borderLayer.backgroundColor = inactiveBorderColor.cgColor
108 | }
109 | }
110 |
111 | private func updatePlaceholder() {
112 | placeholderLabel.frame = placeholderRect(forBounds: bounds)
113 | placeholderLabel.text = placeholder
114 | placeholderLabel.textAlignment = textAlignment
115 |
116 | if isFirstResponder || text!.isNotEmpty {
117 | placeholderLabel.font = placeholderFontFromFontAndPercentageOfOriginalSize(font: font!, percentageOfOriginalSize: placeholderFontScale * 0.8)
118 | placeholderLabel.text = placeholder?.uppercased()
119 | placeholderLabel.textColor = activeBorderColor
120 | } else {
121 | placeholderLabel.font = placeholderFontFromFontAndPercentageOfOriginalSize(font: font!, percentageOfOriginalSize: placeholderFontScale)
122 | placeholderLabel.textColor = placeholderColor
123 | }
124 | }
125 |
126 |
127 | private func placeholderFontFromFontAndPercentageOfOriginalSize(font: UIFont, percentageOfOriginalSize: CGFloat) -> UIFont! {
128 | let smallerFont = UIFont(descriptor: font.fontDescriptor, size: font.pointSize * placeholderFontScale)
129 | return smallerFont
130 | }
131 |
132 | private func rectForBounds(_ bounds: CGRect) -> CGRect {
133 | return CGRect(x: bounds.origin.x, y: bounds.origin.y + placeholderHeight, width: bounds.size.width, height: bounds.size.height - placeholderHeight)
134 | }
135 |
136 | private var placeholderHeight : CGFloat {
137 | return placeHolderInsets.y + placeholderFontFromFontAndPercentageOfOriginalSize(font: font!, percentageOfOriginalSize: placeholderFontScale).lineHeight
138 | }
139 |
140 | private func animateViews() {
141 | UIView.animate(withDuration: 0.2, animations: {
142 | // Prevents a "flash" in the placeholder
143 | if self.text!.isEmpty {
144 | self.placeholderLabel.alpha = 0
145 | }
146 |
147 | self.placeholderLabel.frame = self.placeholderRect(forBounds: self.bounds)
148 |
149 | }) { _ in
150 | self.updatePlaceholder()
151 |
152 | UIView.animate(withDuration: 0.3, animations: {
153 | self.placeholderLabel.alpha = 1
154 | self.updateBorder()
155 | self.updateBackground()
156 | }, completion: { _ in
157 | self.animationCompletionHandler?(self.isFirstResponder ? .textEntry : .textDisplay)
158 | })
159 | }
160 | }
161 |
162 | // MARK: - TextFieldEffects
163 |
164 | override open func animateViewsForTextEntry() {
165 | animateViews()
166 | }
167 |
168 | override open func animateViewsForTextDisplay() {
169 | animateViews()
170 | }
171 |
172 | // MARK: - Overrides
173 |
174 | override open var bounds: CGRect {
175 | didSet {
176 | updatePlaceholder()
177 | updateBorder()
178 | updateBackground()
179 | }
180 | }
181 |
182 | override open func drawViewsForRect(_ rect: CGRect) {
183 | updatePlaceholder()
184 | updateBorder()
185 | updateBackground()
186 |
187 | layer.insertSublayer(borderLayer, at: 0)
188 | addSubview(placeholderLabel)
189 | }
190 |
191 | open override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
192 | if isFirstResponder || text!.isNotEmpty {
193 | return CGRect(x: placeHolderInsets.x, y: placeHolderInsets.y, width: bounds.width, height: placeholderHeight)
194 | } else {
195 | return textRect(forBounds: bounds)
196 | }
197 | }
198 |
199 | open override func editingRect(forBounds bounds: CGRect) -> CGRect {
200 | return textRect(forBounds: bounds)
201 | }
202 |
203 | override open func textRect(forBounds bounds: CGRect) -> CGRect {
204 | return CGRect(x: textFieldInsets.x,
205 | y: placeholderHeight,
206 | width: bounds.width - (textFieldInsets.x * 2),
207 | height: bounds.height - placeholderHeight)
208 | }
209 |
210 | // MARK: - Interface Builder
211 |
212 | open override func prepareForInterfaceBuilder() {
213 | placeholderLabel.alpha = 1
214 | }
215 |
216 | }
217 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldEffects/YokoTextField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // YokoTextField.swift
3 | // TextFieldEffects
4 | //
5 | // Created by Raúl Riera on 30/01/2015.
6 | // Copyright (c) 2015 Raul Riera. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /**
12 | A YokoTextField is a subclass of the TextFieldEffects object, is a control that displays an UITextField with a customizable 3D visual effect on the background of the control.
13 | */
14 | @IBDesignable open class YokoTextField: TextFieldEffects {
15 | /**
16 | The color of the placeholder text.
17 |
18 | This property applies a color to the complete placeholder string. The default value for this property is a black color.
19 | */
20 | @IBInspectable dynamic open var placeholderColor: UIColor? {
21 | didSet {
22 | updatePlaceholder()
23 | }
24 | }
25 |
26 | /**
27 | The scale of the placeholder font.
28 |
29 | This property determines the size of the placeholder label relative to the font size of the text field.
30 | */
31 | @IBInspectable dynamic open var placeholderFontScale: CGFloat = 0.7 {
32 | didSet {
33 | updatePlaceholder()
34 | }
35 | }
36 |
37 | /**
38 | The view’s foreground color.
39 |
40 | The default value for this property is a clear color.
41 | */
42 | @IBInspectable dynamic open var foregroundColor: UIColor = .black {
43 | didSet {
44 | updateForeground()
45 | }
46 | }
47 |
48 | override open var placeholder: String? {
49 | didSet {
50 | updatePlaceholder()
51 | }
52 | }
53 |
54 | override open var bounds: CGRect {
55 | didSet {
56 | updateForeground()
57 | updatePlaceholder()
58 | }
59 | }
60 |
61 | private let foregroundView = UIView()
62 | private let foregroundLayer = CALayer()
63 | private let borderThickness: CGFloat = 3
64 | private let placeholderInsets = CGPoint(x: 6, y: 6)
65 | private let textFieldInsets = CGPoint(x: 6, y: 6)
66 |
67 | // MARK: - TextFieldEffects
68 |
69 | override open func drawViewsForRect(_ rect: CGRect) {
70 | updateForeground()
71 | updatePlaceholder()
72 |
73 | insertSubview(foregroundView, at: 0)
74 | addSubview(placeholderLabel)
75 | layer.insertSublayer(foregroundLayer, at: 0)
76 | }
77 |
78 | override open func animateViewsForTextEntry() {
79 | UIView.animate(withDuration: 0.4, delay: 0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.6, options: .beginFromCurrentState, animations: {
80 |
81 | self.foregroundView.layer.transform = CATransform3DIdentity
82 |
83 | }, completion: { _ in
84 | self.animationCompletionHandler?(.textEntry)
85 | })
86 |
87 | foregroundLayer.frame = rectForBorder(foregroundView.frame, isFilled: false)
88 | }
89 |
90 | override open func animateViewsForTextDisplay() {
91 | if text!.isEmpty {
92 | UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.6, options: .beginFromCurrentState, animations: {
93 |
94 | self.foregroundLayer.frame = self.rectForBorder(self.foregroundView.frame, isFilled: true)
95 | self.foregroundView.layer.transform = self.rotationAndPerspectiveTransformForView(self.foregroundView)
96 | }, completion: { _ in
97 | self.animationCompletionHandler?(.textDisplay)
98 | })
99 | }
100 | }
101 |
102 | // MARK: - Private
103 |
104 | private func updateForeground() {
105 | foregroundView.frame = rectForForeground(frame)
106 | foregroundView.isUserInteractionEnabled = false
107 | foregroundView.layer.transform = rotationAndPerspectiveTransformForView(foregroundView)
108 | foregroundView.backgroundColor = foregroundColor
109 |
110 | foregroundLayer.borderWidth = borderThickness
111 | foregroundLayer.borderColor = colorWithBrightnessFactor(foregroundColor, factor: 0.8).cgColor
112 | foregroundLayer.frame = rectForBorder(foregroundView.frame, isFilled: true)
113 | }
114 |
115 | private func updatePlaceholder() {
116 | placeholderLabel.font = placeholderFontFromFont(font!)
117 | placeholderLabel.text = placeholder
118 | placeholderLabel.textColor = placeholderColor
119 | placeholderLabel.sizeToFit()
120 | layoutPlaceholderInTextRect()
121 |
122 | if isFirstResponder || text!.isNotEmpty {
123 | animateViewsForTextEntry()
124 | }
125 | }
126 |
127 | private func placeholderFontFromFont(_ font: UIFont) -> UIFont! {
128 | let smallerFont = UIFont(descriptor: font.fontDescriptor, size: font.pointSize * placeholderFontScale)
129 | return smallerFont
130 | }
131 |
132 | private func rectForForeground(_ bounds: CGRect) -> CGRect {
133 | let newRect = CGRect(x: 0, y: 0, width: bounds.size.width, height: bounds.size.height - font!.lineHeight + textFieldInsets.y - borderThickness)
134 |
135 | return newRect
136 | }
137 |
138 | private func rectForBorder(_ bounds: CGRect, isFilled: Bool) -> CGRect {
139 | var newRect = CGRect(x: 0, y: bounds.size.height, width: bounds.size.width, height: isFilled ? borderThickness : 0)
140 |
141 | if !CATransform3DIsIdentity(foregroundView.layer.transform) {
142 | newRect.origin = CGPoint(x: 0, y: bounds.origin.y)
143 | }
144 |
145 | return newRect
146 | }
147 |
148 | private func layoutPlaceholderInTextRect() {
149 | let textRect = self.textRect(forBounds: bounds)
150 | var originX = textRect.origin.x
151 | switch textAlignment {
152 | case .center:
153 | originX += textRect.size.width/2 - placeholderLabel.bounds.width/2
154 | case .right:
155 | originX += textRect.size.width - placeholderLabel.bounds.width
156 | default:
157 | break
158 | }
159 | placeholderLabel.frame = CGRect(x: originX, y: bounds.height - placeholderLabel.frame.height,
160 | width: placeholderLabel.frame.size.width, height: placeholderLabel.frame.size.height)
161 | }
162 |
163 | // MARK: -
164 |
165 | private func setAnchorPoint(_ anchorPoint:CGPoint, forView view:UIView) {
166 | var newPoint:CGPoint = CGPoint(x: view.bounds.size.width * anchorPoint.x, y: view.bounds.size.height * anchorPoint.y)
167 | var oldPoint:CGPoint = CGPoint(x: view.bounds.size.width * view.layer.anchorPoint.x, y: view.bounds.size.height * view.layer.anchorPoint.y)
168 |
169 | newPoint = newPoint.applying(view.transform)
170 | oldPoint = oldPoint.applying(view.transform)
171 |
172 | var position = view.layer.position
173 |
174 | position.x -= oldPoint.x
175 | position.x += newPoint.x
176 |
177 | position.y -= oldPoint.y
178 | position.y += newPoint.y
179 |
180 | view.layer.position = position
181 | view.layer.anchorPoint = anchorPoint
182 | }
183 |
184 | private func colorWithBrightnessFactor(_ color: UIColor, factor: CGFloat) -> UIColor {
185 | var hue : CGFloat = 0
186 | var saturation : CGFloat = 0
187 | var brightness : CGFloat = 0
188 | var alpha : CGFloat = 0
189 |
190 | if color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) {
191 | return UIColor(hue: hue, saturation: saturation, brightness: brightness * factor, alpha: alpha)
192 | } else {
193 | return color;
194 | }
195 | }
196 |
197 | private func rotationAndPerspectiveTransformForView(_ view: UIView) -> CATransform3D {
198 | setAnchorPoint(CGPoint(x: 0.5, y: 1.0), forView:view)
199 |
200 | var rotationAndPerspectiveTransform = CATransform3DIdentity
201 | rotationAndPerspectiveTransform.m34 = 1.0/800
202 | let radians = ((-90) / 180.0 * CGFloat.pi)
203 | rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, radians, 1.0, 0.0, 0.0)
204 | return rotationAndPerspectiveTransform
205 | }
206 |
207 | // MARK: - Overrides
208 |
209 | override open func editingRect(forBounds bounds: CGRect) -> CGRect {
210 | let newBounds = CGRect(x: 0, y: 0, width: bounds.size.width, height: bounds.size.height - font!.lineHeight + textFieldInsets.y)
211 | return newBounds.insetBy(dx: textFieldInsets.x, dy: 0)
212 | }
213 |
214 | override open func textRect(forBounds bounds: CGRect) -> CGRect {
215 | let newBounds = CGRect(x: 0, y: 0, width: bounds.size.width, height: bounds.size.height - font!.lineHeight + textFieldInsets.y)
216 |
217 | return newBounds.insetBy(dx: textFieldInsets.x, dy: 0)
218 | }
219 |
220 | }
221 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldEffects.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 11E69DA71B27B1A90025D54E /* AkiraTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11E69DA61B27B1A90025D54E /* AkiraTextField.swift */; };
11 | 4C42C7711AB20C97009BE2A0 /* TextFieldEffects.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB3B6CE1AA8DEA7000AFA56 /* TextFieldEffects.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
12 | 4C8036EB1B90A88E00218FAE /* ExampleTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8036EA1B90A88E00218FAE /* ExampleTableViewController.swift */; };
13 | 4C86F6A31E8C0085001FB2B3 /* TextFieldEffects.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C86F6A21E8C0085001FB2B3 /* TextFieldEffects.swift */; };
14 | 4C86F6A41E8C0109001FB2B3 /* TextFieldEffects.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C86F6A21E8C0085001FB2B3 /* TextFieldEffects.swift */; };
15 | 4CB3B6D31AA8DEA7000AFA56 /* TextFieldEffects.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CB3B6D21AA8DEA7000AFA56 /* TextFieldEffects.h */; settings = {ATTRIBUTES = (Public, ); }; };
16 | 4CB3B6EF1AA8DEC3000AFA56 /* HoshiTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB3B6E71AA8DEC3000AFA56 /* HoshiTextField.swift */; };
17 | 4CB3B6F01AA8DEC3000AFA56 /* IsaoTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB3B6E81AA8DEC3000AFA56 /* IsaoTextField.swift */; };
18 | 4CB3B6F11AA8DEC3000AFA56 /* JiroTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB3B6E91AA8DEC3000AFA56 /* JiroTextField.swift */; };
19 | 4CB3B6F21AA8DEC3000AFA56 /* KaedeTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB3B6EA1AA8DEC3000AFA56 /* KaedeTextField.swift */; };
20 | 4CB3B6F31AA8DEC3000AFA56 /* MadokaTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB3B6EB1AA8DEC3000AFA56 /* MadokaTextField.swift */; };
21 | 4CB3B6F41AA8DEC3000AFA56 /* MinoruTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB3B6EC1AA8DEC3000AFA56 /* MinoruTextField.swift */; };
22 | 4CB3B6F61AA8DEC3000AFA56 /* YokoTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB3B6EE1AA8DEC3000AFA56 /* YokoTextField.swift */; };
23 | 4CB3B6F71AA8DED3000AFA56 /* TextFieldEffects.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB3B6CE1AA8DEA7000AFA56 /* TextFieldEffects.framework */; };
24 | 4CBF76721A71AF7700073B6A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CBF76711A71AF7700073B6A /* AppDelegate.swift */; };
25 | 4CBF76771A71AF7700073B6A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4CBF76751A71AF7700073B6A /* Main.storyboard */; };
26 | 4CBF76791A71AF7700073B6A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4CBF76781A71AF7700073B6A /* Images.xcassets */; };
27 | 4CBF767C1A71AF7700073B6A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4CBF767A1A71AF7700073B6A /* LaunchScreen.xib */; };
28 | DF983ABB1BBD1F4100BCC4C7 /* YoshikoTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF983ABA1BBD1F4100BCC4C7 /* YoshikoTextField.swift */; };
29 | /* End PBXBuildFile section */
30 |
31 | /* Begin PBXContainerItemProxy section */
32 | 4C42C7721AB20C97009BE2A0 /* PBXContainerItemProxy */ = {
33 | isa = PBXContainerItemProxy;
34 | containerPortal = 4CBF76421A71AE4500073B6A /* Project object */;
35 | proxyType = 1;
36 | remoteGlobalIDString = 4CB3B6CD1AA8DEA7000AFA56;
37 | remoteInfo = TextFieldEffects;
38 | };
39 | /* End PBXContainerItemProxy section */
40 |
41 | /* Begin PBXCopyFilesBuildPhase section */
42 | 4CE3658B1A73CC520021A842 /* Embed Frameworks */ = {
43 | isa = PBXCopyFilesBuildPhase;
44 | buildActionMask = 2147483647;
45 | dstPath = "";
46 | dstSubfolderSpec = 10;
47 | files = (
48 | 4C42C7711AB20C97009BE2A0 /* TextFieldEffects.framework in Embed Frameworks */,
49 | );
50 | name = "Embed Frameworks";
51 | runOnlyForDeploymentPostprocessing = 0;
52 | };
53 | /* End PBXCopyFilesBuildPhase section */
54 |
55 | /* Begin PBXFileReference section */
56 | 11E69DA61B27B1A90025D54E /* AkiraTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AkiraTextField.swift; sourceTree = ""; };
57 | 4C8036EA1B90A88E00218FAE /* ExampleTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleTableViewController.swift; sourceTree = ""; };
58 | 4C86F6A21E8C0085001FB2B3 /* TextFieldEffects.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldEffects.swift; sourceTree = ""; };
59 | 4CB3B6CE1AA8DEA7000AFA56 /* TextFieldEffects.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TextFieldEffects.framework; sourceTree = BUILT_PRODUCTS_DIR; };
60 | 4CB3B6D11AA8DEA7000AFA56 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
61 | 4CB3B6D21AA8DEA7000AFA56 /* TextFieldEffects.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TextFieldEffects.h; sourceTree = ""; };
62 | 4CB3B6E71AA8DEC3000AFA56 /* HoshiTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HoshiTextField.swift; sourceTree = ""; };
63 | 4CB3B6E81AA8DEC3000AFA56 /* IsaoTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IsaoTextField.swift; sourceTree = ""; };
64 | 4CB3B6E91AA8DEC3000AFA56 /* JiroTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JiroTextField.swift; sourceTree = ""; };
65 | 4CB3B6EA1AA8DEC3000AFA56 /* KaedeTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KaedeTextField.swift; sourceTree = ""; };
66 | 4CB3B6EB1AA8DEC3000AFA56 /* MadokaTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MadokaTextField.swift; sourceTree = ""; };
67 | 4CB3B6EC1AA8DEC3000AFA56 /* MinoruTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MinoruTextField.swift; sourceTree = ""; };
68 | 4CB3B6EE1AA8DEC3000AFA56 /* YokoTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YokoTextField.swift; sourceTree = ""; };
69 | 4CBF766D1A71AF7700073B6A /* TextFieldsDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TextFieldsDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
70 | 4CBF76701A71AF7700073B6A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
71 | 4CBF76711A71AF7700073B6A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
72 | 4CBF76761A71AF7700073B6A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
73 | 4CBF76781A71AF7700073B6A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
74 | 4CBF767B1A71AF7700073B6A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
75 | DF983ABA1BBD1F4100BCC4C7 /* YoshikoTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YoshikoTextField.swift; sourceTree = ""; };
76 | /* End PBXFileReference section */
77 |
78 | /* Begin PBXFrameworksBuildPhase section */
79 | 4CB3B6CA1AA8DEA7000AFA56 /* Frameworks */ = {
80 | isa = PBXFrameworksBuildPhase;
81 | buildActionMask = 2147483647;
82 | files = (
83 | );
84 | runOnlyForDeploymentPostprocessing = 0;
85 | };
86 | 4CBF766A1A71AF7700073B6A /* Frameworks */ = {
87 | isa = PBXFrameworksBuildPhase;
88 | buildActionMask = 2147483647;
89 | files = (
90 | 4CB3B6F71AA8DED3000AFA56 /* TextFieldEffects.framework in Frameworks */,
91 | );
92 | runOnlyForDeploymentPostprocessing = 0;
93 | };
94 | /* End PBXFrameworksBuildPhase section */
95 |
96 | /* Begin PBXGroup section */
97 | 4CB3B6CF1AA8DEA7000AFA56 /* TextFieldEffects */ = {
98 | isa = PBXGroup;
99 | children = (
100 | 11E69DA61B27B1A90025D54E /* AkiraTextField.swift */,
101 | 4CB3B6E71AA8DEC3000AFA56 /* HoshiTextField.swift */,
102 | 4CB3B6E81AA8DEC3000AFA56 /* IsaoTextField.swift */,
103 | 4CB3B6E91AA8DEC3000AFA56 /* JiroTextField.swift */,
104 | 4CB3B6EA1AA8DEC3000AFA56 /* KaedeTextField.swift */,
105 | 4CB3B6EB1AA8DEC3000AFA56 /* MadokaTextField.swift */,
106 | 4CB3B6EC1AA8DEC3000AFA56 /* MinoruTextField.swift */,
107 | 4C86F6A21E8C0085001FB2B3 /* TextFieldEffects.swift */,
108 | 4CB3B6EE1AA8DEC3000AFA56 /* YokoTextField.swift */,
109 | DF983ABA1BBD1F4100BCC4C7 /* YoshikoTextField.swift */,
110 | 4CB3B6D21AA8DEA7000AFA56 /* TextFieldEffects.h */,
111 | 4CB3B6D01AA8DEA7000AFA56 /* Supporting Files */,
112 | );
113 | path = TextFieldEffects;
114 | sourceTree = "";
115 | };
116 | 4CB3B6D01AA8DEA7000AFA56 /* Supporting Files */ = {
117 | isa = PBXGroup;
118 | children = (
119 | 4CB3B6D11AA8DEA7000AFA56 /* Info.plist */,
120 | );
121 | name = "Supporting Files";
122 | sourceTree = "";
123 | };
124 | 4CBF76411A71AE4500073B6A = {
125 | isa = PBXGroup;
126 | children = (
127 | 4CBF766E1A71AF7700073B6A /* TextFieldsDemo */,
128 | 4CB3B6CF1AA8DEA7000AFA56 /* TextFieldEffects */,
129 | 4CBF764C1A71AE4500073B6A /* Products */,
130 | );
131 | sourceTree = "";
132 | };
133 | 4CBF764C1A71AE4500073B6A /* Products */ = {
134 | isa = PBXGroup;
135 | children = (
136 | 4CBF766D1A71AF7700073B6A /* TextFieldsDemo.app */,
137 | 4CB3B6CE1AA8DEA7000AFA56 /* TextFieldEffects.framework */,
138 | );
139 | name = Products;
140 | sourceTree = "";
141 | };
142 | 4CBF766E1A71AF7700073B6A /* TextFieldsDemo */ = {
143 | isa = PBXGroup;
144 | children = (
145 | 4CBF76711A71AF7700073B6A /* AppDelegate.swift */,
146 | 4C8036EA1B90A88E00218FAE /* ExampleTableViewController.swift */,
147 | 4CBF76751A71AF7700073B6A /* Main.storyboard */,
148 | 4CBF76781A71AF7700073B6A /* Images.xcassets */,
149 | 4CBF767A1A71AF7700073B6A /* LaunchScreen.xib */,
150 | 4CBF766F1A71AF7700073B6A /* Supporting Files */,
151 | );
152 | path = TextFieldsDemo;
153 | sourceTree = "";
154 | };
155 | 4CBF766F1A71AF7700073B6A /* Supporting Files */ = {
156 | isa = PBXGroup;
157 | children = (
158 | 4CBF76701A71AF7700073B6A /* Info.plist */,
159 | );
160 | name = "Supporting Files";
161 | sourceTree = "";
162 | };
163 | /* End PBXGroup section */
164 |
165 | /* Begin PBXHeadersBuildPhase section */
166 | 4CB3B6CB1AA8DEA7000AFA56 /* Headers */ = {
167 | isa = PBXHeadersBuildPhase;
168 | buildActionMask = 2147483647;
169 | files = (
170 | 4CB3B6D31AA8DEA7000AFA56 /* TextFieldEffects.h in Headers */,
171 | );
172 | runOnlyForDeploymentPostprocessing = 0;
173 | };
174 | /* End PBXHeadersBuildPhase section */
175 |
176 | /* Begin PBXNativeTarget section */
177 | 4CB3B6CD1AA8DEA7000AFA56 /* TextFieldEffects */ = {
178 | isa = PBXNativeTarget;
179 | buildConfigurationList = 4CB3B6E11AA8DEA7000AFA56 /* Build configuration list for PBXNativeTarget "TextFieldEffects" */;
180 | buildPhases = (
181 | 4CB3B6C91AA8DEA7000AFA56 /* Sources */,
182 | 4CB3B6CA1AA8DEA7000AFA56 /* Frameworks */,
183 | 4CB3B6CB1AA8DEA7000AFA56 /* Headers */,
184 | 4CB3B6CC1AA8DEA7000AFA56 /* Resources */,
185 | );
186 | buildRules = (
187 | );
188 | dependencies = (
189 | );
190 | name = TextFieldEffects;
191 | productName = TextFieldEffects;
192 | productReference = 4CB3B6CE1AA8DEA7000AFA56 /* TextFieldEffects.framework */;
193 | productType = "com.apple.product-type.framework";
194 | };
195 | 4CBF766C1A71AF7700073B6A /* TextFieldsDemo */ = {
196 | isa = PBXNativeTarget;
197 | buildConfigurationList = 4CBF76891A71AF7800073B6A /* Build configuration list for PBXNativeTarget "TextFieldsDemo" */;
198 | buildPhases = (
199 | 4CBF76691A71AF7700073B6A /* Sources */,
200 | 4CBF766A1A71AF7700073B6A /* Frameworks */,
201 | 4CBF766B1A71AF7700073B6A /* Resources */,
202 | 4CE3658B1A73CC520021A842 /* Embed Frameworks */,
203 | );
204 | buildRules = (
205 | );
206 | dependencies = (
207 | 4C42C7731AB20C97009BE2A0 /* PBXTargetDependency */,
208 | );
209 | name = TextFieldsDemo;
210 | productName = TextFieldsDemo;
211 | productReference = 4CBF766D1A71AF7700073B6A /* TextFieldsDemo.app */;
212 | productType = "com.apple.product-type.application";
213 | };
214 | /* End PBXNativeTarget section */
215 |
216 | /* Begin PBXProject section */
217 | 4CBF76421A71AE4500073B6A /* Project object */ = {
218 | isa = PBXProject;
219 | attributes = {
220 | LastSwiftUpdateCheck = 0700;
221 | LastUpgradeCheck = 1200;
222 | ORGANIZATIONNAME = "Raul Riera";
223 | TargetAttributes = {
224 | 4CB3B6CD1AA8DEA7000AFA56 = {
225 | CreatedOnToolsVersion = 6.2;
226 | LastSwiftMigration = 1100;
227 | ProvisioningStyle = Automatic;
228 | };
229 | 4CBF766C1A71AF7700073B6A = {
230 | CreatedOnToolsVersion = 6.1.1;
231 | DevelopmentTeam = R64MTWS872;
232 | LastSwiftMigration = 1100;
233 | };
234 | };
235 | };
236 | buildConfigurationList = 4CBF76451A71AE4500073B6A /* Build configuration list for PBXProject "TextFieldEffects" */;
237 | compatibilityVersion = "Xcode 3.2";
238 | developmentRegion = en;
239 | hasScannedForEncodings = 0;
240 | knownRegions = (
241 | en,
242 | Base,
243 | );
244 | mainGroup = 4CBF76411A71AE4500073B6A;
245 | productRefGroup = 4CBF764C1A71AE4500073B6A /* Products */;
246 | projectDirPath = "";
247 | projectRoot = "";
248 | targets = (
249 | 4CBF766C1A71AF7700073B6A /* TextFieldsDemo */,
250 | 4CB3B6CD1AA8DEA7000AFA56 /* TextFieldEffects */,
251 | );
252 | };
253 | /* End PBXProject section */
254 |
255 | /* Begin PBXResourcesBuildPhase section */
256 | 4CB3B6CC1AA8DEA7000AFA56 /* Resources */ = {
257 | isa = PBXResourcesBuildPhase;
258 | buildActionMask = 2147483647;
259 | files = (
260 | );
261 | runOnlyForDeploymentPostprocessing = 0;
262 | };
263 | 4CBF766B1A71AF7700073B6A /* Resources */ = {
264 | isa = PBXResourcesBuildPhase;
265 | buildActionMask = 2147483647;
266 | files = (
267 | 4CBF76771A71AF7700073B6A /* Main.storyboard in Resources */,
268 | 4CBF767C1A71AF7700073B6A /* LaunchScreen.xib in Resources */,
269 | 4CBF76791A71AF7700073B6A /* Images.xcassets in Resources */,
270 | );
271 | runOnlyForDeploymentPostprocessing = 0;
272 | };
273 | /* End PBXResourcesBuildPhase section */
274 |
275 | /* Begin PBXSourcesBuildPhase section */
276 | 4CB3B6C91AA8DEA7000AFA56 /* Sources */ = {
277 | isa = PBXSourcesBuildPhase;
278 | buildActionMask = 2147483647;
279 | files = (
280 | 4C86F6A41E8C0109001FB2B3 /* TextFieldEffects.swift in Sources */,
281 | DF983ABB1BBD1F4100BCC4C7 /* YoshikoTextField.swift in Sources */,
282 | 4CB3B6F31AA8DEC3000AFA56 /* MadokaTextField.swift in Sources */,
283 | 4CB3B6F61AA8DEC3000AFA56 /* YokoTextField.swift in Sources */,
284 | 4CB3B6EF1AA8DEC3000AFA56 /* HoshiTextField.swift in Sources */,
285 | 4CB3B6F01AA8DEC3000AFA56 /* IsaoTextField.swift in Sources */,
286 | 4CB3B6F21AA8DEC3000AFA56 /* KaedeTextField.swift in Sources */,
287 | 11E69DA71B27B1A90025D54E /* AkiraTextField.swift in Sources */,
288 | 4CB3B6F11AA8DEC3000AFA56 /* JiroTextField.swift in Sources */,
289 | 4CB3B6F41AA8DEC3000AFA56 /* MinoruTextField.swift in Sources */,
290 | );
291 | runOnlyForDeploymentPostprocessing = 0;
292 | };
293 | 4CBF76691A71AF7700073B6A /* Sources */ = {
294 | isa = PBXSourcesBuildPhase;
295 | buildActionMask = 2147483647;
296 | files = (
297 | 4C8036EB1B90A88E00218FAE /* ExampleTableViewController.swift in Sources */,
298 | 4CBF76721A71AF7700073B6A /* AppDelegate.swift in Sources */,
299 | 4C86F6A31E8C0085001FB2B3 /* TextFieldEffects.swift in Sources */,
300 | );
301 | runOnlyForDeploymentPostprocessing = 0;
302 | };
303 | /* End PBXSourcesBuildPhase section */
304 |
305 | /* Begin PBXTargetDependency section */
306 | 4C42C7731AB20C97009BE2A0 /* PBXTargetDependency */ = {
307 | isa = PBXTargetDependency;
308 | target = 4CB3B6CD1AA8DEA7000AFA56 /* TextFieldEffects */;
309 | targetProxy = 4C42C7721AB20C97009BE2A0 /* PBXContainerItemProxy */;
310 | };
311 | /* End PBXTargetDependency section */
312 |
313 | /* Begin PBXVariantGroup section */
314 | 4CBF76751A71AF7700073B6A /* Main.storyboard */ = {
315 | isa = PBXVariantGroup;
316 | children = (
317 | 4CBF76761A71AF7700073B6A /* Base */,
318 | );
319 | name = Main.storyboard;
320 | sourceTree = "";
321 | };
322 | 4CBF767A1A71AF7700073B6A /* LaunchScreen.xib */ = {
323 | isa = PBXVariantGroup;
324 | children = (
325 | 4CBF767B1A71AF7700073B6A /* Base */,
326 | );
327 | name = LaunchScreen.xib;
328 | sourceTree = "";
329 | };
330 | /* End PBXVariantGroup section */
331 |
332 | /* Begin XCBuildConfiguration section */
333 | 4CB3B6E21AA8DEA7000AFA56 /* Debug */ = {
334 | isa = XCBuildConfiguration;
335 | buildSettings = {
336 | CLANG_ENABLE_MODULES = YES;
337 | CODE_SIGN_IDENTITY = "";
338 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
339 | CODE_SIGN_STYLE = Automatic;
340 | DEFINES_MODULE = YES;
341 | DEVELOPMENT_TEAM = "";
342 | DYLIB_COMPATIBILITY_VERSION = 1;
343 | DYLIB_CURRENT_VERSION = 1;
344 | DYLIB_INSTALL_NAME_BASE = "@rpath";
345 | GCC_PREPROCESSOR_DEFINITIONS = (
346 | "DEBUG=1",
347 | "$(inherited)",
348 | );
349 | INFOPLIST_FILE = TextFieldEffects/Info.plist;
350 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
351 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
352 | PRODUCT_BUNDLE_IDENTIFIER = "com.raulriera.$(PRODUCT_NAME:rfc1034identifier)";
353 | PRODUCT_NAME = "$(TARGET_NAME)";
354 | PROVISIONING_PROFILE_SPECIFIER = "";
355 | SKIP_INSTALL = YES;
356 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
357 | SWIFT_VERSION = 5.0;
358 | };
359 | name = Debug;
360 | };
361 | 4CB3B6E31AA8DEA7000AFA56 /* Release */ = {
362 | isa = XCBuildConfiguration;
363 | buildSettings = {
364 | CLANG_ENABLE_MODULES = YES;
365 | CODE_SIGN_IDENTITY = "";
366 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
367 | CODE_SIGN_STYLE = Automatic;
368 | COPY_PHASE_STRIP = NO;
369 | DEFINES_MODULE = YES;
370 | DEVELOPMENT_TEAM = "";
371 | DYLIB_COMPATIBILITY_VERSION = 1;
372 | DYLIB_CURRENT_VERSION = 1;
373 | DYLIB_INSTALL_NAME_BASE = "@rpath";
374 | INFOPLIST_FILE = TextFieldEffects/Info.plist;
375 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
376 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
377 | PRODUCT_BUNDLE_IDENTIFIER = "com.raulriera.$(PRODUCT_NAME:rfc1034identifier)";
378 | PRODUCT_NAME = "$(TARGET_NAME)";
379 | PROVISIONING_PROFILE_SPECIFIER = "";
380 | SKIP_INSTALL = YES;
381 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
382 | SWIFT_VERSION = 5.0;
383 | };
384 | name = Release;
385 | };
386 | 4CBF765F1A71AE4500073B6A /* Debug */ = {
387 | isa = XCBuildConfiguration;
388 | buildSettings = {
389 | ALWAYS_SEARCH_USER_PATHS = NO;
390 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
391 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
392 | CLANG_CXX_LIBRARY = "libc++";
393 | CLANG_ENABLE_MODULES = YES;
394 | CLANG_ENABLE_OBJC_ARC = YES;
395 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
396 | CLANG_WARN_BOOL_CONVERSION = YES;
397 | CLANG_WARN_COMMA = YES;
398 | CLANG_WARN_CONSTANT_CONVERSION = YES;
399 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
400 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
401 | CLANG_WARN_EMPTY_BODY = YES;
402 | CLANG_WARN_ENUM_CONVERSION = YES;
403 | CLANG_WARN_INFINITE_RECURSION = YES;
404 | CLANG_WARN_INT_CONVERSION = YES;
405 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
406 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
407 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
408 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
409 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
410 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
411 | CLANG_WARN_STRICT_PROTOTYPES = YES;
412 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
413 | CLANG_WARN_UNREACHABLE_CODE = YES;
414 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
415 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
416 | COPY_PHASE_STRIP = NO;
417 | CURRENT_PROJECT_VERSION = 1;
418 | ENABLE_STRICT_OBJC_MSGSEND = YES;
419 | ENABLE_TESTABILITY = YES;
420 | GCC_C_LANGUAGE_STANDARD = gnu99;
421 | GCC_DYNAMIC_NO_PIC = NO;
422 | GCC_NO_COMMON_BLOCKS = YES;
423 | GCC_OPTIMIZATION_LEVEL = 0;
424 | GCC_PREPROCESSOR_DEFINITIONS = (
425 | "DEBUG=1",
426 | "$(inherited)",
427 | );
428 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
429 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
430 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
431 | GCC_WARN_UNDECLARED_SELECTOR = YES;
432 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
433 | GCC_WARN_UNUSED_FUNCTION = YES;
434 | GCC_WARN_UNUSED_VARIABLE = YES;
435 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
436 | MTL_ENABLE_DEBUG_INFO = YES;
437 | ONLY_ACTIVE_ARCH = YES;
438 | SDKROOT = iphoneos;
439 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
440 | SWIFT_VERSION = 4.2;
441 | TARGETED_DEVICE_FAMILY = "1,2";
442 | VERSIONING_SYSTEM = "apple-generic";
443 | VERSION_INFO_PREFIX = "";
444 | };
445 | name = Debug;
446 | };
447 | 4CBF76601A71AE4500073B6A /* Release */ = {
448 | isa = XCBuildConfiguration;
449 | buildSettings = {
450 | ALWAYS_SEARCH_USER_PATHS = NO;
451 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
452 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
453 | CLANG_CXX_LIBRARY = "libc++";
454 | CLANG_ENABLE_MODULES = YES;
455 | CLANG_ENABLE_OBJC_ARC = YES;
456 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
457 | CLANG_WARN_BOOL_CONVERSION = YES;
458 | CLANG_WARN_COMMA = YES;
459 | CLANG_WARN_CONSTANT_CONVERSION = YES;
460 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
461 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
462 | CLANG_WARN_EMPTY_BODY = YES;
463 | CLANG_WARN_ENUM_CONVERSION = YES;
464 | CLANG_WARN_INFINITE_RECURSION = YES;
465 | CLANG_WARN_INT_CONVERSION = YES;
466 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
467 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
468 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
469 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
470 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
471 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
472 | CLANG_WARN_STRICT_PROTOTYPES = YES;
473 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
474 | CLANG_WARN_UNREACHABLE_CODE = YES;
475 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
476 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
477 | COPY_PHASE_STRIP = YES;
478 | CURRENT_PROJECT_VERSION = 1;
479 | ENABLE_NS_ASSERTIONS = NO;
480 | ENABLE_STRICT_OBJC_MSGSEND = YES;
481 | GCC_C_LANGUAGE_STANDARD = gnu99;
482 | GCC_NO_COMMON_BLOCKS = YES;
483 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
484 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
485 | GCC_WARN_UNDECLARED_SELECTOR = YES;
486 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
487 | GCC_WARN_UNUSED_FUNCTION = YES;
488 | GCC_WARN_UNUSED_VARIABLE = YES;
489 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
490 | MTL_ENABLE_DEBUG_INFO = NO;
491 | SDKROOT = iphoneos;
492 | SWIFT_VERSION = 4.2;
493 | TARGETED_DEVICE_FAMILY = "1,2";
494 | VALIDATE_PRODUCT = YES;
495 | VERSIONING_SYSTEM = "apple-generic";
496 | VERSION_INFO_PREFIX = "";
497 | };
498 | name = Release;
499 | };
500 | 4CBF768A1A71AF7800073B6A /* Debug */ = {
501 | isa = XCBuildConfiguration;
502 | buildSettings = {
503 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
504 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
505 | DEVELOPMENT_TEAM = R64MTWS872;
506 | GCC_PREPROCESSOR_DEFINITIONS = (
507 | "DEBUG=1",
508 | "$(inherited)",
509 | );
510 | INFOPLIST_FILE = TextFieldsDemo/Info.plist;
511 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
512 | PRODUCT_BUNDLE_IDENTIFIER = "com.raulriera.$(PRODUCT_NAME:rfc1034identifier)";
513 | PRODUCT_NAME = "$(TARGET_NAME)";
514 | SWIFT_VERSION = 5.0;
515 | };
516 | name = Debug;
517 | };
518 | 4CBF768B1A71AF7800073B6A /* Release */ = {
519 | isa = XCBuildConfiguration;
520 | buildSettings = {
521 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
522 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
523 | DEVELOPMENT_TEAM = R64MTWS872;
524 | INFOPLIST_FILE = TextFieldsDemo/Info.plist;
525 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
526 | PRODUCT_BUNDLE_IDENTIFIER = "com.raulriera.$(PRODUCT_NAME:rfc1034identifier)";
527 | PRODUCT_NAME = "$(TARGET_NAME)";
528 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
529 | SWIFT_VERSION = 5.0;
530 | };
531 | name = Release;
532 | };
533 | /* End XCBuildConfiguration section */
534 |
535 | /* Begin XCConfigurationList section */
536 | 4CB3B6E11AA8DEA7000AFA56 /* Build configuration list for PBXNativeTarget "TextFieldEffects" */ = {
537 | isa = XCConfigurationList;
538 | buildConfigurations = (
539 | 4CB3B6E21AA8DEA7000AFA56 /* Debug */,
540 | 4CB3B6E31AA8DEA7000AFA56 /* Release */,
541 | );
542 | defaultConfigurationIsVisible = 0;
543 | defaultConfigurationName = Release;
544 | };
545 | 4CBF76451A71AE4500073B6A /* Build configuration list for PBXProject "TextFieldEffects" */ = {
546 | isa = XCConfigurationList;
547 | buildConfigurations = (
548 | 4CBF765F1A71AE4500073B6A /* Debug */,
549 | 4CBF76601A71AE4500073B6A /* Release */,
550 | );
551 | defaultConfigurationIsVisible = 0;
552 | defaultConfigurationName = Release;
553 | };
554 | 4CBF76891A71AF7800073B6A /* Build configuration list for PBXNativeTarget "TextFieldsDemo" */ = {
555 | isa = XCConfigurationList;
556 | buildConfigurations = (
557 | 4CBF768A1A71AF7800073B6A /* Debug */,
558 | 4CBF768B1A71AF7800073B6A /* Release */,
559 | );
560 | defaultConfigurationIsVisible = 0;
561 | defaultConfigurationName = Release;
562 | };
563 | /* End XCConfigurationList section */
564 | };
565 | rootObject = 4CBF76421A71AE4500073B6A /* Project object */;
566 | }
567 |
--------------------------------------------------------------------------------
/TextFieldEffects/TextFieldsDemo/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 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
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 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
--------------------------------------------------------------------------------