├── Captures ├── Kyo.gif ├── Sae.gif ├── Akira.gif ├── Hideo.gif ├── Hoshi.gif ├── Isao.gif ├── Jiro.gif ├── Kaede.gif ├── Kuro.gif ├── Ruri.gif ├── Yoko.gif ├── Chisato.gif ├── Haruki.gif ├── Kohana.gif ├── Madoka.gif ├── Manami.gif ├── Minoru.gif ├── Nariko.gif └── Yoshiko.gif ├── CCTextFieldEffects ├── pencil.png ├── Info.plist ├── YokoTextField.h ├── KaedeTextField.h ├── HideoTextField.h ├── KohanaTextField.h ├── KuroTextField.h ├── AkiraTextField.h ├── MadokaTextField.h ├── JiroTextField.h ├── HarukiTextField.h ├── MinoruTextField.h ├── IsaoTextField.h ├── KyoTextField.h ├── ManamiTextField.h ├── NarikoTextField.h ├── SaeTextField.h ├── HoshiTextField.h ├── ChisatoTextField.h ├── RuriTextField.h ├── CCTextField.h ├── YoshikoTextField.h ├── CCTextFieldEffects.h ├── PulsingHaloLayer.h ├── CCTextField.m ├── PulsingHaloLayer.m ├── HideoTextField.m ├── KohanaTextField.m ├── AkiraTextField.m ├── KaedeTextField.m ├── HarukiTextField.m ├── ChisatoTextField.m ├── SaeTextField.m ├── MinoruTextField.m ├── KyoTextField.m ├── JiroTextField.m ├── IsaoTextField.m ├── NarikoTextField.m ├── YoshikoTextField.m ├── MadokaTextField.m ├── RuriTextField.m ├── ManamiTextField.m ├── HoshiTextField.m ├── KuroTextField.m └── YokoTextField.m ├── CCTextFieldEffectsDemo ├── mail.png ├── user.png ├── ViewController.h ├── AppDelegate.h ├── main.m ├── DetailViewController.h ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── effects.json ├── AppDelegate.m ├── ViewController.m ├── Base.lproj │ └── Main.storyboard └── DetailViewController.m ├── CCTextFieldEffects.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── CCTextFieldEffects.xcscheme ├── CCTextFieldEffects.podspec ├── .gitignore └── Licence /Captures/Kyo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/Captures/Kyo.gif -------------------------------------------------------------------------------- /Captures/Sae.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/Captures/Sae.gif -------------------------------------------------------------------------------- /Captures/Akira.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/Captures/Akira.gif -------------------------------------------------------------------------------- /Captures/Hideo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/Captures/Hideo.gif -------------------------------------------------------------------------------- /Captures/Hoshi.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/Captures/Hoshi.gif -------------------------------------------------------------------------------- /Captures/Isao.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/Captures/Isao.gif -------------------------------------------------------------------------------- /Captures/Jiro.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/Captures/Jiro.gif -------------------------------------------------------------------------------- /Captures/Kaede.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/Captures/Kaede.gif -------------------------------------------------------------------------------- /Captures/Kuro.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/Captures/Kuro.gif -------------------------------------------------------------------------------- /Captures/Ruri.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/Captures/Ruri.gif -------------------------------------------------------------------------------- /Captures/Yoko.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/Captures/Yoko.gif -------------------------------------------------------------------------------- /Captures/Chisato.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/Captures/Chisato.gif -------------------------------------------------------------------------------- /Captures/Haruki.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/Captures/Haruki.gif -------------------------------------------------------------------------------- /Captures/Kohana.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/Captures/Kohana.gif -------------------------------------------------------------------------------- /Captures/Madoka.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/Captures/Madoka.gif -------------------------------------------------------------------------------- /Captures/Manami.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/Captures/Manami.gif -------------------------------------------------------------------------------- /Captures/Minoru.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/Captures/Minoru.gif -------------------------------------------------------------------------------- /Captures/Nariko.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/Captures/Nariko.gif -------------------------------------------------------------------------------- /Captures/Yoshiko.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/Captures/Yoshiko.gif -------------------------------------------------------------------------------- /CCTextFieldEffects/pencil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/CCTextFieldEffects/pencil.png -------------------------------------------------------------------------------- /CCTextFieldEffectsDemo/mail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/CCTextFieldEffectsDemo/mail.png -------------------------------------------------------------------------------- /CCTextFieldEffectsDemo/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cokile/CCTextFieldEffects/HEAD/CCTextFieldEffectsDemo/user.png -------------------------------------------------------------------------------- /CCTextFieldEffects.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CCTextFieldEffectsDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/25/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UITableViewController 12 | 13 | @end 14 | 15 | -------------------------------------------------------------------------------- /CCTextFieldEffectsDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/25/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /CCTextFieldEffectsDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/25/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /CCTextFieldEffectsDemo/DetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DetailViewController.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/25/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DetailViewController : UIViewController 12 | 13 | @property (nonatomic) CGFloat red; 14 | @property (nonatomic) CGFloat green; 15 | @property (nonatomic) CGFloat blue; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /CCTextFieldEffects.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = 'CCTextFieldEffects' 3 | spec.platform = :ios 4 | spec.version = '0.1.3' 5 | spec.license = { :type => 'MIT' } 6 | spec.homepage = 'https://github.com/Cokile/CCTextFieldEffects' 7 | spec.authors = { 'Cokile' => 'kelvintgx@gmail.com' } 8 | spec.summary = 'A simple replacement for UITextField.' 9 | spec.source = { :git => 'https://github.com/Cokile/CCTextFieldEffects.git', :tag => 'v0.1.3'} 10 | spec.source_files = 'CCTextFieldEffects/*.{h,m}' 11 | spec.resources = 'CCTextFieldEffects/*.png' 12 | spec.requires_arc = true 13 | end 14 | -------------------------------------------------------------------------------- /CCTextFieldEffectsDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /CCTextFieldEffects/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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata 19 | 20 | ## Other 21 | *.xccheckout 22 | *.moved-aside 23 | *.xcuserstate 24 | *.xcscmblueprint 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | 30 | # CocoaPods 31 | # 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 35 | # 36 | Pods/ 37 | # Carthage 38 | # 39 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 40 | # Carthage/Checkouts 41 | 42 | Carthage/Build 43 | -------------------------------------------------------------------------------- /CCTextFieldEffects/YokoTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // YokoTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/26/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @interface YokoTextField : CCTextField 12 | 13 | #pragma mark - Public properties 14 | /** 15 | * The color of the placeholder text. 16 | * 17 | * This property applies a color to the complete placeholder string. The default value for this property is a shallow gray color. 18 | */ 19 | @property (strong, nonatomic) UIColor *placeholderColor; 20 | 21 | /** 22 | * The view’s foreground color. 23 | * 24 | * The default value for this property is a black color. 25 | */ 26 | @property (strong, nonatomic) UIColor *foregroundColor; 27 | 28 | /** 29 | * The scale of the placeholder font. 30 | * 31 | * This property determines the size of the placeholder label relative to the font size of the text field. 32 | */ 33 | @property (nonatomic) CGFloat placeholderFontScale; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /CCTextFieldEffects/KaedeTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // KaedeTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/26/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @interface KaedeTextField : CCTextField 12 | 13 | #pragma mark - Public properties 14 | 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 dark gray color. 19 | */ 20 | @property (strong, nonatomic) UIColor *placeholderColor; 21 | 22 | /** 23 | * The view’s foreground color. 24 | * 25 | * The default value for this property is a shallow gray color. 26 | */ 27 | @property (strong, nonatomic) UIColor *foregroundColor; 28 | 29 | /** 30 | * The scale of the placeholder font. 31 | * 32 | * This property determines the size of the placeholder label relative to the font size of the text field. 33 | */ 34 | @property (nonatomic) CGFloat placeholderFontScale; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /CCTextFieldEffects/HideoTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // HideoTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/27/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @interface HideoTextField : CCTextField 12 | 13 | #pragma mark - Public properties 14 | 15 | /** 16 | * The color of the image container color. 17 | * 18 | * This property applies a color to the background of the image container. The default value for this property is a purple color. 19 | */ 20 | @property (strong, nonatomic) UIColor *imageContainerColor; 21 | 22 | /** 23 | * The image of the image container view. 24 | * 25 | * This property applies a image to the image container. 26 | */ 27 | @property (strong, nonatomic) UIImage *image; 28 | 29 | /** 30 | * The scale of the image. 31 | * 32 | * This property determines the size of the image relative to the original size when animated. The default value for this properties is 0.7 33 | */ 34 | @property (nonatomic) CGFloat imageScale; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /CCTextFieldEffects/KohanaTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // KohanaTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 7/1/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @interface KohanaTextField : CCTextField 12 | 13 | #pragma mark - Public properties 14 | /** 15 | * The color of the placeholder text. 16 | * 17 | * This property applies a color to the complete placeholder string. The default value for this property is a gray color. 18 | */ 19 | @property (strong, nonatomic) UIColor *placeholderColor; 20 | 21 | /** 22 | * The image of the comtrol. 23 | * 24 | * This property applies a image to the control. The color of the image is determined by placeholderColor. 25 | */ 26 | @property (strong, nonatomic) UIImage *image; 27 | 28 | /** 29 | * The scale of the placeholder font. 30 | * 31 | * This property determines the size of the placeholder label relative to the font size of the text field. 32 | */ 33 | @property (nonatomic) CGFloat placeholderFontScale; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /CCTextFieldEffects/KuroTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // KuroTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/29/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @interface KuroTextField : CCTextField 12 | 13 | #pragma mark - Public properties 14 | /** 15 | * The color of the border. 16 | * 17 | * This property applies a color to the bonuds of the border. The default value for this property is a gray color. 18 | */ 19 | @property (strong, nonatomic) UIColor *borderColor; 20 | 21 | /** 22 | * The color of the placeholder text. 23 | * 24 | * This property applies a color to the complete placeholder string. The default value for this property is a pink color. 25 | */ 26 | @property (strong, nonatomic) UIColor *placeholderColor; 27 | 28 | /** 29 | * The scale of the placeholder font. 30 | * 31 | * This property determines the size of the placeholder label relative to the font size of the text field. 32 | */ 33 | @property (nonatomic) CGFloat placeholderFontScale; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /CCTextFieldEffects/AkiraTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // AkiraTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/25/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @interface AkiraTextField : CCTextField 12 | 13 | #pragma mark - Public properties 14 | /** 15 | * The color of the border. 16 | * 17 | * This property applies a color to the bounds of the control. The default value for this property is a grey color. 18 | */ 19 | @property (strong, nonatomic) UIColor *borderColor; 20 | 21 | /** 22 | * The color of the placeholder text. 23 | * 24 | * This property applies a color to the complete placeholder string. The default value for this property is a orange color. 25 | */ 26 | @property (strong, nonatomic) UIColor *placeholderColor; 27 | 28 | /** 29 | * The scale of the placeholder font. 30 | * 31 | * This property determines the size of the placeholder label relative to the font size of the text field. 32 | */ 33 | @property (nonatomic) CGFloat placeholderFontScale; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /CCTextFieldEffects/MadokaTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // MadokaTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/26/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @interface MadokaTextField : CCTextField 12 | 13 | #pragma mark - Public properties 14 | /** 15 | * The color of the placeholder text. 16 | * 17 | * This property applies a color to the complete placeholder string. The default value for this property is a purple color. 18 | */ 19 | @property (strong, nonatomic) UIColor *placeholderColor; 20 | 21 | /** 22 | * The color of the border. 23 | * 24 | * This property applies a color to the lower edge of the control. The default value for this property is a purple color. 25 | */ 26 | @property (strong, nonatomic) UIColor *borderColor; 27 | 28 | /** 29 | * The scale of the placeholder font. 30 | * 31 | * This property determines the size of the placeholder label relative to the font size of the text field. 32 | */ 33 | @property (nonatomic) CGFloat placeholderFontScale; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /CCTextFieldEffects/JiroTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // JiroTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/26/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @interface JiroTextField : CCTextField 12 | 13 | #pragma mark - Public properties 14 | /** 15 | * The color of the border. 16 | * 17 | * This property applies a color to the lower edge of the control. The default value for this property is a shadow blue color. 18 | */ 19 | @property (strong, nonatomic) UIColor *borderColor; 20 | 21 | /** 22 | * The color of the placeholder text. 23 | * 24 | * This property applies a color to the complete placeholder string. The default value for this property is a shadow blue color. 25 | */ 26 | @property (strong, nonatomic) UIColor *placeholderColor; 27 | 28 | /** 29 | * The scale of the placeholder font. 30 | * 31 | * This property determines the size of the placeholder label relative to the font size of the text field. 32 | */ 33 | @property (nonatomic) CGFloat placeholderFontScale; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /CCTextFieldEffects/HarukiTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // HarukiTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/28/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @interface HarukiTextField : CCTextField 12 | 13 | #pragma mark - Public properties 14 | 15 | /** 16 | * The color of the border. 17 | * 18 | * This property applies a color to the upper and lower borders of the control. The default value for this property is a dark gray color. 19 | */ 20 | @property (strong, nonatomic) UIColor *borderColor; 21 | 22 | /** 23 | * The color of the placeholder text. 24 | * 25 | * This property applies a color to the complete placeholder string. The default value for this property is a dark gray color. 26 | */ 27 | @property (strong, nonatomic) UIColor *placeholderColor; 28 | 29 | /** 30 | * The scale of the placeholder font. 31 | * 32 | * This property determines the size of the placeholder label relative to the font size of the text field. 33 | */ 34 | @property (nonatomic) CGFloat placeholderFontScale; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /CCTextFieldEffects/MinoruTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // MinoruTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/28/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @interface MinoruTextField : CCTextField 12 | 13 | #pragma mark - Public properties 14 | /** 15 | * The color of the placeholder text. 16 | * 17 | * This property applies a color to the complete placeholder string. The default value for this property is a dark gray color. 18 | */ 19 | @property (strong, nonatomic) UIColor *placeholderColor; 20 | 21 | /** 22 | * The color of the border color when active. 23 | * 24 | * This property applies a color to the border. The default value for this property is a shallow red color. 25 | */ 26 | @property (strong, nonatomic) UIColor *borderColor; 27 | 28 | @property (strong, nonatomic) UIColor *backgroundColor; 29 | 30 | /** 31 | * The scale of the placeholder font. 32 | * 33 | * This property determines the size of the placeholder label relative to the font size of the text field. 34 | */ 35 | @property (nonatomic) CGFloat placeholderFontScale; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /CCTextFieldEffects/IsaoTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // IsaoTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/25/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @interface IsaoTextField : CCTextField 12 | 13 | #pragma mark - Public properties 14 | /** 15 | * The color of the border when it has no content. 16 | * 17 | * This property applies a color to the lower edge of the control. The default value for this property is a white color. This value is also applied to the placeholder color. 18 | */ 19 | @property (strong, nonatomic) UIColor *inactiveColor; 20 | 21 | /** 22 | * The color of the border when it has content. 23 | * 24 | * This property applies a color to the lower edge of the control. The default value for this property is a shallow red color. 25 | */ 26 | @property (strong, nonatomic) UIColor *activeColor; 27 | 28 | /** 29 | * The scale of the placeholder font. 30 | * 31 | * This property determines the size of the placeholder label relative to the font size of the text field. 32 | */ 33 | @property (nonatomic) CGFloat placeholderFontScale; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /CCTextFieldEffects/KyoTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // KyoTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/28/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @interface KyoTextField : CCTextField 12 | 13 | #pragma mark - Public properties 14 | /** 15 | * The color of the placeholder text. 16 | * 17 | * This property applies a color to the complete placeholder string. The default value for this property is a dark gray color. 18 | */ 19 | @property (strong, nonatomic) UIColor *placeholderColor; 20 | 21 | /** 22 | * The color of the overlay. 23 | * 24 | * This property applies a color to the complete placeholder string. The default value for this property is a transparent transparent purple color. 25 | */ 26 | @property (strong, nonatomic) UIColor *overlayColor; 27 | 28 | @property (strong, nonatomic) UIColor *backgroundColor; 29 | 30 | /** 31 | * The scale of the placeholder font. 32 | * 33 | * This property determines the size of the placeholder label relative to the font size of the text field. 34 | */ 35 | @property (nonatomic) CGFloat placeholderFontScale; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Licence: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2016 Runqiu Xu. 3 | This code is distributed under the terms and conditions of the MIT license. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in the 7 | Software without restriction, including without limitation the rights to use, copy, 8 | modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 9 | and to permit persons to whom the Software is furnished to do so, subject to the 10 | 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 IMPLIED, 16 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 17 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 18 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 19 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 20 | OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /CCTextFieldEffectsDemo/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 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /CCTextFieldEffects/ManamiTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // ManamiTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/30/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @interface ManamiTextField : CCTextField 12 | 13 | #pragma mark - Public properties 14 | /** 15 | * The color of the placeholder text. 16 | * 17 | * This property applies a color to the complete placeholder string. The default value for this property is a gray color. 18 | */ 19 | @property (strong, nonatomic) UIColor *placeholderColor; 20 | 21 | /** 22 | * The color of the border. 23 | * 24 | * This property applies a color to the lower edge of the control. The default value for this property is a gray color. 25 | */ 26 | @property (strong, nonatomic) UIColor *borderColor; 27 | 28 | /** 29 | * The color of the background. 30 | * 31 | * This property applies a color to the background of the text area. The default value for this property is a gray color. 32 | */ 33 | @property (strong, nonatomic) UIColor *backgroundColor; 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 | @property (nonatomic) CGFloat placeholderFontScale; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /CCTextFieldEffects/NarikoTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // NarikoTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/30/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @interface NarikoTextField : CCTextField 12 | 13 | #pragma mark - Public properties 14 | /** 15 | * The color of the placeholder text. 16 | * 17 | * This property applies a color to the complete placeholder string. The default value for this property is a gray color. 18 | */ 19 | @property (strong, nonatomic) UIColor *placeholderColor; 20 | 21 | /** 22 | * The color of the border. 23 | * 24 | * This property applies a color to the lower edge of the control. The default value for this property is a gray color. 25 | */ 26 | @property (strong, nonatomic) UIColor *borderColor; 27 | 28 | /** 29 | * The color of the background. 30 | * 31 | * This property applies a color to the background of the text area. The default value for this property is a white color. 32 | */ 33 | @property (strong, nonatomic) UIColor *backgroundColor; 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 | @property (nonatomic) CGFloat placeholderFontScale; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /CCTextFieldEffects/SaeTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // SaeTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 7/1/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @interface SaeTextField : CCTextField 12 | 13 | #pragma mark - Public properties 14 | /** 15 | * The color of the border. 16 | * 17 | * This property applies a color to the lower border of the control. The default value for this property is a white color. 18 | */ 19 | @property (strong, nonatomic) UIColor *borderColor; 20 | 21 | /** 22 | * The image of the control. 23 | * 24 | * This property applies a image to the right-down of the control, the color of the image is determined by borderColor. The default value for this property is a pencil. 25 | */ 26 | @property (strong, nonatomic) UIImage *image; 27 | 28 | /** 29 | * The color of the placeholder text. 30 | * 31 | * This property applies a color to the complete placeholder string. The default value for this property is a transparent black color. 32 | */ 33 | @property (strong, nonatomic) UIColor *placeholderColor; 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 | @property (nonatomic) CGFloat placeholderFontScale; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /CCTextFieldEffects/HoshiTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // HoshiTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/25/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @interface HoshiTextField : CCTextField 12 | 13 | #pragma mark - Public methods 14 | /** 15 | * The color of the border when it has no content. 16 | * 17 | * his property applies a color to the lower edge of the control. The default value for this property is a gray color. 18 | */ 19 | @property (strong, nonatomic) UIColor *borderInactiveColor; 20 | 21 | /** 22 | * The color of the border when it has content. 23 | * 24 | * This property applies a color to the lower edge of the control. The default value for this property is a dark gray color. 25 | */ 26 | @property (strong, nonatomic) UIColor *borderActiveColor; 27 | 28 | /** 29 | * The color of the placeholder text. 30 | * 31 | * This property applies a color to the complete placeholder string. The default value for this property is a gray color. 32 | */ 33 | @property (strong, nonatomic) UIColor *placeholderColor; 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 | @property(nonatomic) CGFloat placeholderFontScale; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /CCTextFieldEffects/ChisatoTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // ChisatoTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/29/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @interface ChisatoTextField : CCTextField 12 | 13 | #pragma mark - Public properties 14 | /** 15 | * The color of the border. 16 | * 17 | * This property applies a color to the bounds of the control. The default value for this property is a grey color. 18 | */ 19 | @property (strong, nonatomic) UIColor *borderColor; 20 | 21 | /** 22 | * The color of the placeholder text. 23 | * 24 | * This property applies a color to the complete placeholder string. The default value for this property is a gray color. 25 | */ 26 | @property (strong, nonatomic) UIColor *placeholderColor; 27 | 28 | /** 29 | * The color of the active border and placeholder. 30 | * 31 | * This property applies a color to the bounds of the control and placeholder when the text is not empty or focused. The default value for this property is a pink color. 32 | */ 33 | @property (strong, nonatomic) UIColor *activeColor; 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 | @property (nonatomic) CGFloat placeholderFontScale; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /CCTextFieldEffects/RuriTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // RuriTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/29/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @interface RuriTextField : CCTextField 12 | 13 | #pragma mark - Public properties 14 | /** 15 | * The color of the placeholder text. 16 | * 17 | * This property applies a color to the complete placeholder string. The default value for this property is a purple color. 18 | */ 19 | @property (strong, nonatomic) UIColor *placeholderColor; 20 | 21 | /** 22 | * The color of the border. 23 | * 24 | * This property applies a color to the lower edge of the control. The default value for this property is a shallow green color. 25 | */ 26 | @property (strong, nonatomic) UIColor *borderColor; 27 | 28 | /** 29 | * The color of the active border and placeholder. 30 | * 31 | * This property applies a color to the lower edge of the control and placeholder when the text is not empty or focused. The default value for this property is a shallow green color. 32 | */ 33 | @property (strong, nonatomic) UIColor *activeColor; 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 | @property (nonatomic) CGFloat placeholderFontScale; 41 | 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /CCTextFieldEffects/CCTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // CCTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/25/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | * Closure executed when an animation has been completed 13 | * 14 | * @param type The type of animatino a TextFieldEffect can perform. 15 | */ 16 | typedef void(^AnimationCompletionHandler)(void); 17 | 18 | @interface CCTextField : UITextField 19 | 20 | #pragma mark - Public properties 21 | /** 22 | * UIColor that indicates the cursorColor. 23 | */ 24 | @property (strong, nonatomic) UIColor *cursorColor; 25 | 26 | /** 27 | * UILabel that holds all the placeholder information. 28 | */ 29 | @property (strong, nonatomic) UILabel *placeholderLabel; 30 | 31 | /** 32 | * Block executed when the animation for obtaining focus has been completed. 33 | */ 34 | @property (copy, nonatomic) AnimationCompletionHandler didBeginEditingHandler; 35 | 36 | /** 37 | * Block executed when the animation for losing focus has been completed. 38 | */ 39 | @property (copy, nonatomic) AnimationCompletionHandler didEndEditingHandler; 40 | 41 | #pragma mark - Public methods 42 | /** 43 | * Creates all the animations that are used to leave the textfield in the "entering text" state. 44 | */ 45 | - (void)animateViewsForTextEntry; 46 | 47 | /** 48 | * Creates all the animations that are used to leave the textfield in the "display input text" state. 49 | */ 50 | - (void)animateViewsForTextDisplay; 51 | 52 | - (void)updateViewsForBoundsChange:(CGRect)bounds; 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /CCTextFieldEffects/YoshikoTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // YoshikoTextField.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/26/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @interface YoshikoTextField : CCTextField 12 | 13 | #pragma mark - Public properties 14 | /** 15 | * The color of the border when it has content. 16 | * 17 | * This property applies a color to the edges of the control. The default value for this property is a green color. 18 | */ 19 | @property (strong, nonatomic) UIColor *activeBorderColor; 20 | 21 | /** 22 | * The color of the border when it has no content. 23 | * 24 | * This property applies a color to the edges of the control. The default value for this property is a clear color. 25 | */ 26 | @property (strong, nonatomic) UIColor *inactiveBorderColor; 27 | 28 | /** 29 | * The color of the input's background when it has content. When it's not focused it reverts to the color of the `inactiveBorderColor` The default value for this property is a white color. 30 | */ 31 | @property (strong, nonatomic) UIColor *activeBackgroundColor; 32 | 33 | /** 34 | * The color of the placeholder text. 35 | * 36 | * This property applies a color to the complete placeholder string. The default value for this property is a dark gray color. 37 | */ 38 | @property (strong, nonatomic) UIColor *placeholderColor; 39 | 40 | /** 41 | * The scale of the placeholder font. 42 | * 43 | * This property determines the size of the placeholder label relative to the font size of the text field. 44 | */ 45 | @property (nonatomic) CGFloat placeholderFontScale; 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /CCTextFieldEffects/CCTextFieldEffects.h: -------------------------------------------------------------------------------- 1 | // 2 | // CCTextFieldEffects.h 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 7/2/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for CCTextFieldEffects. 12 | FOUNDATION_EXPORT double CCTextFieldEffectsVersionNumber; 13 | 14 | //! Project version string for CCTextFieldEffects. 15 | FOUNDATION_EXPORT const unsigned char CCTextFieldEffectsVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | #import 20 | #import 21 | #import 22 | #import 23 | #import 24 | #import 25 | #import 26 | #import 27 | #import 28 | #import 29 | #import 30 | #import 31 | #import 32 | #import 33 | #import 34 | #import 35 | #import 36 | #import 37 | #import 38 | #import 39 | 40 | #import 41 | -------------------------------------------------------------------------------- /CCTextFieldEffectsDemo/effects.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "backgroundColor": [47, 50, 56], 4 | "title":"Akira", 5 | }, 6 | 7 | { 8 | "backgroundColor": [249, 247, 246], 9 | "title":"Hoshi", 10 | }, 11 | 12 | { 13 | "backgroundColor": [61, 68, 68], 14 | "title":"Isao", 15 | }, 16 | 17 | { 18 | "backgroundColor": [208, 214, 214], 19 | "title":"Jiro", 20 | }, 21 | 22 | { 23 | "backgroundColor": [249, 247, 246], 24 | "title":"Kaede", 25 | }, 26 | 27 | { 28 | "backgroundColor": [47, 50, 56], 29 | "title":"Madoka", 30 | }, 31 | 32 | { 33 | "backgroundColor": [223, 102, 89], 34 | "title":"Yoko", 35 | }, 36 | 37 | { 38 | "backgroundColor": [249, 247, 246], 39 | "title":"Yoshiko", 40 | }, 41 | 42 | { 43 | "backgroundColor": [249, 247, 246], 44 | "title":"Hideo", 45 | }, 46 | 47 | { 48 | "backgroundColor": [240, 239, 238], 49 | "title":"Haruki", 50 | }, 51 | 52 | { 53 | "backgroundColor": [249, 247, 246], 54 | "title":"Minoru", 55 | }, 56 | 57 | { 58 | "backgroundColor": [232, 232, 232], 59 | "title":"Kyo", 60 | }, 61 | 62 | { 63 | "backgroundColor": [47, 50, 56], 64 | "title":"Kuro", 65 | }, 66 | 67 | { 68 | "backgroundColor": [47, 50, 56], 69 | "title":"Ruri", 70 | }, 71 | 72 | { 73 | "backgroundColor": [47, 50, 56], 74 | "title":"Chisato", 75 | }, 76 | 77 | { 78 | "backgroundColor": [232, 232, 232], 79 | "title":"Manami", 80 | }, 81 | 82 | { 83 | "backgroundColor": [208, 214, 214], 84 | "title":"Nariko", 85 | }, 86 | 87 | { 88 | "backgroundColor": [135, 129, 189], 89 | "title":"Sae", 90 | }, 91 | 92 | { 93 | "backgroundColor": [232, 232, 232], 94 | "title":"Kohana", 95 | }, 96 | ] 97 | -------------------------------------------------------------------------------- /CCTextFieldEffects/PulsingHaloLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // PulsingHaloLayer.h 3 | // https://github.com/shu223/PulsingHalo 4 | // 5 | // Created by shuichi on 12/5/13. 6 | // Copyright (c) 2013 Shuichi Tsutsumi. All rights reserved. 7 | // 8 | // Inspired by https://github.com/samvermette/SVPulsingAnnotationView 9 | 10 | 11 | #import 12 | #import 13 | 14 | 15 | @interface PulsingHaloLayer : CALayer 16 | 17 | /** 18 | * The default value of this property is @c 60pt. 19 | */ 20 | @property (nonatomic, assign) CGFloat radius; 21 | 22 | /** 23 | * The default value of this property is @c 0.0. 24 | */ 25 | @property (nonatomic, assign) CGFloat fromValueForRadius; 26 | 27 | /** 28 | * The default value of this property is @c 0.45. 29 | */ 30 | @property (nonatomic, assign) CGFloat fromValueForAlpha; 31 | 32 | /** 33 | * The value of this property should be ranging from @c 0 to @c 1 (exclusive). 34 | * 35 | * The default value of this property is @c 0.2. 36 | */ 37 | @property (nonatomic, assign) CGFloat keyTimeForHalfOpacity; 38 | 39 | /** 40 | * The animation duration in seconds. 41 | * 42 | * The default value of this property is @c 3. 43 | */ 44 | @property (nonatomic, assign) NSTimeInterval animationDuration; 45 | 46 | /** 47 | * The animation interval in seconds. 48 | * 49 | * The default value of this property is @c 0. 50 | */ 51 | @property (nonatomic, assign) NSTimeInterval pulseInterval; 52 | 53 | /** 54 | * The default value of this property is @c INFINITY. 55 | */ 56 | @property (nonatomic, assign) float repeatCount; 57 | 58 | /** 59 | * The default value of this property is @c YES. 60 | */ 61 | @property (nonatomic, assign) BOOL useTimingFunction; 62 | 63 | - (id)initWithRepeatCount:(float)repeatCount; 64 | -(void)startAnimation; 65 | -(void)stopAnimation; 66 | @end 67 | -------------------------------------------------------------------------------- /CCTextFieldEffects/CCTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // CCTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/25/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "CCTextField.h" 10 | 11 | @implementation CCTextField 12 | 13 | #pragma mark - Custom accessorys 14 | - (void)setCursorColor:(UIColor *)cursorColor { 15 | _cursorColor = cursorColor; 16 | 17 | self.tintColor = cursorColor; 18 | } 19 | 20 | #pragma mark - Lifecycle 21 | - (instancetype)initWithFrame:(CGRect)frame { 22 | self = [super initWithFrame:frame]; 23 | 24 | if (self) { 25 | self.font = [UIFont boldSystemFontOfSize:self.font.pointSize]; 26 | } 27 | 28 | return self; 29 | } 30 | 31 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 32 | if ((self = [super initWithCoder:aDecoder])) { 33 | self.font = [UIFont boldSystemFontOfSize:self.font.pointSize]; 34 | } 35 | return self; 36 | } 37 | 38 | - (void)dealloc { 39 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 40 | } 41 | 42 | #pragma mark - Public methods 43 | - (void)animateViewsForTextEntry { 44 | NSAssert(NO, @"%@ must be overridden", NSStringFromSelector(_cmd)); 45 | } 46 | 47 | - (void)animateViewsForTextDisplay { 48 | NSAssert(NO, @"%@ must be overridden", NSStringFromSelector(_cmd)); 49 | } 50 | 51 | - (void)updateViewsForBoundsChange:(CGRect)bounds { 52 | NSAssert(NO, @"%@ must be overridden", NSStringFromSelector(_cmd)); 53 | } 54 | 55 | #pragma mark - Overridden methods 56 | - (void)drawPlaceholderInRect:(CGRect)rect { 57 | // Don't draw any placeholders. 58 | } 59 | 60 | - (void)willMoveToSuperview:(UIView *)newSuperview { 61 | if (newSuperview != nil) { 62 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(animateViewsForTextEntry) name:UITextFieldTextDidBeginEditingNotification object:self]; 63 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(animateViewsForTextDisplay) name:UITextFieldTextDidEndEditingNotification object:self]; 64 | } 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /CCTextFieldEffectsDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/25/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // 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. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /CCTextFieldEffectsDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/25/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "DetailViewController.h" 11 | 12 | @interface ViewController () 13 | 14 | @property (copy, nonatomic) NSMutableArray *effects; 15 | 16 | @end 17 | 18 | @implementation ViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | // Do any additional setup after loading the view, typically from a nib. 23 | 24 | NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"effects" ofType:@"json"]; 25 | NSData *jsonData = [NSData dataWithContentsOfFile:jsonPath]; 26 | NSError *error; 27 | self.effects = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error]; 28 | self.tableView.backgroundColor = [UIColor colorWithRed:0.9765 green:0.9686 blue:0.9647 alpha:1.0]; 29 | } 30 | 31 | #pragma mark - UITableViewDataSource 32 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 33 | return 1; 34 | } 35 | 36 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 37 | return [self.effects count]; 38 | } 39 | 40 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 41 | UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"Cell"]; 42 | cell.textLabel.text = [[self.effects objectAtIndex:indexPath.row] objectForKey:@"title"]; 43 | 44 | return cell; 45 | } 46 | 47 | #pragma mark - UITableViewDelegate 48 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 49 | [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; 50 | 51 | DetailViewController *DVC =[[DetailViewController alloc] init]; 52 | DVC.title = [[self.effects objectAtIndex:indexPath.row] objectForKey:@"title"]; 53 | DVC.red = [[[[self.effects objectAtIndex:indexPath.row] objectForKey:@"backgroundColor"] objectAtIndex:0] floatValue]; 54 | DVC.green = [[[[self.effects objectAtIndex:indexPath.row] objectForKey:@"backgroundColor"] objectAtIndex:1] floatValue]; 55 | DVC.blue = [[[[self.effects objectAtIndex:indexPath.row] objectForKey:@"backgroundColor"] objectAtIndex:2] floatValue]; 56 | 57 | [self.navigationController pushViewController:DVC animated:YES]; 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /CCTextFieldEffects.xcodeproj/xcshareddata/xcschemes/CCTextFieldEffects.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /CCTextFieldEffects/PulsingHaloLayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // PulsingHaloLayer.m 3 | // https://github.com/shu223/PulsingHalo 4 | // 5 | // Created by shuichi on 12/5/13. 6 | // Copyright (c) 2013 Shuichi Tsutsumi. All rights reserved. 7 | // 8 | // Inspired by https://github.com/samvermette/SVPulsingAnnotationView 9 | 10 | 11 | #import "PulsingHaloLayer.h" 12 | 13 | 14 | @interface PulsingHaloLayer () 15 | @property (nonatomic, strong) CAAnimationGroup *animationGroup; 16 | @end 17 | 18 | 19 | @implementation PulsingHaloLayer 20 | @dynamic repeatCount; 21 | 22 | - (id)initWithRepeatCount:(float) repeatCount 23 | { 24 | self = [super init]; 25 | if (self) { 26 | self.contentsScale = [UIScreen mainScreen].scale; 27 | self.opacity = 0; 28 | 29 | // default 30 | self.radius = 60; 31 | self.fromValueForRadius = 0.0; 32 | self.fromValueForAlpha = 0.45; 33 | self.keyTimeForHalfOpacity = 0.2; 34 | self.animationDuration = 1.0; 35 | self.pulseInterval = 0; 36 | self.repeatCount = 1; 37 | self.backgroundColor = [[UIColor colorWithRed:0.000 green:0.478 blue:1.000 alpha:1] CGColor]; 38 | self.useTimingFunction = YES; 39 | 40 | // dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { 41 | // 42 | // 43 | // 44 | // if(self.pulseInterval != INFINITY) { 45 | // 46 | // dispatch_async(dispatch_get_main_queue(), ^(void) { 47 | // 48 | // [self addAnimation:self.animationGroup forKey:@"pulse"]; 49 | // }); 50 | // } 51 | // }); 52 | } 53 | return self; 54 | 55 | } 56 | 57 | - (id)init { 58 | return [self initWithRepeatCount:INFINITY]; 59 | } 60 | 61 | - (void)setRadius:(CGFloat)radius { 62 | 63 | // _radius = radius; 64 | // 65 | // CGPoint tempPos = self.position; 66 | // 67 | // CGFloat diameter = self.radius * 2; 68 | // 69 | // self.bounds = CGRectMake(0, 0, diameter, diameter); 70 | // self.cornerRadius =0; 71 | // self.position = tempPos; 72 | } 73 | 74 | - (void)setupAnimationGroup { 75 | 76 | self.animationGroup = [CAAnimationGroup animation]; 77 | self.animationGroup.duration = self.animationDuration + self.pulseInterval; 78 | self.animationGroup.repeatCount = self.repeatCount; 79 | self.animationGroup.removedOnCompletion = NO; 80 | if (self.useTimingFunction) { 81 | CAMediaTimingFunction *defaultCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]; 82 | self.animationGroup.timingFunction = defaultCurve; 83 | } 84 | 85 | CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale.xy"]; 86 | scaleAnimation.fromValue = @(1); 87 | scaleAnimation.toValue = @5.5; 88 | scaleAnimation.duration = self.animationDuration; 89 | 90 | CAKeyframeAnimation *opacityAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"]; 91 | opacityAnimation.duration = self.animationDuration; 92 | opacityAnimation.values = @[@(self.fromValueForAlpha), @0.6, @0]; 93 | opacityAnimation.keyTimes = @[@0, @(self.keyTimeForHalfOpacity), @1]; 94 | opacityAnimation.removedOnCompletion = NO; 95 | 96 | NSArray *animations = @[scaleAnimation, opacityAnimation]; 97 | 98 | self.animationGroup.animations = animations; 99 | self.animationGroup.delegate = self; 100 | } 101 | 102 | 103 | -(void)startAnimation{ 104 | [self setupAnimationGroup]; 105 | [self addAnimation:self.animationGroup forKey:@"pulse"]; 106 | } 107 | 108 | -(void)stopAnimation{ 109 | [self removeAllAnimations]; 110 | } 111 | 112 | // ============================================================================= 113 | #pragma mark - CAAnimation Delegate 114 | 115 | //- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { 116 | // 117 | // if (flag) { 118 | // [self removeAllAnimations]; 119 | // [self removeFromSuperlayer]; 120 | // } 121 | //} 122 | 123 | @end 124 | -------------------------------------------------------------------------------- /CCTextFieldEffects/HideoTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // HideoTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/27/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "HideoTextField.h" 10 | 11 | @interface HideoTextField () 12 | 13 | @property (strong, nonatomic) UIView *imageContainerView; 14 | @property (strong, nonatomic) UIImageView *imageView; 15 | 16 | @end 17 | 18 | @implementation HideoTextField 19 | 20 | #pragma mark - Constants 21 | static CGPoint const textFieldInsets = {6 ,0}; 22 | 23 | #pragma mark - Custom accessorys 24 | - (void)setImageContainerColor:(UIColor *)imageContainerColor { 25 | _imageContainerColor = imageContainerColor; 26 | 27 | self.imageContainerView.backgroundColor = imageContainerColor; 28 | } 29 | 30 | - (void)setImage:(UIImage *)image { 31 | _image = image; 32 | 33 | self.imageView.image = image; 34 | } 35 | 36 | #pragma mark - Lifecycle 37 | - (instancetype)initWithFrame:(CGRect)frame { 38 | self = [super initWithFrame:frame]; 39 | 40 | if (self) { 41 | [self commonInit]; 42 | } 43 | 44 | return self; 45 | } 46 | 47 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 48 | self = [super initWithCoder:aDecoder]; 49 | 50 | if (self) { 51 | [self commonInit]; 52 | } 53 | return self; 54 | } 55 | 56 | - (void) commonInit { 57 | self.imageContainerView = [[UIView alloc] init]; 58 | self.imageView = [[UIImageView alloc] init]; 59 | 60 | self.imageContainerColor = [UIColor colorWithRed:0.5373 green:0.6157 blue:0.8549 alpha:1.0]; 61 | self.imageView.backgroundColor = [UIColor clearColor]; 62 | self.backgroundColor = [UIColor whiteColor]; 63 | self.cursorColor = [UIColor colorWithRed:0.6667 green:0.6667 blue:0.6667 alpha:1.0]; 64 | self.textColor = self.cursorColor; 65 | 66 | self.imageScale = 0.7; 67 | } 68 | 69 | #pragma mark - Overridden methods 70 | - (void)drawRect:(CGRect)rect { 71 | self.imageContainerView.frame = CGRectMake(0, 0, CGRectGetHeight(rect), CGRectGetHeight(rect)); 72 | [self addSubview:self.imageContainerView]; 73 | 74 | self.imageView.frame = CGRectMake(0, 0, CGRectGetWidth(self.imageContainerView.frame)/3, CGRectGetHeight(self.imageContainerView.frame)/3); 75 | self.imageView.center = self.imageContainerView.center; 76 | [self.imageContainerView addSubview:self.imageView]; 77 | } 78 | 79 | - (CGRect)editingRectForBounds:(CGRect)bounds { 80 | CGRect frame = CGRectMake(CGRectGetWidth(self.imageContainerView.frame), 0, CGRectGetWidth(bounds)-CGRectGetWidth(self.imageContainerView.frame), CGRectGetHeight(bounds)); 81 | 82 | return CGRectInset(frame, textFieldInsets.x, textFieldInsets.y); 83 | } 84 | 85 | - (CGRect)textRectForBounds:(CGRect)bounds { 86 | CGRect frame = CGRectMake(CGRectGetWidth(self.imageContainerView.frame), 0, CGRectGetWidth(bounds)-CGRectGetWidth(self.imageContainerView.frame), CGRectGetHeight(bounds)); 87 | 88 | return CGRectInset(frame, textFieldInsets.x, textFieldInsets.y); 89 | } 90 | 91 | - (void)animateViewsForTextEntry { 92 | if ([self isFirstResponder] && self.text.length == 0) { 93 | // Prevent cursor display in front of the container view when animating. 94 | [self bringSubviewToFront:self.imageContainerView]; 95 | 96 | [UIView animateWithDuration:0.27 animations:^{ 97 | self.imageContainerView.frame = CGRectMake(0, 0, CGRectGetWidth(self.imageContainerView.frame)*0.67, CGRectGetHeight(self.imageContainerView.frame)); 98 | self.imageView.transform = CGAffineTransformMakeScale(self.imageScale, self.imageScale); 99 | self.imageView.center = self.imageContainerView.center; 100 | } completion:^(BOOL finished) { 101 | if (self.didBeginEditingHandler != nil) { 102 | self.didBeginEditingHandler(); 103 | } 104 | }]; 105 | } 106 | } 107 | 108 | - (void)animateViewsForTextDisplay { 109 | if (self.text.length == 0) { 110 | [UIView animateWithDuration:0.27 animations:^{ 111 | self.imageContainerView.frame = CGRectMake(0, 0, CGRectGetHeight(self.frame), CGRectGetHeight(self.imageContainerView.frame)); 112 | self.imageView.transform = CGAffineTransformIdentity; 113 | self.imageView.center = self.imageContainerView.center; 114 | } completion:^(BOOL finished) { 115 | if (self.didEndEditingHandler != nil) { 116 | self.didEndEditingHandler(); 117 | } 118 | }]; 119 | } 120 | } 121 | 122 | #pragma mark - Private methods 123 | 124 | @end 125 | -------------------------------------------------------------------------------- /CCTextFieldEffects/KohanaTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // KohanaTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 7/1/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "KohanaTextField.h" 10 | 11 | @interface KohanaTextField () 12 | 13 | @property (strong, nonatomic) UIImageView *imageView; 14 | 15 | @end 16 | 17 | @implementation KohanaTextField 18 | 19 | #pragma mark - Constants 20 | static CGPoint const placeholderInsets = {0, 0}; 21 | static CGPoint const textFieldInsets = {6, 0}; 22 | 23 | #pragma mark - Custom accessorys 24 | - (void)setPlaceholderColor:(UIColor *)placeholderColor { 25 | _placeholderColor = placeholderColor; 26 | 27 | self.placeholderLabel.textColor = placeholderColor; 28 | [self.imageView setTintColor:placeholderColor]; 29 | } 30 | 31 | - (void)setImage:(UIImage *)image { 32 | _image = image; 33 | 34 | self.imageView.image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; 35 | } 36 | 37 | - (void)setPlaceholderFontScale:(CGFloat)placeholderFontScale { 38 | _placeholderFontScale = placeholderFontScale; 39 | 40 | self.placeholderLabel.font = [self placeholderFontFromFont:self.font]; 41 | } 42 | 43 | - (void)setPlaceholder:(NSString *)placeholder { 44 | [super setPlaceholder:placeholder]; 45 | 46 | self.placeholderLabel.text = placeholder; 47 | } 48 | 49 | #pragma mark - Lifecycle 50 | - (instancetype)initWithFrame:(CGRect)frame { 51 | self = [super initWithFrame:frame]; 52 | 53 | if (self) { 54 | [self commonInit]; 55 | } 56 | 57 | return self; 58 | } 59 | 60 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 61 | self = [super initWithCoder:aDecoder]; 62 | 63 | if (self) { 64 | [self commonInit]; 65 | } 66 | return self; 67 | } 68 | 69 | - (void) commonInit { 70 | self.placeholderLabel = [[UILabel alloc] init]; 71 | self.imageView = [[UIImageView alloc] init]; 72 | 73 | self.placeholderColor = [UIColor colorWithRed:0.8235 green:0.8235 blue:0.8235 alpha:1]; 74 | self.cursorColor = [UIColor colorWithRed:0.4157 green:0.4745 blue:0.5373 alpha:1]; 75 | self.textColor = self.cursorColor; 76 | self.backgroundColor = [UIColor whiteColor]; 77 | 78 | self.placeholderFontScale = 0.8; 79 | } 80 | 81 | #pragma mark - Overridden methods 82 | - (void)drawRect:(CGRect)rect { 83 | CGFloat length = CGRectGetHeight(rect); 84 | 85 | self.imageView.frame = CGRectInset(CGRectMake(-length, 0, length, length), length*0.25, length*0.25); 86 | self.imageView.transform = CGAffineTransformMakeScale(0.7, 0.7); 87 | [self addSubview:self.imageView]; 88 | 89 | CGRect frame = CGRectMake(0, 0, CGRectGetWidth(rect), length);; 90 | self.placeholderLabel.frame = CGRectInset(frame, length*0.3, placeholderInsets.y); 91 | [self addSubview:self.placeholderLabel]; 92 | } 93 | 94 | 95 | - (CGRect)textRectForBounds:(CGRect)bounds { 96 | CGFloat length = CGRectGetHeight(self.bounds); 97 | 98 | CGRect rect = CGRectOffset(bounds, length+textFieldInsets.x, 0); 99 | return CGRectMake(rect.origin.x, rect.origin.y, CGRectGetWidth(rect)-2*textFieldInsets.x-length, CGRectGetHeight(rect)); 100 | } 101 | 102 | - (CGRect)editingRectForBounds:(CGRect)bounds { 103 | CGFloat length = CGRectGetHeight(self.bounds); 104 | 105 | CGRect rect = CGRectOffset(bounds, length+textFieldInsets.x, 0); 106 | return CGRectMake(rect.origin.x, rect.origin.y, CGRectGetWidth(rect)-2*textFieldInsets.x-length, CGRectGetHeight(rect)); 107 | } 108 | 109 | - (void)animateViewsForTextEntry { 110 | if (self.text.length == 0) { 111 | [UIView animateWithDuration:0.25 animations:^{ 112 | CGFloat length = CGRectGetHeight(self.bounds); 113 | 114 | self.imageView.frame = CGRectOffset(self.imageView.frame, length, 0); 115 | self.placeholderLabel.frame = CGRectOffset(self.placeholderLabel.frame, length, 0); 116 | self.placeholderLabel.alpha = 0; 117 | } completion:^(BOOL finished) { 118 | 119 | }]; 120 | } 121 | } 122 | 123 | - (void)animateViewsForTextDisplay { 124 | if (self.text.length == 0) { 125 | [UIView animateWithDuration:0.24 animations:^{ 126 | CGFloat length = CGRectGetHeight(self.bounds); 127 | 128 | self.imageView.frame = CGRectOffset(self.imageView.frame, -length, 0); 129 | self.placeholderLabel.frame = CGRectOffset(self.placeholderLabel.frame, -length, 0); 130 | self.placeholderLabel.alpha = 1; 131 | } completion:^(BOOL finished) { 132 | 133 | }]; 134 | } 135 | } 136 | 137 | #pragma mark - Private methods 138 | - (UIFont *)placeholderFontFromFont:(UIFont *)font { 139 | UIFont *smallerFont = [UIFont fontWithName:font.fontName size:font.pointSize*self.placeholderFontScale]; 140 | 141 | return smallerFont; 142 | } 143 | 144 | @end 145 | -------------------------------------------------------------------------------- /CCTextFieldEffects/AkiraTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // AkiraTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/25/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "AkiraTextField.h" 10 | 11 | @interface AkiraTextField () 12 | 13 | @property (strong, nonatomic) CALayer *borderLayer; 14 | @property (nonatomic) CGFloat placeholderHeight; 15 | 16 | @end 17 | 18 | @implementation AkiraTextField 19 | 20 | #pragma mark - Constants 21 | static CGFloat const activeSize = 1.2; 22 | static CGFloat const inactiveSize = 2.5; 23 | static CGPoint const textFieldInsets = {6, 0}; 24 | static CGPoint const placeHolderInsets = {6, 0}; 25 | 26 | #pragma mark - Custom accessorys 27 | - (void)setBorderColor:(UIColor *)borderColor { 28 | _borderColor = borderColor; 29 | 30 | [self updateBorder]; 31 | } 32 | 33 | - (void)setPlaceholderColor:(UIColor *)placeholderColor { 34 | _placeholderColor = placeholderColor; 35 | 36 | [self updatePlaceholder]; 37 | } 38 | 39 | - (void)setPlaceholderFontScale:(CGFloat)placeholderFontScale { 40 | _placeholderFontScale = placeholderFontScale; 41 | 42 | [self updatePlaceholder]; 43 | } 44 | 45 | - (void)setPlaceholder:(NSString *)placeholder { 46 | [super setPlaceholder:placeholder]; 47 | 48 | [self updatePlaceholder]; 49 | } 50 | 51 | - (void)setBounds:(CGRect)bounds { 52 | [super setBounds:bounds]; 53 | 54 | [self updateBorder]; 55 | } 56 | 57 | - (CGFloat)placeholderHeight { 58 | return placeHolderInsets.y + [self placeholderFontFromFont:self.font].lineHeight; 59 | } 60 | 61 | #pragma mark - Lifecycle 62 | - (instancetype)initWithFrame:(CGRect)frame { 63 | self = [super initWithFrame:frame]; 64 | 65 | if (self) { 66 | [self commonInit]; 67 | } 68 | 69 | return self; 70 | } 71 | 72 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 73 | self = [super initWithCoder:aDecoder]; 74 | 75 | if (self) { 76 | [self commonInit]; 77 | } 78 | return self; 79 | } 80 | 81 | - (void) commonInit { 82 | self.borderLayer = [[CALayer alloc] init]; 83 | self.placeholderLabel = [[UILabel alloc] init]; 84 | 85 | self.borderColor = [UIColor colorWithRed:0.4118 green:0.4157 blue:0.4314 alpha:1.0]; 86 | self.placeholderColor = [UIColor colorWithRed:0.8 green:0.3765 blue:0.3333 alpha:1.0]; 87 | self.cursorColor = self.borderColor; 88 | self.textColor = [UIColor colorWithRed:0.6667 green:0.6667 blue:0.6667 alpha:1.0]; 89 | 90 | self.placeholderFontScale = 0.7; 91 | } 92 | 93 | #pragma mark - Overridden methods 94 | - (void)drawRect:(CGRect)rect { 95 | [self updateBorder]; 96 | [self updatePlaceholder]; 97 | 98 | [self addSubview:self.placeholderLabel]; 99 | [self.layer addSublayer:self.borderLayer]; 100 | } 101 | 102 | - (CGRect)placeholderRectForBounds:(CGRect)bounds { 103 | if ([self isFirstResponder] || self.text.length!=0) { 104 | return CGRectMake(placeHolderInsets.x, placeHolderInsets.y, bounds.size.width, self.placeholderHeight); 105 | } else { 106 | return [self textRectForBounds:bounds]; 107 | } 108 | } 109 | 110 | - (CGRect)editingRectForBounds:(CGRect)bounds { 111 | return [self textRectForBounds:bounds]; 112 | } 113 | 114 | - (CGRect)textRectForBounds:(CGRect)bounds { 115 | return CGRectOffset(bounds, textFieldInsets.x, textFieldInsets.y+self.placeholderHeight/2); 116 | } 117 | 118 | - (void)animateViewsForTextEntry { 119 | [UIView animateWithDuration:0.35 animations:^{ 120 | [self updateBorder]; 121 | [self updatePlaceholder]; 122 | } completion:^(BOOL finished) { 123 | if (self.didBeginEditingHandler != nil) { 124 | self.didBeginEditingHandler(); 125 | } 126 | }]; 127 | } 128 | 129 | - (void)animateViewsForTextDisplay { 130 | [UIView animateWithDuration:0.35 animations:^{ 131 | [self updateBorder]; 132 | [self updatePlaceholder]; 133 | } completion:^(BOOL finished) { 134 | if (self.didEndEditingHandler != nil) { 135 | self.didEndEditingHandler(); 136 | } 137 | }]; 138 | } 139 | 140 | #pragma mark - Private methods 141 | - (void)updateBorder { 142 | self.borderLayer.frame = [self rectForBounds:self.bounds]; 143 | self.borderLayer.borderWidth = ([self isFirstResponder] || self.text.length!=0)?activeSize:inactiveSize; 144 | self.borderLayer.borderColor = self.borderColor.CGColor; 145 | } 146 | 147 | - (void)updatePlaceholder { 148 | self.placeholderLabel.frame = [self placeholderRectForBounds:self.bounds]; 149 | self.placeholderLabel.text = self.placeholder; 150 | self.placeholderLabel.font = [self placeholderFontFromFont:self.font]; 151 | self.placeholderLabel.textColor = self.placeholderColor; 152 | } 153 | 154 | - (UIFont *)placeholderFontFromFont:(UIFont *)font { 155 | UIFont *smallerFont = [UIFont fontWithName:font.fontName size:font.pointSize*self.placeholderFontScale]; 156 | 157 | return smallerFont; 158 | } 159 | 160 | - (CGRect)rectForBounds:(CGRect)bounds { 161 | return CGRectMake(bounds.origin.x, bounds.origin.y+self.placeholderHeight, bounds.size.width, bounds.size.height-self.placeholderHeight); 162 | } 163 | 164 | @end 165 | -------------------------------------------------------------------------------- /CCTextFieldEffectsDemo/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 | 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 | -------------------------------------------------------------------------------- /CCTextFieldEffects/KaedeTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // KaedeTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/26/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "KaedeTextfield.h" 10 | 11 | @interface KaedeTextField () 12 | 13 | @property (strong, nonatomic) UIView *foregroundView; 14 | 15 | @end 16 | 17 | @implementation KaedeTextField 18 | 19 | #pragma mark - Constants 20 | static CGPoint const textFieldInsets = {10, 0}; 21 | static CGPoint const placeholderInsets = {10, 5}; 22 | 23 | #pragma mark - Custom accessorys 24 | - (void)setPlaceholderColor:(UIColor *)placeholderColor { 25 | _placeholderColor = placeholderColor; 26 | 27 | [self updatePlaceholder]; 28 | } 29 | 30 | - (void)setForegroundColor:(UIColor *)foregroundColor { 31 | _foregroundColor = foregroundColor; 32 | 33 | [self updateForegroundColor]; 34 | } 35 | 36 | - (void)setPlaceholderFontScale:(CGFloat)placeholderFontScale { 37 | _placeholderFontScale = placeholderFontScale; 38 | 39 | [self updatePlaceholder]; 40 | } 41 | 42 | - (void)setPlaceholder:(NSString *)placeholder { 43 | [super setPlaceholder:placeholder]; 44 | 45 | [self updatePlaceholder]; 46 | } 47 | 48 | - (void)setBounds:(CGRect)bounds { 49 | [super setBounds:bounds]; 50 | 51 | [self drawRect:bounds]; 52 | } 53 | 54 | #pragma mark - Lifecycle 55 | - (instancetype)initWithFrame:(CGRect)frame { 56 | self = [super initWithFrame:frame]; 57 | 58 | if (self) { 59 | [self commonInit]; 60 | } 61 | 62 | return self; 63 | } 64 | 65 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 66 | self = [super initWithCoder:aDecoder]; 67 | 68 | if (self) { 69 | [self commonInit]; 70 | } 71 | return self; 72 | } 73 | 74 | - (void) commonInit { 75 | self.foregroundView = [[UIView alloc] init]; 76 | self.placeholderLabel = [[UILabel alloc] init]; 77 | 78 | self.placeholderColor = [UIColor colorWithRed:0.4157 green:0.4745 blue:0.5373 alpha:1.0]; 79 | self.foregroundColor = [UIColor colorWithRed:0.9373 green:0.9333 blue:0.9333 alpha:1.0]; 80 | self.cursorColor = [UIColor colorWithRed:0.6157 green:0.6706 blue:0.7294 alpha:1.0]; 81 | self.textColor = self.cursorColor; 82 | self.backgroundColor = [UIColor whiteColor]; 83 | 84 | self.placeholderFontScale = 0.8; 85 | } 86 | 87 | #pragma mark - Overridden methos 88 | - (void)drawRect:(CGRect)rect { 89 | CGRect frame = CGRectMake(0, 0, CGRectGetWidth(rect), CGRectGetHeight(rect)); 90 | 91 | self.foregroundView.frame = frame; 92 | self.foregroundView.userInteractionEnabled = NO; 93 | self.placeholderLabel.frame = CGRectInset(frame, placeholderInsets.x, placeholderInsets.y); 94 | self.placeholderLabel.font = [self placeholderFontFromFont:self.font]; 95 | 96 | [self updateForegroundColor]; 97 | [self updatePlaceholder]; 98 | 99 | if (self.text.length!=0 || [self isFirstResponder]) { 100 | [self animateViewsForTextEntry]; 101 | } 102 | 103 | [self addSubview:self.foregroundView]; 104 | [self addSubview:self.placeholderLabel]; 105 | } 106 | 107 | - (CGRect)editingRectForBounds:(CGRect)bounds { 108 | CGRect frame = CGRectMake(bounds.origin.x, bounds.origin.y, CGRectGetWidth(bounds)*0.6, CGRectGetHeight(bounds)); 109 | 110 | return CGRectInset(frame, textFieldInsets.x, textFieldInsets.y); 111 | } 112 | 113 | - (CGRect)textRectForBounds:(CGRect)bounds { 114 | CGRect frame = CGRectMake(bounds.origin.x, bounds.origin.y, CGRectGetWidth(bounds)*0.6, CGRectGetHeight(bounds)); 115 | 116 | return CGRectInset(frame, textFieldInsets.x, textFieldInsets.y); 117 | } 118 | 119 | - (void)animateViewsForTextEntry { 120 | [UIView animateWithDuration:0.16 animations:^{ 121 | self.placeholderLabel.frame = CGRectMake(CGRectGetWidth(self.frame)*0.7, placeholderInsets.y, CGRectGetWidth(self.placeholderLabel.frame), CGRectGetHeight(self.placeholderLabel.frame)); 122 | }]; 123 | 124 | [UIView animateWithDuration:0.22 animations:^{ 125 | self.foregroundView.frame = CGRectMake(CGRectGetWidth(self.frame)*0.65, 0, CGRectGetWidth(self.foregroundView.frame), CGRectGetHeight(self.foregroundView.frame)); 126 | } completion:^(BOOL finished) { 127 | if (self.didBeginEditingHandler != nil) { 128 | self.didBeginEditingHandler(); 129 | } 130 | }]; 131 | } 132 | 133 | - (void)animateViewsForTextDisplay { 134 | if (self.text.length == 0) { 135 | [UIView animateWithDuration:0.3 animations:^{ 136 | self.placeholderLabel.frame = CGRectMake(placeholderInsets.x, placeholderInsets.y, CGRectGetWidth(self.placeholderLabel.frame), CGRectGetHeight(self.placeholderLabel.frame)); 137 | }]; 138 | 139 | [UIView animateWithDuration:0.3 animations:^{ 140 | self.foregroundView.frame = CGRectMake(0, 0, CGRectGetWidth(self.foregroundView.frame), CGRectGetHeight(self.foregroundView.frame)); 141 | } completion:^(BOOL finished) { 142 | if (self.didEndEditingHandler != nil) { 143 | self.didEndEditingHandler(); 144 | } 145 | }]; 146 | } 147 | } 148 | 149 | #pragma mark - Private methos 150 | - (void)updatePlaceholder { 151 | self.placeholderLabel.text = self.placeholder; 152 | self.placeholderLabel.textColor = self.placeholderColor; 153 | } 154 | 155 | - (void)updateForegroundColor { 156 | self.foregroundView.backgroundColor = self.foregroundColor; 157 | } 158 | 159 | - (UIFont *)placeholderFontFromFont:(UIFont *)font { 160 | UIFont *smallerFont = [UIFont fontWithName:font.fontName size:font.pointSize*self.placeholderFontScale]; 161 | 162 | return smallerFont; 163 | } 164 | 165 | @end 166 | -------------------------------------------------------------------------------- /CCTextFieldEffects/HarukiTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // HarukiTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/28/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "HarukiTextField.h" 10 | 11 | @interface HarukiTextField () 12 | 13 | @property (strong, nonatomic) CALayer *upperLayer; 14 | @property (strong, nonatomic) CALayer *lowerLayer; 15 | @property (nonatomic) CGFloat placeholderHeight; 16 | 17 | @end 18 | 19 | @implementation HarukiTextField 20 | 21 | #pragma mark - Constants 22 | static CGFloat const borderSize = 3; 23 | static CGFloat const borderMoveDistance = 8; 24 | static CGPoint const textFieldInsets = {8, 0}; 25 | static CGPoint const placeHolderInsets = {8, 0}; 26 | 27 | #pragma mark - Custom accessorys 28 | - (void)setBorderColor:(UIColor *)borderColor { 29 | _borderColor = borderColor; 30 | 31 | self.upperLayer.borderColor = borderColor.CGColor; 32 | self.lowerLayer.borderColor = borderColor.CGColor; 33 | } 34 | 35 | - (void)setPlaceholderColor:(UIColor *)placeholderColor { 36 | _placeholderColor = placeholderColor; 37 | 38 | self.placeholderLabel.textColor = placeholderColor; 39 | } 40 | 41 | - (void)setPlaceholderFontScale:(CGFloat)placeholderFontScale { 42 | _placeholderFontScale = placeholderFontScale; 43 | 44 | self.placeholderLabel.font = [self placeholderFontFromFont:self.font]; 45 | } 46 | 47 | - (void)setPlaceholder:(NSString *)placeholder { 48 | [super setPlaceholder:placeholder]; 49 | 50 | self.placeholderLabel.text = placeholder; 51 | } 52 | 53 | - (CGFloat)placeholderHeight { 54 | return placeHolderInsets.y + [self placeholderFontFromFont:self.font].lineHeight; 55 | } 56 | 57 | #pragma mark - Liftcycle 58 | - (instancetype)initWithFrame:(CGRect)frame { 59 | self = [super initWithFrame:frame]; 60 | 61 | if (self) { 62 | [self commonInit]; 63 | } 64 | 65 | return self; 66 | } 67 | 68 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 69 | self = [super initWithCoder:aDecoder]; 70 | 71 | if (self) { 72 | [self commonInit]; 73 | } 74 | return self; 75 | } 76 | 77 | - (void) commonInit { 78 | self.upperLayer = [[CALayer alloc] init]; 79 | self.upperLayer.borderWidth = borderSize; 80 | 81 | self.lowerLayer = [[CALayer alloc] init]; 82 | self.lowerLayer.borderWidth = borderSize; 83 | 84 | self.placeholderLabel = [[UILabel alloc] init]; 85 | 86 | self.borderColor = [UIColor colorWithRed:0.4147 green:0.4745 blue:0.5373 alpha:1]; 87 | self.placeholderColor = self.borderColor; 88 | self.cursorColor = [UIColor colorWithRed:0.6863 green:0.7098 blue:0.7333 alpha:1]; 89 | self.textColor = self.cursorColor; 90 | 91 | self.placeholderFontScale = 0.75; 92 | } 93 | 94 | #pragma mark - Overridden methods 95 | - (void)drawRect:(CGRect)rect { 96 | self.upperLayer.frame = CGRectMake(0, self.placeholderHeight+borderMoveDistance, CGRectGetWidth(self.bounds), borderSize); 97 | [self.layer addSublayer:self.upperLayer]; 98 | 99 | self.lowerLayer.frame = CGRectMake(0, CGRectGetHeight(self.bounds)-borderSize-borderMoveDistance, CGRectGetWidth(self.bounds), borderSize); 100 | [self.layer addSublayer:self.lowerLayer]; 101 | 102 | self.placeholderLabel.frame = [self placeholderRectForBounds:self.bounds]; 103 | [self addSubview:self.placeholderLabel]; 104 | } 105 | 106 | - (CGRect)placeholderRectForBounds:(CGRect)bounds { 107 | if ([self isFirstResponder] || self.text.length!=0) { 108 | return CGRectMake(placeHolderInsets.x, placeHolderInsets.y, bounds.size.width, self.placeholderHeight); 109 | } else { 110 | return [self textRectForBounds:bounds]; 111 | } 112 | } 113 | 114 | - (CGRect)editingRectForBounds:(CGRect)bounds { 115 | return [self textRectForBounds:bounds]; 116 | } 117 | 118 | - (CGRect)textRectForBounds:(CGRect)bounds { 119 | return CGRectOffset(bounds, textFieldInsets.x, textFieldInsets.y+self.placeholderHeight/2); 120 | } 121 | 122 | - (void)animateViewsForTextEntry { 123 | if (self.text.length == 0) { 124 | // Hide the cursor when the animating 125 | UIColor *originalCursorColor = self.cursorColor; 126 | self.cursorColor = [UIColor clearColor]; 127 | 128 | [UIView animateWithDuration:0.35 animations:^{ 129 | self.upperLayer.frame = CGRectMake(0, self.placeholderHeight*1.1, CGRectGetWidth(self.bounds), borderSize); 130 | self.lowerLayer.frame = CGRectMake(0, CGRectGetHeight(self.bounds)-borderSize, CGRectGetWidth(self.bounds), borderSize); 131 | self.placeholderLabel.frame = [self placeholderRectForBounds:self.bounds]; 132 | } completion:^(BOOL finished) { 133 | self.cursorColor = originalCursorColor; 134 | 135 | if (self.didBeginEditingHandler != nil) { 136 | self.didBeginEditingHandler(); 137 | } 138 | }]; 139 | } 140 | } 141 | 142 | - (void)animateViewsForTextDisplay { 143 | if (self.text.length == 0) { 144 | [UIView animateWithDuration:0.35 animations:^{ 145 | self.upperLayer.frame = CGRectMake(0, self.placeholderHeight+borderMoveDistance, CGRectGetWidth(self.bounds), borderSize); 146 | self.lowerLayer.frame = CGRectMake(0, CGRectGetHeight(self.bounds)-borderSize-borderMoveDistance, CGRectGetWidth(self.bounds), borderSize); 147 | self.placeholderLabel.frame = [self placeholderRectForBounds:self.bounds]; 148 | } completion:^(BOOL finished) { 149 | if (self.didEndEditingHandler != nil) { 150 | self.didEndEditingHandler(); 151 | } 152 | }]; 153 | } 154 | } 155 | 156 | #pragma mark - Private methods 157 | - (UIFont *)placeholderFontFromFont:(UIFont *)font { 158 | UIFont *smallerFont = [UIFont fontWithName:font.fontName size:font.pointSize*self.placeholderFontScale]; 159 | 160 | return smallerFont; 161 | } 162 | 163 | @end 164 | -------------------------------------------------------------------------------- /CCTextFieldEffects/ChisatoTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // ChisatoTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/29/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "ChisatoTextField.h" 10 | 11 | @interface ChisatoTextField () 12 | 13 | @property (strong, nonatomic) CALayer *borderLayer; 14 | @property (nonatomic) CGFloat placeholderHeight; 15 | 16 | @end 17 | 18 | @implementation ChisatoTextField 19 | 20 | #pragma mark - Constants 21 | static CGFloat const borderSize = 2.5; 22 | static CGPoint const textFieldInsets = {8, 0}; 23 | static CGPoint const placeHolderInsets = {8, 0}; 24 | 25 | #pragma mark - Custom accessorys 26 | - (void)setBorderColor:(UIColor *)borderColor { 27 | _borderColor = borderColor; 28 | 29 | [self updateBorder]; 30 | } 31 | 32 | - (void)setPlaceholderColor:(UIColor *)placeholderColor { 33 | _placeholderColor = placeholderColor; 34 | 35 | [self updatePlaceholder]; 36 | } 37 | 38 | - (void)setPlaceholderFontScale:(CGFloat)placeholderFontScale { 39 | _placeholderFontScale = placeholderFontScale; 40 | 41 | [self updatePlaceholder]; 42 | } 43 | 44 | - (void)setPlaceholder:(NSString *)placeholder { 45 | [super setPlaceholder:placeholder]; 46 | 47 | [self updatePlaceholder]; 48 | } 49 | 50 | - (void)setBounds:(CGRect)bounds { 51 | [super setBounds:bounds]; 52 | 53 | [self updateBorder]; 54 | } 55 | 56 | - (CGFloat)placeholderHeight { 57 | return placeHolderInsets.y + [self placeholderFontFromFont:self.font].lineHeight; 58 | } 59 | 60 | #pragma mark - Lifecycle 61 | - (instancetype)initWithFrame:(CGRect)frame { 62 | self = [super initWithFrame:frame]; 63 | 64 | if (self) { 65 | [self commonInit]; 66 | } 67 | 68 | return self; 69 | } 70 | 71 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 72 | self = [super initWithCoder:aDecoder]; 73 | 74 | if (self) { 75 | [self commonInit]; 76 | } 77 | return self; 78 | } 79 | 80 | - (void) commonInit { 81 | self.borderLayer = [[CALayer alloc] init]; 82 | self.placeholderLabel = [[UILabel alloc] init]; 83 | 84 | self.borderColor = [UIColor colorWithRed:0.7098 green:0.7098 blue:0.7098 alpha:1.0]; 85 | self.placeholderColor = self.borderColor; 86 | self.cursorColor = self.borderColor; 87 | self.textColor = self.borderColor; 88 | self.activeColor = [UIColor colorWithRed:0.8549 green:0.3922 blue:0.5176 alpha:1]; 89 | 90 | self.placeholderFontScale = 0.8; 91 | } 92 | 93 | #pragma mark - Overridden methods 94 | - (void)drawRect:(CGRect)rect { 95 | [self updateBorder]; 96 | [self updatePlaceholder]; 97 | 98 | [self addSubview:self.placeholderLabel]; 99 | [self.layer addSublayer:self.borderLayer]; 100 | } 101 | 102 | - (CGRect)placeholderRectForBounds:(CGRect)bounds { 103 | if ([self isFirstResponder] || self.text.length!=0) { 104 | return CGRectMake(placeHolderInsets.x, placeHolderInsets.y, bounds.size.width, self.placeholderHeight); 105 | } else { 106 | return [self textRectForBounds:bounds]; 107 | } 108 | } 109 | 110 | - (CGRect)editingRectForBounds:(CGRect)bounds { 111 | return [self textRectForBounds:bounds]; 112 | } 113 | 114 | - (CGRect)textRectForBounds:(CGRect)bounds { 115 | return CGRectOffset(bounds, textFieldInsets.x, textFieldInsets.y+self.placeholderHeight/2); 116 | } 117 | 118 | - (void)animateViewsForTextEntry { 119 | if (self.text.length == 0) { 120 | [UIView animateWithDuration:0.1 animations:^{ 121 | self.placeholderLabel.frame = CGRectOffset(self.placeholderLabel.frame, 0, self.placeholderHeight*2); 122 | self.borderLayer.borderColor = self.activeColor.CGColor; 123 | } completion:^(BOOL finished) { 124 | self.placeholderLabel.alpha = 0; 125 | self.placeholderLabel.frame = CGRectOffset([self placeholderRectForBounds:self.bounds], 0, -self.placeholderHeight*2); 126 | [UIView animateWithDuration:0.15 animations:^{ 127 | self.placeholderLabel.textColor = self.activeColor; 128 | self.placeholderLabel.alpha = 1; 129 | self.placeholderLabel.frame = [self placeholderRectForBounds:self.bounds]; 130 | } completion:^(BOOL finished) { 131 | if (self.didBeginEditingHandler != nil) { 132 | self.didBeginEditingHandler(); 133 | } 134 | }]; 135 | }]; 136 | } 137 | } 138 | 139 | - (void)animateViewsForTextDisplay { 140 | if (self.text.length == 0) { 141 | [UIView animateWithDuration:0.15 animations:^{ 142 | self.borderLayer.borderColor = self.borderColor.CGColor; 143 | self.placeholderLabel.alpha = 0; 144 | } completion:^(BOOL finished) { 145 | self.placeholderLabel.textColor = self.placeholderColor; 146 | self.placeholderLabel.frame = [self placeholderRectForBounds:self.bounds]; 147 | self.placeholderLabel.alpha = 1; 148 | if (self.didEndEditingHandler != nil) { 149 | self.didEndEditingHandler(); 150 | } 151 | }]; 152 | } 153 | } 154 | 155 | #pragma mark - Private methods 156 | - (void)updateBorder { 157 | self.borderLayer.frame = [self rectForBounds:self.bounds]; 158 | self.borderLayer.borderWidth = borderSize; 159 | self.borderLayer.borderColor = self.borderColor.CGColor; 160 | } 161 | 162 | - (void)updatePlaceholder { 163 | self.placeholderLabel.frame = [self placeholderRectForBounds:self.bounds]; 164 | self.placeholderLabel.text = self.placeholder; 165 | self.placeholderLabel.font = [self placeholderFontFromFont:self.font]; 166 | self.placeholderLabel.textColor = self.placeholderColor; 167 | } 168 | 169 | - (UIFont *)placeholderFontFromFont:(UIFont *)font { 170 | UIFont *smallerFont = [UIFont fontWithName:font.fontName size:font.pointSize*self.placeholderFontScale]; 171 | 172 | return smallerFont; 173 | } 174 | 175 | - (CGRect)rectForBounds:(CGRect)bounds { 176 | return CGRectMake(bounds.origin.x, bounds.origin.y+self.placeholderHeight, bounds.size.width, bounds.size.height-self.placeholderHeight); 177 | } 178 | 179 | @end 180 | 181 | -------------------------------------------------------------------------------- /CCTextFieldEffects/SaeTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // SaeTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 7/1/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "SaeTextField.h" 10 | 11 | @interface SaeTextField () 12 | 13 | @property (strong, nonatomic) UIImageView *imageView; 14 | @property (strong, nonatomic) UIView *borderView; 15 | 16 | @end 17 | 18 | @implementation SaeTextField 19 | 20 | #pragma mark - Constants 21 | static CGFloat const borderTickness = 2; 22 | static CGPoint const textFieldInset = {0, 6}; 23 | static CGPoint const placeholderInset = {0, 6}; 24 | 25 | #pragma mark - Custom accessorys 26 | - (void)setBorderColor:(UIColor *)borderColor { 27 | _borderColor = borderColor; 28 | 29 | self.borderView.backgroundColor = borderColor; 30 | [self.imageView setTintColor:borderColor]; 31 | } 32 | 33 | - (void)setImage:(UIImage *)image { 34 | _image = image; 35 | 36 | self.imageView.image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; 37 | } 38 | 39 | - (void)setPlaceholderColor:(UIColor *)placeholderColor { 40 | _placeholderColor = placeholderColor; 41 | 42 | self.placeholderLabel.textColor = placeholderColor; 43 | } 44 | 45 | - (void)setPlaceholderFontScale:(CGFloat)placeholderFontScale { 46 | _placeholderFontScale = placeholderFontScale; 47 | 48 | self.placeholderLabel.font = [self placeholderFontFromFont:self.font]; 49 | } 50 | 51 | - (void)setPlaceholder:(NSString *)placeholder { 52 | [super setPlaceholder:placeholder]; 53 | 54 | self.placeholderLabel.text = placeholder; 55 | } 56 | 57 | #pragma mark - Lifecycle 58 | - (instancetype)initWithFrame:(CGRect)frame { 59 | self = [super initWithFrame:frame]; 60 | 61 | if (self) { 62 | [self commonInit]; 63 | } 64 | 65 | return self; 66 | } 67 | 68 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 69 | self = [super initWithCoder:aDecoder]; 70 | 71 | if (self) { 72 | [self commonInit]; 73 | } 74 | return self; 75 | } 76 | 77 | - (void) commonInit { 78 | self.imageView = [[UIImageView alloc] init]; 79 | self.borderView = [[UIView alloc] init]; 80 | self.placeholderLabel = [[UILabel alloc] init]; 81 | 82 | self.borderColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:1]; 83 | self.placeholderColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.4]; 84 | self.cursorColor = self.borderColor; 85 | self.textColor = self.cursorColor; 86 | 87 | self.image = [UIImage imageNamed:@"pencil.png"]; 88 | 89 | self.placeholderFontScale = 0.8; 90 | } 91 | 92 | #pragma mark - Overridden methods 93 | - (void)drawRect:(CGRect)rect { 94 | CGFloat length = self.placeholderLabel.font.lineHeight; 95 | 96 | self.borderView.frame = CGRectMake(CGRectGetWidth(rect), CGRectGetHeight(rect)-borderTickness, CGRectGetWidth(rect), borderTickness); 97 | [self addSubview:self.borderView]; 98 | 99 | self.imageView.frame = CGRectMake(CGRectGetWidth(rect)-length, CGRectGetHeight(rect)-length-borderTickness, length, length); 100 | [self addSubview:self.imageView]; 101 | 102 | self.placeholderLabel.frame = CGRectMake(placeholderInset.x, CGRectGetHeight(rect)-self.placeholderLabel.font.lineHeight-placeholderInset.y-borderTickness, CGRectGetWidth(rect)-length, self.placeholderLabel.font.lineHeight+placeholderInset.y); 103 | [self addSubview:self.placeholderLabel]; 104 | } 105 | 106 | - (CGRect)editingRectForBounds:(CGRect)bounds { 107 | CGRect newBounds = CGRectMake(0, self.placeholderLabel.font.lineHeight+placeholderInset.y, CGRectGetWidth(bounds), CGRectGetHeight(bounds)-self.placeholderLabel.font.lineHeight-placeholderInset.y-borderTickness); 108 | 109 | return CGRectInset(newBounds, textFieldInset.x, textFieldInset.y); 110 | } 111 | 112 | - (CGRect)textRectForBounds:(CGRect)bounds { 113 | CGRect newBounds = CGRectMake(0, self.placeholderLabel.font.lineHeight+placeholderInset.y, CGRectGetWidth(bounds), CGRectGetHeight(bounds)-self.placeholderLabel.font.lineHeight-placeholderInset.y-borderTickness); 114 | 115 | return CGRectInset(newBounds, textFieldInset.x, textFieldInset.y); 116 | } 117 | 118 | - (void)animateViewsForTextEntry { 119 | if (self.text.length == 0) { 120 | self.imageView.layer.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0); 121 | 122 | [UIView animateWithDuration:0.35 animations:^{ 123 | self.placeholderLabel.layer.transform = CATransform3DMakeTranslation(0, -CGRectGetHeight([self textRectForBounds:self.bounds])-placeholderInset.y, 0); 124 | 125 | self.borderView.frame = CGRectOffset(self.borderView.frame, -CGRectGetWidth(self.bounds), 0); 126 | self.imageView.frame = CGRectOffset(self.imageView.frame, -CGRectGetWidth(self.bounds), 0); 127 | } completion:^(BOOL finished) { 128 | if (self.didBeginEditingHandler != nil) { 129 | self.didBeginEditingHandler(); 130 | } 131 | }]; 132 | } 133 | } 134 | 135 | - (void)animateViewsForTextDisplay { 136 | if (self.text.length == 0) { 137 | [UIView animateWithDuration:0.35 animations:^{ 138 | self.borderView.frame = CGRectOffset(self.borderView.frame, CGRectGetWidth(self.bounds), 0); 139 | 140 | CGFloat length = self.placeholderLabel.font.lineHeight; 141 | self.imageView.frame = CGRectMake(CGRectGetWidth(self.bounds)-length, CGRectGetHeight(self.bounds)-length, length, length); 142 | 143 | self.placeholderLabel.layer.transform = CATransform3DIdentity; 144 | } completion:^(BOOL finished) { 145 | [UIView animateWithDuration:0.2 animations:^{ 146 | self.imageView.layer.transform = CATransform3DIdentity; 147 | } completion:^(BOOL finished) { 148 | if (self.didEndEditingHandler != nil) { 149 | self.didEndEditingHandler(); 150 | } 151 | }]; 152 | }]; 153 | } 154 | } 155 | 156 | #pragma mark - Private methods 157 | - (UIFont *)placeholderFontFromFont:(UIFont *)font { 158 | UIFont *smallerFont = [UIFont fontWithName:font.fontName size:font.pointSize*self.placeholderFontScale]; 159 | 160 | return smallerFont; 161 | } 162 | 163 | @end 164 | -------------------------------------------------------------------------------- /CCTextFieldEffects/MinoruTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // MinoruTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/28/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "MinoruTextField.h" 10 | #import "PulsingHaloLayer.h" 11 | 12 | @interface MinoruTextField () 13 | 14 | @property (strong, nonatomic) CALayer *borderLayer; 15 | @property (strong, nonatomic) UIColor *backgroundLayerColor; 16 | @property (strong, nonatomic) PulsingHaloLayer *halo; 17 | 18 | @end 19 | 20 | @implementation MinoruTextField 21 | 22 | #pragma mark - Constants 23 | static CGFloat const borderThickness = 2; 24 | static CGPoint const placeholderInsets = {6, 6}; 25 | static CGPoint const textFieldInsets = {14, 6}; 26 | static CGPoint const shadowInsets = {7, 8}; 27 | 28 | #pragma mark - Custom accessorys 29 | - (void)setPlaceholderColor:(UIColor *)placeholderColor { 30 | _placeholderColor = placeholderColor; 31 | 32 | [self updatePlaceholder]; 33 | } 34 | 35 | - (void)setBorderColor:(UIColor *)borderColor { 36 | _borderColor = borderColor; 37 | 38 | self.borderLayer.borderColor = borderColor.CGColor; 39 | self.halo.backgroundColor = borderColor.CGColor; 40 | } 41 | 42 | - (void)setBackgroundColor:(UIColor *)backgroundColor { 43 | self.backgroundLayerColor = backgroundColor; 44 | } 45 | 46 | - (UIColor *)backgroundColor { 47 | return self.backgroundLayerColor; 48 | } 49 | 50 | - (void)setPlaceholderFontScale:(CGFloat)placeholderFontScale { 51 | _placeholderFontScale = placeholderFontScale; 52 | 53 | [self updatePlaceholder]; 54 | } 55 | 56 | - (void)setPlaceholder:(NSString *)placeholder { 57 | [super setPlaceholder:placeholder]; 58 | 59 | [self updatePlaceholder]; 60 | } 61 | 62 | - (void)setBounds:(CGRect)bounds { 63 | [super setBounds:bounds]; 64 | 65 | [self updateBorder]; 66 | [self updatePlaceholder]; 67 | } 68 | 69 | #pragma mark - Lifecycle 70 | - (instancetype)initWithFrame:(CGRect)frame { 71 | self = [super initWithFrame:frame]; 72 | 73 | if (self) { 74 | [self commonInit]; 75 | } 76 | 77 | return self; 78 | } 79 | 80 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 81 | self = [super initWithCoder:aDecoder]; 82 | 83 | if (self) { 84 | [self commonInit]; 85 | } 86 | return self; 87 | } 88 | 89 | - (void) commonInit { 90 | self.borderLayer = [[CALayer alloc] init]; 91 | self.placeholderLabel = [[UILabel alloc] init]; 92 | 93 | self.placeholderColor = [UIColor colorWithRed:0.4157 green:0.4745 blue:0.5373 alpha:1]; 94 | self.backgroundColor = [UIColor whiteColor]; 95 | self.borderColor = [UIColor colorWithRed:0.9255 green:0.6353 blue:0.6078 alpha:1]; 96 | self.cursorColor = [UIColor colorWithRed:0.9255 green:0.6353 blue:0.6078 alpha:1]; 97 | self.textColor = self.cursorColor; 98 | 99 | self.halo = [PulsingHaloLayer layer]; 100 | self.halo.repeatCount = 1; 101 | self.halo.animationDuration = 0.4; 102 | self.halo.radius = 0; 103 | self.halo.backgroundColor = self.borderColor.CGColor; 104 | [self.layer addSublayer:self.halo]; 105 | 106 | self.placeholderFontScale = 0.65; 107 | } 108 | 109 | #pragma mark - Overridden methods 110 | - (void)drawRect:(CGRect)rect { 111 | CGRect frame = CGRectMake(0, 0, CGRectGetWidth(rect), CGRectGetHeight(rect)); 112 | 113 | self.placeholderLabel.frame = CGRectInset(frame, placeholderInsets.x, placeholderInsets.y); 114 | self.placeholderLabel.font = [self placeholderFontFromFont:self.font]; 115 | 116 | [self updateBorder]; 117 | [self updatePlaceholder]; 118 | 119 | [self.layer addSublayer:self.borderLayer]; 120 | [self addSubview:self.placeholderLabel]; 121 | } 122 | 123 | - (void) layoutSubviews { 124 | [super layoutSubviews]; 125 | 126 | self.halo.radius = CGRectGetHeight(self.bounds); 127 | } 128 | 129 | - (CGRect)editingRectForBounds:(CGRect)bounds { 130 | CGRect newBounds = [self rectForBorderBounds:bounds]; 131 | 132 | return CGRectInset(newBounds, textFieldInsets.x, 0); 133 | } 134 | 135 | - (CGRect)textRectForBounds:(CGRect)bounds { 136 | CGRect newBounds = [self rectForBorderBounds:bounds]; 137 | 138 | return CGRectInset(newBounds, textFieldInsets.x, 0); 139 | } 140 | 141 | - (void)animateViewsForTextEntry { 142 | [UIView animateWithDuration:0.35 animations:^{ 143 | self.borderLayer.borderWidth = borderThickness; 144 | self.borderLayer.borderColor = self.borderColor.CGColor; 145 | 146 | self.halo.frame = self.borderLayer.frame; 147 | [self.halo startAnimation]; 148 | } completion:^(BOOL finished) { 149 | if (self.didBeginEditingHandler != nil) { 150 | self.didBeginEditingHandler(); 151 | } 152 | }]; 153 | } 154 | 155 | - (void)animateViewsForTextDisplay { 156 | [UIView animateWithDuration:0.35 animations:^{ 157 | self.borderLayer.borderWidth = 0; 158 | } completion:^(BOOL finished) { 159 | if (self.didEndEditingHandler != nil) { 160 | self.didEndEditingHandler(); 161 | } 162 | }]; 163 | } 164 | 165 | #pragma mark - Private methods 166 | - (void)updateBorder { 167 | self.borderLayer.frame = [self rectForBorderBounds:self.frame]; 168 | self.borderLayer.backgroundColor = self.backgroundColor.CGColor; 169 | } 170 | 171 | - (void)updatePlaceholder { 172 | self.placeholderLabel.text = self.placeholder; 173 | self.placeholderLabel.textColor = self.placeholderColor; 174 | [self.placeholderLabel sizeToFit]; 175 | [self layoutPlaceholderInTextRect]; 176 | 177 | if ([self isFirstResponder]) { 178 | [self animateViewsForTextEntry]; 179 | } 180 | } 181 | 182 | - (UIFont *)placeholderFontFromFont:(UIFont *)font { 183 | return [UIFont fontWithName:font.fontName size:font.pointSize*self.placeholderFontScale]; 184 | } 185 | 186 | - (CGRect)rectForBorderBounds:(CGRect)bounds { 187 | return CGRectMake(shadowInsets.x, shadowInsets.y, CGRectGetWidth(bounds)-shadowInsets.x*2, CGRectGetHeight(bounds)-self.font.lineHeight-placeholderInsets.y); 188 | } 189 | 190 | - (void)layoutPlaceholderInTextRect { 191 | self.placeholderLabel.frame = CGRectMake(placeholderInsets.x+shadowInsets.x, CGRectGetHeight(self.bounds)-CGRectGetHeight(self.placeholderLabel.frame), CGRectGetWidth(self.placeholderLabel.frame), CGRectGetHeight(self.placeholderLabel.frame)); 192 | } 193 | 194 | @end 195 | -------------------------------------------------------------------------------- /CCTextFieldEffects/KyoTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // KyoTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/28/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "KyoTextField.h" 10 | 11 | @interface KyoTextField () 12 | 13 | @property (strong, nonatomic) CALayer *borderLayer; 14 | @property (strong, nonatomic) UIColor *backgroundLayerColor; 15 | @property (strong, nonatomic) UIView *overlayView; 16 | @property (nonatomic) NSUInteger index; 17 | 18 | @end 19 | 20 | @implementation KyoTextField 21 | 22 | #pragma mark - Constants 23 | static CGPoint const placeholderInsets = {1, 3}; 24 | static CGPoint const textFieldInsets = {1, 6}; 25 | 26 | #pragma mark - Custom accessorys 27 | - (void)setPlaceholderColor:(UIColor *)placeholderColor { 28 | _placeholderColor = placeholderColor; 29 | 30 | [self updatePlaceholder]; 31 | } 32 | 33 | - (void)setBackgroundColor:(UIColor *)backgroundColor { 34 | self.backgroundLayerColor = backgroundColor; 35 | } 36 | 37 | - (UIColor *)backgroundColor { 38 | return self.backgroundLayerColor; 39 | } 40 | 41 | - (void)setPlaceholderFontScale:(CGFloat)placeholderFontScale { 42 | _placeholderFontScale = placeholderFontScale; 43 | 44 | [self updatePlaceholder]; 45 | } 46 | 47 | - (void)setPlaceholder:(NSString *)placeholder { 48 | [super setPlaceholder:placeholder]; 49 | 50 | [self updatePlaceholder]; 51 | } 52 | 53 | - (void)setBounds:(CGRect)bounds { 54 | [super setBounds:bounds]; 55 | 56 | [self updateBorder]; 57 | [self updatePlaceholder]; 58 | } 59 | 60 | #pragma mark - Lifecycle 61 | - (instancetype)initWithFrame:(CGRect)frame { 62 | self = [super initWithFrame:frame]; 63 | 64 | if (self) { 65 | [self commonInit]; 66 | } 67 | 68 | return self; 69 | } 70 | 71 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 72 | self = [super initWithCoder:aDecoder]; 73 | 74 | if (self) { 75 | [self commonInit]; 76 | } 77 | return self; 78 | } 79 | 80 | - (void) commonInit { 81 | self.overlayView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds]; 82 | self.borderLayer = [[CALayer alloc] init]; 83 | self.placeholderLabel = [[UILabel alloc] init]; 84 | 85 | self.placeholderColor = [UIColor colorWithRed:0.4157 green:0.4745 blue:0.5373 alpha:1]; 86 | self.overlayColor = [UIColor colorWithRed:0.2392 green:0.3451 blue:0.8235 alpha:0.6]; 87 | self.backgroundColor = [UIColor whiteColor]; 88 | self.cursorColor = [UIColor colorWithRed:0.3255 green:0.3647 blue:0.5725 alpha:1]; 89 | self.textColor = self.cursorColor; 90 | 91 | self.placeholderFontScale = 0.85; 92 | } 93 | 94 | #pragma mark - Overridden methods 95 | - (void)drawRect:(CGRect)rect { 96 | CGRect frame = CGRectMake(0, 0, CGRectGetWidth(rect), CGRectGetHeight(rect)); 97 | 98 | self.placeholderLabel.frame = CGRectInset(frame, placeholderInsets.x, placeholderInsets.y); 99 | self.placeholderLabel.font = [self placeholderFontFromFont:self.font]; 100 | 101 | [self updateBorder]; 102 | [self updatePlaceholder]; 103 | 104 | [self.layer addSublayer:self.borderLayer]; 105 | [self addSubview:self.placeholderLabel]; 106 | } 107 | 108 | - (CGRect)editingRectForBounds:(CGRect)bounds { 109 | CGRect newBounds = [self rectForBorderBounds:bounds]; 110 | 111 | return CGRectInset(newBounds, textFieldInsets.x+self.borderLayer.cornerRadius, 0); 112 | } 113 | 114 | - (CGRect)textRectForBounds:(CGRect)bounds { 115 | CGRect newBounds = [self rectForBorderBounds:bounds]; 116 | 117 | return CGRectInset(newBounds, textFieldInsets.x+self.borderLayer.cornerRadius, 0); 118 | } 119 | 120 | - (void)animateViewsForTextEntry { 121 | if (self.superview != nil) { 122 | self.index = [self.superview.subviews indexOfObject:self]; 123 | self.overlayView.backgroundColor = self.overlayColor; 124 | self.overlayView.alpha = 0; 125 | 126 | [UIView animateWithDuration:0.35 animations:^{ 127 | self.overlayView.alpha = [self alphaForColor:self.overlayColor]; 128 | [self.superview addSubview:self.overlayView]; 129 | [self.superview bringSubviewToFront:self]; 130 | self.placeholderLabel.textColor = self.backgroundColor; 131 | } completion:^(BOOL finished) { 132 | if (self.didBeginEditingHandler != nil) { 133 | self.didBeginEditingHandler(); 134 | } 135 | }]; 136 | } 137 | } 138 | 139 | - (void)animateViewsForTextDisplay { 140 | if (self.superview) { 141 | [UIView animateWithDuration:0.35 animations:^{ 142 | self.overlayView.alpha = 0; 143 | self.placeholderLabel.textColor = self.placeholderColor; 144 | } completion:^(BOOL finished) { 145 | [self.overlayView removeFromSuperview]; 146 | [self.superview insertSubview:self atIndex:self.index]; 147 | if (self.didEndEditingHandler != nil) { 148 | self.didEndEditingHandler(); 149 | } 150 | }]; 151 | } 152 | } 153 | 154 | #pragma mark - Private methods 155 | - (void)updateBorder { 156 | self.borderLayer.frame = [self rectForBorderBounds:self.frame]; 157 | self.borderLayer.cornerRadius = CGRectGetHeight(self.borderLayer.frame)/2; 158 | self.borderLayer.backgroundColor = self.backgroundColor.CGColor; 159 | } 160 | 161 | - (void)updatePlaceholder { 162 | self.placeholderLabel.text = self.placeholder; 163 | self.placeholderLabel.textColor = self.placeholderColor; 164 | [self.placeholderLabel sizeToFit]; 165 | [self layoutPlaceholderInTextRect]; 166 | 167 | if ([self isFirstResponder]) { 168 | [self animateViewsForTextEntry]; 169 | } 170 | } 171 | 172 | - (UIFont *)placeholderFontFromFont:(UIFont *)font { 173 | return [UIFont fontWithName:font.fontName size:font.pointSize*self.placeholderFontScale]; 174 | } 175 | 176 | - (CGRect)rectForBorderBounds:(CGRect)bounds { 177 | return CGRectMake(0, 0, CGRectGetWidth(bounds), CGRectGetHeight(bounds)-self.font.lineHeight-placeholderInsets.y); 178 | } 179 | 180 | - (void)layoutPlaceholderInTextRect { 181 | self.placeholderLabel.frame = CGRectMake(placeholderInsets.x+self.borderLayer.cornerRadius, CGRectGetHeight(self.bounds)-CGRectGetHeight(self.placeholderLabel.frame), CGRectGetWidth(self.placeholderLabel.frame), CGRectGetHeight(self.placeholderLabel.frame)); 182 | } 183 | 184 | - (CGFloat)alphaForColor:(UIColor *)color { 185 | CGFloat alpha; 186 | CGFloat red; 187 | CGFloat green; 188 | CGFloat blue; 189 | 190 | if ([color getRed:&red green:&green blue:&blue alpha:&alpha]) { 191 | return alpha; 192 | } else { 193 | return 1; 194 | } 195 | } 196 | 197 | @end 198 | -------------------------------------------------------------------------------- /CCTextFieldEffects/JiroTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // JiroTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/26/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "JiroTextField.h" 10 | 11 | @interface JiroTextField () 12 | 13 | @property (strong, nonatomic) CALayer *borderLayer; 14 | 15 | @end 16 | 17 | @implementation JiroTextField 18 | 19 | #pragma mark - Constant 20 | static CGFloat const borderThickness = 2; 21 | static CGPoint const textFieldInsets = {8, 12}; 22 | static CGPoint const placeholderInsets = {8, 8}; 23 | 24 | #pragma mark - Custom accessorys 25 | - (void)setBorderColor:(UIColor *)borderColor { 26 | _borderColor = borderColor; 27 | 28 | [self updateBorder]; 29 | } 30 | 31 | - (void)setPlaceholderColor:(UIColor *)placeholderColor { 32 | _placeholderColor = placeholderColor; 33 | 34 | [self updatePlaceholder]; 35 | } 36 | 37 | - (void)setPlaceholderFontScale:(CGFloat)placeholderFontScale { 38 | _placeholderFontScale = placeholderFontScale; 39 | 40 | [self updatePlaceholder]; 41 | } 42 | 43 | - (void)setPlaceholder:(NSString *)placeholder { 44 | [super setPlaceholder:placeholder]; 45 | 46 | [self updatePlaceholder]; 47 | } 48 | 49 | - (void)setBounds:(CGRect)bounds { 50 | [super setBounds:bounds]; 51 | 52 | [self updateBorder]; 53 | [self updatePlaceholder]; 54 | } 55 | 56 | #pragma mark - Lifecycle 57 | - (instancetype)initWithFrame:(CGRect)frame { 58 | self = [super initWithFrame:frame]; 59 | 60 | if (self) { 61 | [self commonInit]; 62 | } 63 | 64 | return self; 65 | } 66 | 67 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 68 | self = [super initWithCoder:aDecoder]; 69 | 70 | if (self) { 71 | [self commonInit]; 72 | } 73 | return self; 74 | } 75 | 76 | - (void) commonInit { 77 | self.borderLayer = [[CALayer alloc] init]; 78 | self.placeholderLabel = [[UILabel alloc] init]; 79 | 80 | self.borderColor = [UIColor colorWithRed:0.4157 green:0.4745 blue:0.5373 alpha:1.0]; 81 | self.placeholderColor = self.borderColor; 82 | self.cursorColor = [UIColor colorWithRed:0.8275 green:0.8862 blue:0.8862 alpha:1.0]; 83 | self.textColor = self.cursorColor; 84 | 85 | self.placeholderFontScale = 0.65; 86 | } 87 | 88 | #pragma mark - Overridden methods 89 | - (void)drawRect:(CGRect)rect { 90 | CGRect frame = CGRectMake(0, 0, CGRectGetWidth(rect), CGRectGetHeight(rect)); 91 | self.placeholderLabel.frame = CGRectInset(frame, placeholderInsets.x, placeholderInsets.y); 92 | self.placeholderLabel.font = [self placeholderFontFromFont:self.font]; 93 | 94 | [self updateBorder]; 95 | [self updatePlaceholder]; 96 | 97 | [self.layer addSublayer:self.borderLayer]; 98 | [self addSubview:self.placeholderLabel]; 99 | } 100 | 101 | - (CGRect)editingRectForBounds:(CGRect)bounds { 102 | return CGRectOffset(bounds, textFieldInsets.x, textFieldInsets.y); 103 | } 104 | 105 | - (CGRect)textRectForBounds:(CGRect)bounds { 106 | return CGRectOffset(bounds, textFieldInsets.x, textFieldInsets.y); 107 | } 108 | 109 | - (void)animateViewsForTextEntry { 110 | self.borderLayer.frame= CGRectMake(0, self.font.lineHeight, CGRectGetWidth(self.borderLayer.frame), CGRectGetHeight(self.borderLayer.frame)); 111 | 112 | [UIView animateWithDuration:0.2 delay:0.3 usingSpringWithDamping:0.8 initialSpringVelocity:1 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ 113 | self.placeholderLabel.frame = CGRectMake(placeholderInsets.x, self.borderLayer.frame.origin.y-self.placeholderLabel.bounds.size.height, CGRectGetWidth(self.placeholderLabel.frame), CGRectGetHeight(self.placeholderLabel.frame)); 114 | self.borderLayer.frame = [self rectForBorderThickness:borderThickness isFilled:YES]; 115 | } completion:^(BOOL finished) { 116 | if (self.didBeginEditingHandler != nil) { 117 | self.didBeginEditingHandler(); 118 | } 119 | }]; 120 | } 121 | 122 | - (void)animateViewsForTextDisplay { 123 | if (self.text.length == 0) { 124 | [UIView animateWithDuration:0.35 delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:2.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ 125 | [self layoutPlaceholderInTextRect]; 126 | self.placeholderLabel.alpha = 1; 127 | } completion:^(BOOL finished) { 128 | if (self.didEndEditingHandler != nil) { 129 | self.didEndEditingHandler(); 130 | } 131 | }]; 132 | 133 | self.borderLayer.frame = [self rectForBorderThickness:borderThickness isFilled:NO]; 134 | } 135 | } 136 | 137 | #pragma mark - Private methods 138 | - (void)updateBorder { 139 | self.borderLayer.frame = [self rectForBorderThickness:borderThickness isFilled:NO]; 140 | self.borderLayer.backgroundColor = self.borderColor.CGColor; 141 | } 142 | 143 | - (void)updatePlaceholder { 144 | self.placeholderLabel.text = self.placeholder; 145 | self.placeholderLabel.textColor = self.placeholderColor; 146 | [self.placeholderLabel sizeToFit]; 147 | [self layoutPlaceholderInTextRect]; 148 | 149 | if ([self isFirstResponder] || self.text.length!=0) { 150 | [self animateViewsForTextEntry]; 151 | } 152 | } 153 | 154 | - (UIFont *)placeholderFontFromFont:(UIFont *)font { 155 | UIFont *smallerFont = [UIFont fontWithName:self.font.fontName size:self.font.pointSize*self.placeholderFontScale]; 156 | 157 | return smallerFont; 158 | } 159 | 160 | - (CGRect)rectForBorderThickness:(CGFloat)thickness isFilled:(BOOL)isFilled { 161 | if (isFilled) { 162 | return CGRectMake(0, self.placeholderLabel.frame.origin.y+self.placeholderLabel.font.lineHeight, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame)); 163 | } else { 164 | return CGRectMake(0, CGRectGetHeight(self.frame)-thickness, CGRectGetWidth(self.frame), thickness); 165 | } 166 | } 167 | 168 | - (void)layoutPlaceholderInTextRect { 169 | if (self.text.length != 0) { 170 | return; 171 | } 172 | 173 | CGRect textRect = [self textRectForBounds:self.bounds]; 174 | CGFloat originX = textRect.origin.x; 175 | 176 | switch (self.textAlignment) { 177 | case NSTextAlignmentCenter: 178 | originX += textRect.size.width/2-self.placeholderLabel.bounds.size.width/2; 179 | break; 180 | case NSTextAlignmentRight: 181 | originX += textRect.size.width-self.placeholderLabel.bounds.size.width; 182 | break; 183 | default: 184 | break; 185 | } 186 | 187 | self.placeholderLabel.frame = CGRectMake(originX, textRect.size.height/2, CGRectGetWidth(self.placeholderLabel.frame), CGRectGetHeight(self.placeholderLabel.frame)); 188 | } 189 | 190 | @end 191 | -------------------------------------------------------------------------------- /CCTextFieldEffects/IsaoTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // IsaoTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/25/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "IsaoTextField.h" 10 | 11 | @interface IsaoTextField () 12 | 13 | @property (strong, nonatomic) CALayer *borderLayer; 14 | 15 | @end 16 | 17 | @implementation IsaoTextField 18 | 19 | #pragma mark - Constants 20 | static CGFloat const activeBorderThickness = 4; 21 | static CGFloat const inactiveBorderThickness = 2; 22 | static CGPoint const textFieldInsets = {6, 6}; 23 | static CGPoint const placeholderInsets = {6, 6}; 24 | 25 | #pragma mark - Custom accessorys 26 | - (void)setInactiveColor:(UIColor *)inactiveColor { 27 | _inactiveColor = inactiveColor; 28 | 29 | [self updateBorder]; 30 | } 31 | 32 | - (void)setActiveColor:(UIColor *)activeColor { 33 | _activeColor = activeColor; 34 | 35 | [self updateBorder]; 36 | } 37 | 38 | - (void)setPlaceholderFontScale:(CGFloat)placeholderFontScale { 39 | _placeholderFontScale = placeholderFontScale; 40 | 41 | [self updatePlaceholder]; 42 | } 43 | 44 | - (void)setPlaceholder:(NSString *)placeholder { 45 | [super setPlaceholder:placeholder]; 46 | 47 | [self updatePlaceholder]; 48 | } 49 | 50 | - (void)setBounds:(CGRect)bounds { 51 | [super setBounds:bounds]; 52 | 53 | [self updateBorder]; 54 | [self updatePlaceholder]; 55 | } 56 | 57 | #pragma mark - Lifecycle 58 | - (instancetype)initWithFrame:(CGRect)frame { 59 | self = [super initWithFrame:frame]; 60 | 61 | if (self) { 62 | [self commonInit]; 63 | } 64 | 65 | return self; 66 | } 67 | 68 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 69 | self = [super initWithCoder:aDecoder]; 70 | 71 | if (self) { 72 | [self commonInit]; 73 | } 74 | return self; 75 | } 76 | 77 | - (void) commonInit { 78 | self.borderLayer = [[CALayer alloc] init]; 79 | self.placeholderLabel = [[UILabel alloc] init]; 80 | 81 | self.inactiveColor = [UIColor colorWithRed:0.8549 green:0.8549 blue:0.8549 alpha:1.0]; 82 | self.activeColor = [UIColor colorWithRed:0.8549 green:0.4392 blue:0.4431 alpha:1.0]; 83 | self.placeholderLabel.textColor = self.inactiveColor; 84 | self.cursorColor = [UIColor colorWithRed:0.6863 green:0.702 blue:0.7216 alpha:1.0]; 85 | self.textColor = [UIColor colorWithRed:0.6863 green:0.702 blue:0.7216 alpha:1.0]; 86 | 87 | self.placeholderFontScale = 0.7; 88 | } 89 | 90 | #pragma mark - Overridden methods 91 | - (void)drawRect:(CGRect)rect { 92 | CGRect frame = CGRectMake(0, 0, rect.size.width, rect.size.height); 93 | self.placeholderLabel.frame = CGRectInset(frame, placeholderInsets.x, placeholderInsets.y); 94 | self.placeholderLabel.font = [self placeholderFontFromFont:self.font]; 95 | 96 | [self updateBorder]; 97 | [self updatePlaceholder]; 98 | 99 | [self.layer addSublayer:self.borderLayer]; 100 | [self addSubview:self.placeholderLabel]; 101 | } 102 | 103 | - (CGRect)editingRectForBounds:(CGRect)bounds { 104 | CGRect newBounds = CGRectMake(0, 0, bounds.size.width, bounds.size.height-self.font.lineHeight+textFieldInsets.y); 105 | 106 | return CGRectInset(newBounds, textFieldInsets.x, 0); 107 | } 108 | 109 | - (CGRect)textRectForBounds:(CGRect)bounds { 110 | CGRect newBounds = CGRectMake(0, 0, bounds.size.width, bounds.size.height-self.font.lineHeight+textFieldInsets.y); 111 | 112 | return CGRectInset(newBounds, textFieldInsets.x, 0); 113 | } 114 | 115 | - (void)animateViewsForTextEntry { 116 | [self updateBorder]; 117 | [self performPlacerholderAnimation]; 118 | 119 | self.placeholderLabel.textColor = self.activeColor; 120 | } 121 | 122 | - (void)animateViewsForTextDisplay { 123 | [self updateBorder]; 124 | 125 | [self performPlacerholderAnimation]; 126 | 127 | self.placeholderLabel.textColor = self.inactiveColor; 128 | } 129 | 130 | #pragma mark - Private methods 131 | - (void)updateBorder { 132 | self.borderLayer.frame = [self rectForBorderBounds:self.frame]; 133 | self.borderLayer.backgroundColor = [self isFirstResponder]?self.activeColor.CGColor:self.inactiveColor.CGColor; 134 | } 135 | 136 | - (void)updatePlaceholder { 137 | self.placeholderLabel.text = self.placeholder; 138 | [self.placeholderLabel sizeToFit]; 139 | 140 | [self layoutPlaceholderInTextRect]; 141 | 142 | if ([self isFirstResponder]) { 143 | [self animateViewsForTextEntry]; 144 | } 145 | } 146 | 147 | - (UIFont *)placeholderFontFromFont:(UIFont *)font { 148 | UIFont *smallerFont = [UIFont fontWithName:self.font.fontName size:self.font.pointSize*self.placeholderFontScale]; 149 | 150 | return smallerFont; 151 | } 152 | 153 | - (CGRect)rectForBorderBounds:(CGRect)bounds { 154 | CGRect newRect; 155 | 156 | if ([self isFirstResponder]) { 157 | newRect = CGRectMake(0, bounds.size.height-self.font.lineHeight+textFieldInsets.y-activeBorderThickness, bounds.size.width, activeBorderThickness); 158 | } else { 159 | newRect = CGRectMake(0, bounds.size.height-self.font.lineHeight+textFieldInsets.y-inactiveBorderThickness, bounds.size.width, inactiveBorderThickness); 160 | } 161 | 162 | return newRect; 163 | } 164 | 165 | - (void)layoutPlaceholderInTextRect { 166 | CGRect textRect = [self textRectForBounds:self.bounds]; 167 | CGFloat originX = textRect.origin.x; 168 | 169 | switch (self.textAlignment) { 170 | case NSTextAlignmentCenter: 171 | originX += textRect.size.width/2-self.placeholderLabel.bounds.size.width/2; 172 | break; 173 | case NSTextAlignmentRight: 174 | originX += textRect.size.width-self.placeholderLabel.bounds.size.width; 175 | break; 176 | default: 177 | break; 178 | } 179 | 180 | self.placeholderLabel.frame = CGRectMake(originX, self.bounds.size.height-self.placeholderLabel.frame.size.height, self.placeholderLabel.frame.size.width, self.placeholderLabel.frame.size.height); 181 | } 182 | 183 | - (void)performPlacerholderAnimation { 184 | CGFloat yOffset = 4; 185 | 186 | [UIView animateWithDuration:0.15 animations:^{ 187 | self.placeholderLabel.transform = CGAffineTransformMakeTranslation(0, -yOffset); 188 | self.placeholderLabel.alpha = 0; 189 | } completion:^(BOOL finished){ 190 | self.placeholderLabel.transform = CGAffineTransformIdentity; 191 | self.placeholderLabel.transform = CGAffineTransformMakeTranslation(0, yOffset); 192 | 193 | [UIView animateWithDuration:0.15 animations:^{ 194 | self.placeholderLabel.transform = CGAffineTransformIdentity; 195 | self.placeholderLabel.alpha = 1; 196 | } completion:^(BOOL finished) { 197 | if ([self isFirstResponder] && self.didBeginEditingHandler!= nil) { 198 | self.didBeginEditingHandler(); 199 | } else if (![self isFirstResponder] && self.didEndEditingHandler != nil) { 200 | self.didEndEditingHandler(); 201 | } 202 | }]; 203 | }]; 204 | } 205 | 206 | @end 207 | -------------------------------------------------------------------------------- /CCTextFieldEffects/NarikoTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // NarikoTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/30/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "NarikoTextField.h" 10 | 11 | @interface NarikoTextField () 12 | 13 | @property (strong, nonatomic) CALayer *borderLayer; 14 | @property (strong, nonatomic) CALayer *backgroundLayer; 15 | @property (strong, nonatomic) UIColor *backgroundLayerColor; 16 | 17 | @end 18 | 19 | @implementation NarikoTextField 20 | 21 | #pragma mark - Constants 22 | static CGFloat const borderThickness = 2.5; 23 | static CGPoint const textFieldInsets = {10, 6}; 24 | static CGPoint const placeholderInsets = {6, 6}; 25 | 26 | #pragma mark - Custom accessory 27 | - (void)setPlaceholderColor:(UIColor *)placeholderColor { 28 | _placeholderColor = placeholderColor; 29 | 30 | [self updatePlaceholder]; 31 | } 32 | 33 | - (void)setBorderColor:(UIColor *)borderColor { 34 | _borderColor = borderColor; 35 | 36 | [self updateBorder]; 37 | } 38 | 39 | - (void)setBackgroundColor:(UIColor *)backgroundColor { 40 | self.backgroundLayerColor = backgroundColor; 41 | 42 | self.backgroundLayer.backgroundColor = backgroundColor.CGColor; 43 | } 44 | 45 | - (UIColor *)backgroundColor { 46 | return self.backgroundLayerColor; 47 | } 48 | 49 | - (void)setPlaceholderFontScale:(CGFloat)placeholderFontScale { 50 | _placeholderFontScale = placeholderFontScale; 51 | 52 | [self updatePlaceholder]; 53 | } 54 | 55 | - (void)setPlaceholder:(NSString *)placeholder { 56 | [super setPlaceholder:placeholder]; 57 | 58 | [self updatePlaceholder]; 59 | } 60 | 61 | - (void)setBounds:(CGRect)bounds { 62 | [super setBounds:bounds]; 63 | 64 | [self updateBorder]; 65 | [self updatePlaceholder]; 66 | } 67 | 68 | #pragma mark - Lifecycle 69 | - (instancetype)initWithFrame:(CGRect)frame { 70 | self = [super initWithFrame:frame]; 71 | 72 | if (self) { 73 | [self commonInit]; 74 | } 75 | 76 | return self; 77 | } 78 | 79 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 80 | self = [super initWithCoder:aDecoder]; 81 | 82 | if (self) { 83 | [self commonInit]; 84 | } 85 | return self; 86 | } 87 | 88 | - (void) commonInit { 89 | self.borderLayer = [[CALayer alloc] init]; 90 | self.backgroundLayer = [[CALayer alloc] init]; 91 | self.placeholderLabel = [[UILabel alloc] init]; 92 | 93 | self.placeholderColor = [UIColor colorWithRed:0.4118 green:0.4118 blue:0.4118 alpha:1.0]; 94 | self.borderColor = [UIColor colorWithRed:0.6078 green:0.6235 blue:0.6235 alpha:1]; 95 | self.backgroundColor = [UIColor whiteColor]; 96 | self.cursorColor = [UIColor colorWithRed:0.9451 green:0.5098 blue:0.5725 alpha:1]; 97 | self.textColor = self.cursorColor; 98 | 99 | self.placeholderFontScale = 0.85; 100 | } 101 | 102 | #pragma mark - Overridden methods 103 | - (void)drawRect:(CGRect)rect { 104 | self.placeholderLabel.frame = CGRectMake(placeholderInsets.x, CGRectGetHeight(rect)-placeholderInsets.y-self.placeholderLabel.font.lineHeight, CGRectGetWidth(rect), placeholderInsets.y+self.placeholderLabel.font.lineHeight); 105 | self.placeholderLabel.font = [self placeholderFontFromFont:self.font]; 106 | 107 | [self updateBorder]; 108 | [self updatePlaceholder]; 109 | 110 | [self.layer addSublayer:self.borderLayer]; 111 | 112 | self.backgroundLayer.frame = CGRectMake(0,CGRectGetHeight(self.bounds) , CGRectGetWidth(self.bounds), 0); 113 | [self.layer addSublayer:self.backgroundLayer]; 114 | 115 | [self addSubview:self.placeholderLabel]; 116 | } 117 | 118 | - (CGRect)editingRectForBounds:(CGRect)bounds { 119 | CGRect rect = [self textRectForBounds:bounds]; 120 | 121 | /** 122 | Basically the return value should euqal to the return value of [self textRectForBounds:bounds] (aka. rect) 123 | But when you run the code, the editing rect is a little upper than text rect, though their origin.y are euqal. 124 | I have not figured out the reason, so I make 0.5 offset as a expedient. 125 | */ 126 | return CGRectOffset(rect, 0, 0.5); 127 | } 128 | 129 | - (CGRect)textRectForBounds:(CGRect)bounds { 130 | return CGRectInset([self rectForBorderBounds:bounds], textFieldInsets.x, 0); 131 | } 132 | 133 | - (void)animateViewsForTextEntry { 134 | if (self.text.length == 0) { 135 | [UIView animateWithDuration:0.3 animations:^{ 136 | CGRect backgroundRect = [self editingRectForBounds:self.bounds]; 137 | self.backgroundLayer.frame = CGRectMake(0, CGRectGetHeight(self.bounds)-CGRectGetHeight(backgroundRect), CGRectGetWidth(self.bounds), CGRectGetHeight(backgroundRect)); 138 | self.borderLayer.frame = CGRectOffset(self.borderLayer.frame, 0, -CGRectGetHeight(self.backgroundLayer.frame)); 139 | 140 | CGAffineTransform translate = CGAffineTransformMakeTranslation(0, -CGRectGetHeight(self.backgroundLayer.frame)-placeholderInsets.y); 141 | CGAffineTransform scale = CGAffineTransformMakeScale(0.9, 0.9); 142 | self.placeholderLabel.transform = CGAffineTransformConcat(translate, scale); 143 | } completion:^(BOOL finished) { 144 | if (self.didBeginEditingHandler != nil) { 145 | self.didBeginEditingHandler(); 146 | } 147 | }]; 148 | } 149 | } 150 | 151 | - (void)animateViewsForTextDisplay { 152 | if (self.text.length == 0) { 153 | [UIView animateWithDuration:0.3 animations:^{ 154 | self.placeholderLabel.transform = CGAffineTransformIdentity; 155 | 156 | self.backgroundLayer.frame = CGRectMake(0,CGRectGetHeight(self.bounds) , CGRectGetWidth(self.bounds), 0); 157 | self.borderLayer.frame = CGRectMake(0, CGRectGetHeight(self.bounds)-borderThickness, CGRectGetWidth(self.bounds), borderThickness); 158 | } completion:^(BOOL finished) { 159 | if (self.didEndEditingHandler != nil) { 160 | self.didEndEditingHandler(); 161 | } 162 | }]; 163 | } 164 | } 165 | 166 | #pragma mark - Private methods 167 | - (void)updateBorder { 168 | CGRect rect = [self rectForBorderBounds:self.bounds]; 169 | self.borderLayer.frame = CGRectMake(0, CGRectGetHeight(self.bounds)-borderThickness, CGRectGetWidth(rect), borderThickness); 170 | self.borderLayer.borderWidth = borderThickness; 171 | self.borderLayer.borderColor = self.borderColor.CGColor; 172 | } 173 | 174 | - (void)updatePlaceholder { 175 | self.placeholderLabel.text = self.placeholder; 176 | self.placeholderLabel.textColor = self.placeholderColor; 177 | [self.placeholderLabel sizeToFit]; 178 | 179 | if ([self isFirstResponder] || self.text.length!=0) { 180 | [self animateViewsForTextEntry]; 181 | } 182 | } 183 | 184 | - (UIFont *)placeholderFontFromFont:(UIFont *)font { 185 | UIFont *smallerFont = [UIFont fontWithName:font.fontName size:font.pointSize*self.placeholderFontScale]; 186 | 187 | return smallerFont; 188 | } 189 | 190 | - (CGRect)rectForBorderBounds:(CGRect)bounds { 191 | return CGRectMake(0, self.font.lineHeight+textFieldInsets.y, CGRectGetWidth(bounds), CGRectGetHeight(bounds)-self.font.lineHeight-textFieldInsets.y); 192 | } 193 | 194 | @end 195 | -------------------------------------------------------------------------------- /CCTextFieldEffects/YoshikoTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // YoshikoTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/26/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "YoshikoTextField.h" 10 | 11 | @interface YoshikoTextField () 12 | 13 | @property (strong, nonatomic) CALayer *borderLayer; 14 | @property (nonatomic) CGFloat placeholderHeight; 15 | 16 | @end 17 | 18 | @implementation YoshikoTextField 19 | 20 | #pragma mark - Constants 21 | static CGFloat const borderSize = 2; 22 | static CGPoint const textFieldInsets = {6, 0}; 23 | static CGPoint const placeholderInsets = {6, 0}; 24 | 25 | #pragma mark - Custom accessorys 26 | - (void)setActiveBorderColor:(UIColor *)activeBorderColor { 27 | _activeBorderColor = activeBorderColor; 28 | [self updateBorder]; 29 | [self updateBackground]; 30 | [self updatePlaceholder]; 31 | } 32 | 33 | - (void)setInactiveBorderColor:(UIColor *)inactiveBorderColor { 34 | _inactiveBorderColor = inactiveBorderColor; 35 | 36 | [self updateBorder]; 37 | [self updateBackground]; 38 | [self updatePlaceholder]; 39 | } 40 | 41 | - (void)setActiveBackgroundColor:(UIColor *)activeBackgroundColor { 42 | _activeBackgroundColor = activeBackgroundColor; 43 | 44 | [self updateBackground]; 45 | } 46 | 47 | - (void)setPlaceholderColor:(UIColor *)placeholderColor { 48 | _placeholderColor = placeholderColor; 49 | [self updatePlaceholder]; 50 | } 51 | 52 | - (void)setPlaceholderFontScale:(CGFloat)placeholderFontScale { 53 | _placeholderFontScale = placeholderFontScale; 54 | 55 | [self updatePlaceholder]; 56 | } 57 | 58 | - (void)setPlaceholder:(NSString *)placeholder { 59 | [super setPlaceholder:placeholder]; 60 | 61 | [self updatePlaceholder]; 62 | } 63 | 64 | - (void)setBounds:(CGRect)bounds { 65 | [super setBounds:bounds]; 66 | 67 | [self updateBorder]; 68 | [self updateBackground]; 69 | [self updatePlaceholder]; 70 | } 71 | 72 | - (CGFloat)placeholderHeight { 73 | return placeholderInsets.y + [self placeholderFontFromFont:self.font percentageOfOriginalSize:self.placeholderFontScale].lineHeight; 74 | } 75 | 76 | #pragma mark - Lifecycle 77 | - (instancetype)initWithFrame:(CGRect)frame { 78 | self = [super initWithFrame:frame]; 79 | 80 | if (self) { 81 | [self commonInit]; 82 | } 83 | 84 | return self; 85 | } 86 | 87 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 88 | self = [super initWithCoder:aDecoder]; 89 | 90 | if (self) { 91 | [self commonInit]; 92 | } 93 | return self; 94 | } 95 | 96 | - (void) commonInit { 97 | self.borderLayer = [[CALayer alloc] init]; 98 | self.placeholderLabel = [[UILabel alloc] init]; 99 | 100 | self.placeholderColor = [UIColor colorWithRed:0.5451 green:0.5490 blue:0.5490 alpha:1]; 101 | self.inactiveBorderColor = [UIColor colorWithRed:0.8157 green:0.8196 blue:0.8157 alpha:1]; 102 | self.activeBorderColor = [UIColor colorWithRed:0.6392 green:0.8275 blue:0.6118 alpha:1]; 103 | self.activeBackgroundColor = [UIColor colorWithRed:0.9765 green:0.9686 blue:0.9647 alpha:1]; 104 | self.cursorColor = [UIColor colorWithRed:0.6666 green:0.6666 blue:0.6666 alpha:1]; 105 | self.textColor = self.cursorColor; 106 | 107 | self.placeholderFontScale = 0.7; 108 | } 109 | 110 | #pragma mark - Overridden methods 111 | - (void)drawRect:(CGRect)rect { 112 | [self updateBorder]; 113 | [self updateBackground]; 114 | [self updatePlaceholder]; 115 | 116 | [self.layer addSublayer:self.borderLayer]; 117 | [self addSubview:self.placeholderLabel]; 118 | } 119 | 120 | - (CGRect)placeholderRectForBounds:(CGRect)bounds { 121 | if ([self isFirstResponder] || self.text.length!=0) { 122 | return CGRectMake(placeholderInsets.x, placeholderInsets.y, CGRectGetWidth(bounds), self.placeholderHeight); 123 | } else { 124 | return [self textRectForBounds:self.bounds]; 125 | } 126 | } 127 | 128 | - (CGRect)editingRectForBounds:(CGRect)bounds { 129 | return [self textRectForBounds:bounds]; 130 | } 131 | 132 | - (CGRect)textRectForBounds:(CGRect)bounds { 133 | return CGRectOffset(bounds, textFieldInsets.x, textFieldInsets.y+self.placeholderHeight/2); 134 | } 135 | 136 | - (void)prepareForInterfaceBuilder { 137 | self.placeholderLabel.alpha = 1; 138 | } 139 | 140 | - (void)animateViewsForTextEntry { 141 | [self animateViews]; 142 | } 143 | 144 | - (void)animateViewsForTextDisplay { 145 | [self animateViews]; 146 | } 147 | 148 | #pragma mark - Private methods 149 | - (void)animateViews { 150 | [UIView animateWithDuration:0.2 animations:^{ 151 | // Prevents a "flash" in the placeholder 152 | if (self.text.length == 0) { 153 | self.placeholderLabel.alpha = 0; 154 | } 155 | 156 | self.placeholderLabel.frame = [self placeholderRectForBounds:self.bounds]; 157 | } completion:^(BOOL finished) { 158 | [self updatePlaceholder]; 159 | 160 | [UIView animateWithDuration:0.3 animations:^{ 161 | self.placeholderLabel.alpha = 1; 162 | [self updateBorder]; 163 | [self updateBackground]; 164 | } completion:^(BOOL finished) { 165 | if ([self isFirstResponder] && self.didBeginEditingHandler != nil) { 166 | self.didBeginEditingHandler(); 167 | } else if (![self isFirstResponder] && self.didEndEditingHandler != nil) { 168 | self.didEndEditingHandler(); 169 | } 170 | }]; 171 | }]; 172 | } 173 | 174 | - (void)updateBorder { 175 | self.borderLayer.frame = [self rectForBounds:self.bounds]; 176 | self.borderLayer.borderWidth = borderSize; 177 | self.borderLayer.borderColor = [self isFirstResponder] || self.text.length!=0?self.activeBorderColor.CGColor:self.inactiveBorderColor.CGColor; 178 | } 179 | 180 | - (void)updateBackground { 181 | if ([self isFirstResponder] || self.text.length!=0) { 182 | self.borderLayer.backgroundColor = self.activeBackgroundColor.CGColor; 183 | } else { 184 | self.borderLayer.backgroundColor = self.inactiveBorderColor.CGColor; 185 | } 186 | } 187 | 188 | - (void)updatePlaceholder { 189 | self.placeholderLabel.frame = [self placeholderRectForBounds:self.bounds]; 190 | self.placeholderLabel.text = self.placeholder; 191 | self.placeholderLabel.textAlignment = self.textAlignment; 192 | 193 | if ([self isFirstResponder] || self.text.length!=0) { 194 | self.placeholderLabel.font = [self placeholderFontFromFont:self.font percentageOfOriginalSize:self.placeholderFontScale*0.8]; 195 | self.placeholderLabel.text = self.placeholder.uppercaseString; 196 | self.placeholderLabel.textColor = self.activeBorderColor; 197 | } else { 198 | self.placeholderLabel.font = [self placeholderFontFromFont:self.font percentageOfOriginalSize:self.placeholderFontScale]; 199 | self.placeholderLabel.textColor = self.placeholderColor; 200 | } 201 | } 202 | 203 | - (UIFont *)placeholderFontFromFont:(UIFont *)font percentageOfOriginalSize:(CGFloat)presentage { 204 | UIFont *smallerFont = [UIFont fontWithName:font.fontName size:font.pointSize*presentage]; 205 | 206 | return smallerFont; 207 | } 208 | 209 | - (CGRect)rectForBounds:(CGRect)bounds { 210 | return CGRectMake(bounds.origin.x, bounds.origin.y+self.placeholderHeight, CGRectGetWidth(bounds), CGRectGetHeight(bounds)-self.placeholderHeight); 211 | } 212 | 213 | @end 214 | -------------------------------------------------------------------------------- /CCTextFieldEffects/MadokaTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // MadokaTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/26/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "MadokaTextField.h" 10 | 11 | @interface MadokaTextField () 12 | 13 | @property (strong, nonatomic) CAShapeLayer *borderLayer; 14 | 15 | @end 16 | 17 | @implementation MadokaTextField 18 | 19 | #pragma mark - Constants 20 | static CGFloat const borderThickness = 1; 21 | static CGPoint const textFieldInsets = {6, 6}; 22 | static CGPoint const placeholderInsets = {6, 6}; 23 | 24 | #pragma mark - Custom accessory 25 | - (void)setPlaceholderColor:(UIColor *)placeholderColor { 26 | _placeholderColor = placeholderColor; 27 | 28 | [self updatePlaceholder]; 29 | } 30 | 31 | - (void)setBorderColor:(UIColor *)borderColor { 32 | _borderColor = borderColor; 33 | 34 | [self updateBorder]; 35 | } 36 | 37 | - (void)setPlaceholderFontScale:(CGFloat)placeholderFontScale { 38 | _placeholderFontScale = placeholderFontScale; 39 | 40 | [self updatePlaceholder]; 41 | } 42 | 43 | - (void)setPlaceholder:(NSString *)placeholder { 44 | [super setPlaceholder:placeholder]; 45 | 46 | [self updatePlaceholder]; 47 | } 48 | 49 | - (void)setBounds:(CGRect)bounds { 50 | [super setBounds:bounds]; 51 | 52 | [self updateBorder]; 53 | [self updatePlaceholder]; 54 | } 55 | 56 | #pragma mark - Lifecycle 57 | - (instancetype)initWithFrame:(CGRect)frame { 58 | self = [super initWithFrame:frame]; 59 | 60 | if (self) { 61 | [self commonInit]; 62 | } 63 | 64 | return self; 65 | } 66 | 67 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 68 | self = [super initWithCoder:aDecoder]; 69 | 70 | if (self) { 71 | [self commonInit]; 72 | } 73 | return self; 74 | } 75 | 76 | - (void) commonInit { 77 | self.borderLayer = [[CAShapeLayer alloc] init]; 78 | self.borderLayer.fillColor = [UIColor clearColor].CGColor; 79 | 80 | self.placeholderLabel = [[UILabel alloc] init]; 81 | 82 | self.placeholderColor = [UIColor colorWithRed:0.4039 green:0.3922 blue:0.4863 alpha:1.0]; 83 | self.borderColor = self.placeholderColor; 84 | self.borderLayer.strokeColor = self.borderColor.CGColor; 85 | self.cursorColor = self.placeholderColor; 86 | self.textColor = self.placeholderColor; 87 | 88 | self.placeholderFontScale = 0.75; 89 | } 90 | 91 | #pragma mark - Overridden methods 92 | - (void)drawRect:(CGRect)rect { 93 | CGRect frame = CGRectMake(0, 0, CGRectGetWidth(rect), CGRectGetHeight(rect)); 94 | 95 | self.placeholderLabel.frame = CGRectInset(frame, placeholderInsets.x, placeholderInsets.y); 96 | self.placeholderLabel.font = [self placeholderFontFromFont:self.font]; 97 | 98 | [self updateBorder]; 99 | [self updatePlaceholder]; 100 | 101 | [self.layer addSublayer:self.borderLayer]; 102 | [self addSubview:self.placeholderLabel]; 103 | } 104 | 105 | - (CGRect)editingRectForBounds:(CGRect)bounds { 106 | return CGRectInset([self rectForBorderBounds:bounds], textFieldInsets.x, 0); 107 | } 108 | 109 | - (CGRect)textRectForBounds:(CGRect)bounds { 110 | return CGRectInset([self rectForBorderBounds:bounds], textFieldInsets.x, 0); 111 | } 112 | 113 | - (void)animateViewsForTextEntry { 114 | self.borderLayer.strokeEnd = 1; 115 | 116 | [UIView animateWithDuration:0.3 animations:^{ 117 | CGAffineTransform translate = CGAffineTransformMakeTranslation(-placeholderInsets.x, self.placeholderLabel.bounds.size.height + (placeholderInsets.y*2)); 118 | CGAffineTransform scale = CGAffineTransformMakeScale(0.9, 0.9); 119 | 120 | self.placeholderLabel.transform = CGAffineTransformConcat(translate, scale); 121 | } completion:^(BOOL finished) { 122 | if (self.didBeginEditingHandler != nil) { 123 | self.didBeginEditingHandler(); 124 | } 125 | }]; 126 | } 127 | 128 | - (void)animateViewsForTextDisplay { 129 | if (self.text.length == 0) { 130 | self.borderLayer.strokeEnd = [self percentageForBottomBorder]; 131 | 132 | [UIView animateWithDuration:0.3 animations:^{ 133 | self.placeholderLabel.transform = CGAffineTransformIdentity; 134 | } completion:^(BOOL finished) { 135 | if (self.didEndEditingHandler != nil) { 136 | self.didEndEditingHandler(); 137 | } 138 | }]; 139 | } 140 | } 141 | 142 | #pragma mark - Private methods 143 | - (void)updateBorder { 144 | CGRect rect = [self rectForBorderBounds:self.bounds]; 145 | 146 | UIBezierPath *path = [UIBezierPath bezierPath]; 147 | [path moveToPoint:CGPointMake(rect.origin.x+borderThickness, rect.size.height-borderThickness)]; 148 | [path addLineToPoint:CGPointMake(rect.size.width-borderThickness, rect.size.height-borderThickness)]; 149 | [path addLineToPoint:CGPointMake(rect.size.width-borderThickness, rect.origin.y+borderThickness)]; 150 | [path addLineToPoint:CGPointMake(rect.origin.x+borderThickness, rect.origin.y+borderThickness)]; 151 | [path closePath]; 152 | 153 | self.borderLayer.path = path.CGPath; 154 | self.borderLayer.lineCap = kCALineCapSquare; 155 | self.borderLayer.lineWidth = borderThickness; 156 | self.borderLayer.fillColor = [UIColor clearColor].CGColor; 157 | self.borderLayer.strokeColor = self.borderColor.CGColor; 158 | self.borderLayer.strokeEnd = [self percentageForBottomBorder]; 159 | } 160 | 161 | - (CGFloat)percentageForBottomBorder { 162 | CGRect borderRect = [self rectForBorderBounds:self.bounds]; 163 | CGFloat sumOfSides = (borderRect.size.width*2) + (borderRect.size.height*2); 164 | return (borderRect.size.width*100 / sumOfSides) / 100; 165 | } 166 | 167 | - (void)updatePlaceholder { 168 | self.placeholderLabel.text = self.placeholder; 169 | self.placeholderLabel.textColor = self.placeholderColor; 170 | [self.placeholderLabel sizeToFit]; 171 | [self layoutPlaceholderInTextRect]; 172 | 173 | if ([self isFirstResponder] || self.text.length!=0) { 174 | [self animateViewsForTextEntry]; 175 | } 176 | } 177 | 178 | - (UIFont *)placeholderFontFromFont:(UIFont *)font { 179 | UIFont *smallerFont = [UIFont fontWithName:font.fontName size:font.pointSize*self.placeholderFontScale]; 180 | 181 | return smallerFont; 182 | } 183 | 184 | - (CGRect)rectForBorderBounds:(CGRect)bounds { 185 | return CGRectMake(0, 0, CGRectGetWidth(bounds), CGRectGetHeight(bounds)-self.font.lineHeight-self.placeholderLabel.font.lineHeight+textFieldInsets.y); 186 | } 187 | 188 | - (void)layoutPlaceholderInTextRect { 189 | self.placeholderLabel.transform = CGAffineTransformIdentity; 190 | 191 | CGRect textRect = [self textRectForBounds:self.bounds]; 192 | CGFloat originX = textRect.origin.x; 193 | 194 | switch (self.textAlignment) { 195 | case NSTextAlignmentCenter: 196 | originX += textRect.size.width/2-self.placeholderLabel.bounds.size.width/2; 197 | break; 198 | case NSTextAlignmentRight: 199 | originX += textRect.size.width-self.placeholderLabel.bounds.size.width; 200 | break; 201 | default: 202 | break; 203 | } 204 | 205 | self.placeholderLabel.frame = CGRectMake(originX, CGRectGetHeight(textRect)-CGRectGetHeight(self.placeholderLabel.bounds)-placeholderInsets.y, CGRectGetWidth(self.placeholderLabel.bounds), CGRectGetHeight(self.placeholderLabel.bounds)); 206 | } 207 | 208 | @end 209 | -------------------------------------------------------------------------------- /CCTextFieldEffects/RuriTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // RuriTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/29/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | 10 | #import "RuriTextField.h" 11 | 12 | @interface RuriTextField () 13 | 14 | @property (strong, nonatomic) CALayer *borderLayer; 15 | 16 | @end 17 | 18 | @implementation RuriTextField 19 | 20 | #pragma mark - Constants 21 | static CGFloat const borderActiveThickness = 1; 22 | static CGFloat const borderInactiveThickness = 3; 23 | static CGPoint const textFieldInsets = {6, 6}; 24 | static CGPoint const placeholderInsets = {6, 6}; 25 | 26 | #pragma mark - Custom accessory 27 | - (void)setPlaceholderColor:(UIColor *)placeholderColor { 28 | _placeholderColor = placeholderColor; 29 | 30 | [self updatePlaceholder]; 31 | } 32 | 33 | - (void)setBorderColor:(UIColor *)borderColor { 34 | _borderColor = borderColor; 35 | 36 | [self updateBorder]; 37 | } 38 | 39 | - (void)setPlaceholderFontScale:(CGFloat)placeholderFontScale { 40 | _placeholderFontScale = placeholderFontScale; 41 | 42 | [self updatePlaceholder]; 43 | } 44 | 45 | - (void)setPlaceholder:(NSString *)placeholder { 46 | [super setPlaceholder:placeholder]; 47 | 48 | [self updatePlaceholder]; 49 | } 50 | 51 | - (void)setBounds:(CGRect)bounds { 52 | [super setBounds:bounds]; 53 | 54 | [self updateBorder]; 55 | [self updatePlaceholder]; 56 | } 57 | 58 | #pragma mark - Lifecycle 59 | - (instancetype)initWithFrame:(CGRect)frame { 60 | self = [super initWithFrame:frame]; 61 | 62 | if (self) { 63 | [self commonInit]; 64 | } 65 | 66 | return self; 67 | } 68 | 69 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 70 | self = [super initWithCoder:aDecoder]; 71 | 72 | if (self) { 73 | [self commonInit]; 74 | } 75 | return self; 76 | } 77 | 78 | - (void) commonInit { 79 | self.borderLayer = [[CALayer alloc] init]; 80 | self.placeholderLabel = [[UILabel alloc] init]; 81 | 82 | self.placeholderColor = [UIColor colorWithRed:0.4118 green:0.4118 blue:0.4118 alpha:1.0]; 83 | self.borderColor = [UIColor colorWithRed:0.7137 green:0.7647 blue:0.6745 alpha:1]; 84 | self.cursorColor = [UIColor whiteColor]; 85 | self.textColor = self.cursorColor; 86 | self.activeColor = [UIColor colorWithRed:0.6392 green:0.8275 blue:0.6118 alpha:1]; 87 | 88 | self.placeholderFontScale = 0.8; 89 | } 90 | 91 | #pragma mark - Overridden methods 92 | - (void)drawRect:(CGRect)rect { 93 | CGRect frame = CGRectMake(0, 0, CGRectGetWidth(rect), CGRectGetHeight(rect)); 94 | 95 | self.placeholderLabel.frame = CGRectInset(frame, placeholderInsets.x, placeholderInsets.y); 96 | self.placeholderLabel.font = [self placeholderFontFromFont:self.font]; 97 | 98 | [self updateBorder]; 99 | [self updatePlaceholder]; 100 | 101 | [self.layer addSublayer:self.borderLayer]; 102 | [self addSubview:self.placeholderLabel]; 103 | } 104 | 105 | - (CGRect)editingRectForBounds:(CGRect)bounds { 106 | return CGRectInset([self rectForBorderBounds:bounds], textFieldInsets.x, 0); 107 | } 108 | 109 | - (CGRect)textRectForBounds:(CGRect)bounds { 110 | return CGRectInset([self rectForBorderBounds:bounds], textFieldInsets.x, 0); 111 | } 112 | 113 | - (void)animateViewsForTextEntry { 114 | 115 | [UIView animateWithDuration:0.3 animations:^{ 116 | CGAffineTransform translate = CGAffineTransformMakeTranslation(-placeholderInsets.x, self.placeholderLabel.bounds.size.height + (placeholderInsets.y*2)); 117 | CGAffineTransform scale = CGAffineTransformMakeScale(0.9, 0.9); 118 | self.placeholderLabel.transform = CGAffineTransformConcat(translate, scale); 119 | self.placeholderLabel.textColor = self.activeColor; 120 | self.borderLayer.borderColor = self.activeColor.CGColor; 121 | 122 | CGRect rect = [self rectForBorderBounds:self.bounds]; 123 | self.borderLayer.frame = CGRectMake(0, CGRectGetHeight(rect)-borderActiveThickness, CGRectGetWidth(rect), borderActiveThickness); 124 | } completion:^(BOOL finished) { 125 | if (self.didBeginEditingHandler != nil) { 126 | self.didBeginEditingHandler(); 127 | } 128 | }]; 129 | } 130 | 131 | - (void)animateViewsForTextDisplay { 132 | if (self.text.length == 0) { 133 | 134 | [UIView animateWithDuration:0.3 animations:^{ 135 | self.placeholderLabel.transform = CGAffineTransformIdentity; 136 | self.placeholderLabel.textColor = self.placeholderColor; 137 | self.borderLayer.borderColor = self.borderColor.CGColor; 138 | 139 | CGRect rect = [self rectForBorderBounds:self.bounds]; 140 | self.borderLayer.frame = CGRectMake(0, CGRectGetHeight(rect)-borderInactiveThickness, CGRectGetWidth(rect), borderInactiveThickness); 141 | } completion:^(BOOL finished) { 142 | if (self.didEndEditingHandler != nil) { 143 | self.didEndEditingHandler(); 144 | } 145 | }]; 146 | } 147 | } 148 | 149 | #pragma mark - Private methods 150 | - (void)updateBorder { 151 | CGRect rect = [self rectForBorderBounds:self.bounds]; 152 | 153 | self.borderLayer.frame = CGRectMake(0, CGRectGetHeight(rect)-borderInactiveThickness, CGRectGetWidth(rect), borderInactiveThickness); 154 | self.borderLayer.borderColor = self.borderColor.CGColor; 155 | self.borderLayer.borderWidth = borderInactiveThickness; 156 | } 157 | 158 | - (CGFloat)percentageForBottomBorder { 159 | CGRect borderRect = [self rectForBorderBounds:self.bounds]; 160 | CGFloat sumOfSides = (borderRect.size.width*2) + (borderRect.size.height*2); 161 | return (borderRect.size.width*100 / sumOfSides) / 100; 162 | } 163 | 164 | - (void)updatePlaceholder { 165 | self.placeholderLabel.text = self.placeholder; 166 | self.placeholderLabel.textColor = self.placeholderColor; 167 | [self.placeholderLabel sizeToFit]; 168 | [self layoutPlaceholderInTextRect]; 169 | 170 | if ([self isFirstResponder] || self.text.length!=0) { 171 | [self animateViewsForTextEntry]; 172 | } 173 | } 174 | 175 | - (UIFont *)placeholderFontFromFont:(UIFont *)font { 176 | UIFont *smallerFont = [UIFont fontWithName:font.fontName size:font.pointSize*self.placeholderFontScale]; 177 | 178 | return smallerFont; 179 | } 180 | 181 | - (CGRect)rectForBorderBounds:(CGRect)bounds { 182 | return CGRectMake(0, 0, CGRectGetWidth(bounds), CGRectGetHeight(bounds)-self.font.lineHeight-textFieldInsets.y); 183 | } 184 | 185 | - (void)layoutPlaceholderInTextRect { 186 | self.placeholderLabel.transform = CGAffineTransformIdentity; 187 | 188 | CGRect textRect = [self textRectForBounds:self.bounds]; 189 | CGFloat originX = textRect.origin.x; 190 | 191 | switch (self.textAlignment) { 192 | case NSTextAlignmentCenter: 193 | originX += textRect.size.width/2-self.placeholderLabel.bounds.size.width/2; 194 | break; 195 | case NSTextAlignmentRight: 196 | originX += textRect.size.width-self.placeholderLabel.bounds.size.width; 197 | break; 198 | default: 199 | break; 200 | } 201 | 202 | self.placeholderLabel.frame = CGRectMake(originX, CGRectGetHeight(textRect)-CGRectGetHeight(self.placeholderLabel.bounds)-placeholderInsets.y, CGRectGetWidth(self.placeholderLabel.bounds), CGRectGetHeight(self.placeholderLabel.bounds)); 203 | } 204 | 205 | @end 206 | 207 | -------------------------------------------------------------------------------- /CCTextFieldEffects/ManamiTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // ManamiTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/30/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "ManamiTextField.h" 10 | 11 | @interface ManamiTextField () 12 | 13 | @property (strong, nonatomic) CALayer *borderLayer; 14 | @property (strong, nonatomic) CALayer *backgroundLayer; 15 | @property (strong, nonatomic) UIColor *backgroundLayerColor; 16 | 17 | @end 18 | 19 | @implementation ManamiTextField 20 | 21 | #pragma mark - Constants 22 | static CGFloat const borderThickness = 1.5; 23 | static CGPoint const textFieldInsets = {6, 6}; 24 | static CGPoint const placeholderInsets = {6, 6}; 25 | 26 | #pragma mark - Custom accessory 27 | - (void)setPlaceholderColor:(UIColor *)placeholderColor { 28 | _placeholderColor = placeholderColor; 29 | 30 | [self updatePlaceholder]; 31 | } 32 | 33 | - (void)setBorderColor:(UIColor *)borderColor { 34 | _borderColor = borderColor; 35 | 36 | [self updateBorder]; 37 | } 38 | 39 | - (void)setBackgroundColor:(UIColor *)backgroundColor { 40 | self.backgroundLayerColor = backgroundColor; 41 | 42 | self.backgroundLayer.backgroundColor = backgroundColor.CGColor; 43 | } 44 | 45 | - (UIColor *)backgroundColor { 46 | return self.backgroundLayerColor; 47 | } 48 | 49 | - (void)setPlaceholderFontScale:(CGFloat)placeholderFontScale { 50 | _placeholderFontScale = placeholderFontScale; 51 | 52 | [self updatePlaceholder]; 53 | } 54 | 55 | - (void)setPlaceholder:(NSString *)placeholder { 56 | [super setPlaceholder:placeholder]; 57 | 58 | [self updatePlaceholder]; 59 | } 60 | 61 | - (void)setBounds:(CGRect)bounds { 62 | [super setBounds:bounds]; 63 | 64 | [self updateBorder]; 65 | [self updatePlaceholder]; 66 | } 67 | 68 | #pragma mark - Lifecycle 69 | - (instancetype)initWithFrame:(CGRect)frame { 70 | self = [super initWithFrame:frame]; 71 | 72 | if (self) { 73 | [self commonInit]; 74 | } 75 | 76 | return self; 77 | } 78 | 79 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 80 | self = [super initWithCoder:aDecoder]; 81 | 82 | if (self) { 83 | [self commonInit]; 84 | } 85 | return self; 86 | } 87 | 88 | - (void) commonInit { 89 | self.borderLayer = [[CALayer alloc] init]; 90 | self.backgroundLayer = [[CALayer alloc] init]; 91 | self.placeholderLabel = [[UILabel alloc] init]; 92 | 93 | self.placeholderColor = [UIColor colorWithRed:0.4118 green:0.4118 blue:0.4118 alpha:1.0]; 94 | self.borderColor = [UIColor colorWithRed:0.6588 green:0.6588 blue:0.6588 alpha:1]; 95 | self.backgroundColor = self.borderColor; 96 | self.cursorColor = [UIColor colorWithRed:0.9765 green:0.9686 blue:0.9647 alpha:1]; 97 | self.textColor = self.cursorColor; 98 | 99 | self.placeholderFontScale = 0.9; 100 | } 101 | 102 | #pragma mark - Overridden methods 103 | - (void)drawRect:(CGRect)rect { 104 | CGRect frame = CGRectMake(0, 0, CGRectGetWidth(rect), CGRectGetHeight(rect)); 105 | 106 | self.placeholderLabel.frame = CGRectInset(frame, placeholderInsets.x, placeholderInsets.y); 107 | self.placeholderLabel.font = [self placeholderFontFromFont:self.font]; 108 | 109 | [self updateBorder]; 110 | [self updatePlaceholder]; 111 | 112 | [self.layer addSublayer:self.borderLayer]; 113 | [self addSubview:self.placeholderLabel]; 114 | 115 | CGRect backgroundRect = [self editingRectForBounds:self.bounds]; 116 | self.backgroundLayer.frame = CGRectMake(0, backgroundRect.origin.y, CGRectGetWidth(backgroundRect), 0); 117 | [self.layer addSublayer:self.backgroundLayer]; 118 | } 119 | 120 | - (CGRect)editingRectForBounds:(CGRect)bounds { 121 | return CGRectInset([self rectForBorderBounds:bounds], textFieldInsets.x, 0); 122 | } 123 | 124 | - (CGRect)textRectForBounds:(CGRect)bounds { 125 | return CGRectInset([self rectForBorderBounds:bounds], textFieldInsets.x, 0); 126 | } 127 | 128 | - (void)animateViewsForTextEntry { 129 | if (self.text.length == 0) { 130 | [UIView animateWithDuration:0.3 animations:^{ 131 | CGAffineTransform translate = CGAffineTransformMakeTranslation(-placeholderInsets.x, self.placeholderLabel.bounds.size.height + (placeholderInsets.y*2)); 132 | CGAffineTransform scale = CGAffineTransformMakeScale(0.9, 0.9); 133 | self.placeholderLabel.transform = CGAffineTransformConcat(translate, scale); 134 | self.placeholderLabel.alpha = 0.4; 135 | 136 | CGRect backgroundRect = [self editingRectForBounds:self.bounds]; 137 | self.backgroundLayer.frame = CGRectMake(0, backgroundRect.origin.y, CGRectGetWidth(backgroundRect), CGRectGetHeight(backgroundRect)); 138 | 139 | self.borderLayer.opacity = 0; 140 | } completion:^(BOOL finished) { 141 | if (self.didBeginEditingHandler != nil) { 142 | self.didBeginEditingHandler(); 143 | } 144 | }]; 145 | } 146 | } 147 | 148 | - (void)animateViewsForTextDisplay { 149 | if (self.text.length == 0) { 150 | 151 | [UIView animateWithDuration:0.3 animations:^{ 152 | self.placeholderLabel.transform = CGAffineTransformIdentity; 153 | self.placeholderLabel.alpha = 1; 154 | 155 | CGRect backgroundRect = [self editingRectForBounds:self.bounds]; 156 | self.backgroundLayer.frame = CGRectMake(0, backgroundRect.origin.y, CGRectGetWidth(backgroundRect), 0); 157 | 158 | self.borderLayer.opacity = 1; 159 | } completion:^(BOOL finished) { 160 | if (self.didEndEditingHandler != nil) { 161 | self.didEndEditingHandler(); 162 | } 163 | }]; 164 | } 165 | } 166 | 167 | #pragma mark - Private methods 168 | - (void)updateBorder { 169 | CGRect rect = [self rectForBorderBounds:self.bounds]; 170 | self.borderLayer.frame = CGRectMake(0, CGRectGetHeight(rect), CGRectGetWidth(rect), borderThickness); 171 | self.borderLayer.borderWidth = borderThickness; 172 | self.borderLayer.borderColor = self.borderColor.CGColor; 173 | } 174 | 175 | - (void)updatePlaceholder { 176 | self.placeholderLabel.text = self.placeholder; 177 | self.placeholderLabel.textColor = self.placeholderColor; 178 | [self.placeholderLabel sizeToFit]; 179 | [self layoutPlaceholderInTextRect]; 180 | 181 | if ([self isFirstResponder] || self.text.length!=0) { 182 | [self animateViewsForTextEntry]; 183 | } 184 | } 185 | 186 | - (UIFont *)placeholderFontFromFont:(UIFont *)font { 187 | UIFont *smallerFont = [UIFont fontWithName:font.fontName size:font.pointSize*self.placeholderFontScale]; 188 | 189 | return smallerFont; 190 | } 191 | 192 | - (CGRect)rectForBorderBounds:(CGRect)bounds { 193 | return CGRectMake(0, 0, CGRectGetWidth(bounds), CGRectGetHeight(bounds)-self.font.lineHeight-textFieldInsets.y); 194 | } 195 | 196 | - (void)layoutPlaceholderInTextRect { 197 | self.placeholderLabel.transform = CGAffineTransformIdentity; 198 | 199 | CGRect textRect = [self textRectForBounds:self.bounds]; 200 | CGFloat originX = textRect.origin.x; 201 | 202 | switch (self.textAlignment) { 203 | case NSTextAlignmentCenter: 204 | originX += textRect.size.width/2-self.placeholderLabel.bounds.size.width/2; 205 | break; 206 | case NSTextAlignmentRight: 207 | originX += textRect.size.width-self.placeholderLabel.bounds.size.width; 208 | break; 209 | default: 210 | break; 211 | } 212 | 213 | self.placeholderLabel.frame = CGRectMake(originX, CGRectGetHeight(textRect)-CGRectGetHeight(self.placeholderLabel.bounds)-placeholderInsets.y, CGRectGetWidth(self.placeholderLabel.bounds), CGRectGetHeight(self.placeholderLabel.bounds)); 214 | } 215 | 216 | @end 217 | 218 | 219 | -------------------------------------------------------------------------------- /CCTextFieldEffects/HoshiTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // HoshiTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/25/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "HoshiTextField.h" 10 | 11 | @interface HoshiTextField () 12 | 13 | @property (strong, nonatomic) CALayer *inactiveBorderLayer; 14 | @property (strong, nonatomic) CALayer *activeBorderLayer; 15 | @property (nonatomic) CGPoint activePlaceholderPoint; 16 | 17 | @end 18 | 19 | @implementation HoshiTextField 20 | 21 | #pragma mark - Constants 22 | static CGFloat const activeBorderThickness = 2; 23 | static CGFloat const inactiveBorderThickness = 0.7; 24 | static CGPoint const textFieldInsets = {0, 12}; 25 | static CGPoint const placeholderInsets = {0, 6}; 26 | 27 | #pragma mark - Custom accessorys 28 | - (void)setBorderInactiveColor:(UIColor *)borderInactiveColor { 29 | _borderInactiveColor = borderInactiveColor; 30 | 31 | [self updateBorder]; 32 | } 33 | 34 | - (void)setBorderActiveColor:(UIColor *)borderActiveColor { 35 | _borderActiveColor = borderActiveColor; 36 | 37 | [self updateBorder]; 38 | } 39 | 40 | - (void)setPlaceholderColor:(UIColor *)placeholderColor { 41 | _placeholderColor = placeholderColor; 42 | 43 | [self updatePlaceholder]; 44 | } 45 | 46 | - (void)setPlaceholderFontScale:(CGFloat)placeholderFontScale { 47 | _placeholderFontScale = placeholderFontScale; 48 | 49 | [self updatePlaceholder]; 50 | } 51 | 52 | - (void)setPlaceholder:(NSString *)placeholder { 53 | [super setPlaceholder:placeholder]; 54 | 55 | [self updatePlaceholder]; 56 | } 57 | 58 | - (void)setBounds:(CGRect)bounds { 59 | [super setBounds:bounds]; 60 | 61 | [self updateBorder]; 62 | [self updatePlaceholder]; 63 | } 64 | 65 | #pragma mark - Lifecycle 66 | - (instancetype)initWithFrame:(CGRect)frame { 67 | self = [super initWithFrame:frame]; 68 | 69 | if (self) { 70 | [self commonInit]; 71 | } 72 | 73 | return self; 74 | } 75 | 76 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 77 | self = [super initWithCoder:aDecoder]; 78 | 79 | if (self) { 80 | [self commonInit]; 81 | } 82 | return self; 83 | } 84 | 85 | - (void) commonInit { 86 | self.inactiveBorderLayer = [[CALayer alloc] init]; 87 | self.activeBorderLayer = [[CALayer alloc] init]; 88 | self.placeholderLabel = [[UILabel alloc] init]; 89 | 90 | self.borderInactiveColor = [UIColor colorWithRed:0.7255 green:0.7569 blue:0.7922 alpha:1.0]; 91 | self.borderActiveColor = [UIColor colorWithRed:0.4157 green:0.4745 blue:0.5373 alpha:1.0]; 92 | self.placeholderColor = self.borderInactiveColor; 93 | self.cursorColor = [UIColor colorWithRed:0.349 green:0.3725 blue:0.4314 alpha:1.0]; 94 | self.textColor = [UIColor colorWithRed:0.2785 green:0.2982 blue:0.3559 alpha:1.0]; 95 | 96 | self.placeholderFontScale = 0.65; 97 | self.activePlaceholderPoint = CGPointZero; 98 | } 99 | 100 | #pragma mark - Overridden methods 101 | - (void)drawRect:(CGRect)rect { 102 | CGRect frame = CGRectMake(0, 0, rect.size.width, rect.size.height); 103 | self.placeholderLabel.frame = CGRectInset(frame, placeholderInsets.x, placeholderInsets.y); 104 | self.placeholderLabel.font = [self placeholderFontFromFont:self.font]; 105 | 106 | [self updateBorder]; 107 | [self updatePlaceholder]; 108 | 109 | [self.layer addSublayer:self.inactiveBorderLayer]; 110 | [self.layer addSublayer:self.activeBorderLayer]; 111 | [self addSubview:self.placeholderLabel]; 112 | } 113 | 114 | - (CGRect)editingRectForBounds:(CGRect)bounds { 115 | return CGRectOffset(bounds, textFieldInsets.x, textFieldInsets.y); 116 | } 117 | 118 | - (CGRect)textRectForBounds:(CGRect)bounds { 119 | return CGRectOffset(bounds, textFieldInsets.x, textFieldInsets.y); 120 | } 121 | 122 | - (void)animateViewsForTextEntry { 123 | if (self.text.length == 0) { 124 | [UIView animateWithDuration:0.35 delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:1.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ 125 | self.placeholderLabel.frame = CGRectMake(10, self.placeholderLabel.frame.origin.y, CGRectGetWidth(self.placeholderLabel.frame), CGRectGetHeight(self.placeholderLabel.frame)); 126 | self.placeholderLabel.alpha = 0; 127 | } completion:^(BOOL finished) { 128 | if (self.didBeginEditingHandler != nil) { 129 | self.didBeginEditingHandler(); 130 | } 131 | }]; 132 | } 133 | 134 | [self layoutPlaceholderInTextRect]; 135 | self.placeholderLabel.frame = CGRectMake(self.activePlaceholderPoint.x, self.activePlaceholderPoint.y, CGRectGetWidth(self.placeholderLabel.frame), CGRectGetHeight(self.placeholderLabel.frame)); 136 | 137 | [UIView animateWithDuration:0.2 animations:^{ 138 | self.placeholderLabel.alpha = 0.5; 139 | }]; 140 | 141 | self.activeBorderLayer.frame = [self rectForBorderThickness:activeBorderThickness isFilled:YES]; 142 | } 143 | 144 | - (void)animateViewsForTextDisplay { 145 | if (self.text.length == 0) { 146 | [UIView animateWithDuration:0.35 delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:2.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ 147 | [self layoutPlaceholderInTextRect]; 148 | self.placeholderLabel.alpha = 1.0; 149 | } completion:^(BOOL finished) { 150 | if (self.didEndEditingHandler != nil) { 151 | self.didEndEditingHandler(); 152 | } 153 | }]; 154 | 155 | self.activeBorderLayer.frame = [self rectForBorderThickness:activeBorderThickness isFilled:NO]; 156 | } 157 | } 158 | 159 | #pragma mark - Private methods 160 | - (void)updateBorder{ 161 | self.inactiveBorderLayer.frame = [self rectForBorderThickness:inactiveBorderThickness isFilled:YES]; 162 | self.inactiveBorderLayer.backgroundColor = self.borderInactiveColor.CGColor; 163 | 164 | self.activeBorderLayer.frame = [self rectForBorderThickness:activeBorderThickness isFilled:NO]; 165 | self.activeBorderLayer.backgroundColor = self.borderActiveColor.CGColor; 166 | } 167 | 168 | - (void)updatePlaceholder { 169 | self.placeholderLabel.text = self.placeholder; 170 | self.placeholderLabel.textColor = self.placeholderColor; 171 | [self.placeholderLabel sizeToFit]; 172 | [self layoutPlaceholderInTextRect]; 173 | 174 | if ([self isFirstResponder] || self.text.length!=0) { 175 | [self animateViewsForTextEntry]; 176 | } 177 | } 178 | 179 | - (UIFont *)placeholderFontFromFont:(UIFont *)font { 180 | UIFont *smallerFont = [UIFont fontWithName:font.fontName size:font.pointSize*self.placeholderFontScale]; 181 | 182 | return smallerFont; 183 | } 184 | 185 | - (CGRect)rectForBorderThickness:(CGFloat)thickness isFilled:(BOOL)isFilled { 186 | if (isFilled) { 187 | return CGRectMake(0, CGRectGetHeight(self.frame)-thickness, CGRectGetWidth(self.frame), thickness); 188 | } else { 189 | return CGRectMake(0, CGRectGetHeight(self.frame)-thickness, 0, thickness); 190 | } 191 | } 192 | 193 | - (void)layoutPlaceholderInTextRect { 194 | CGRect textRect = [self textRectForBounds:self.bounds]; 195 | CGFloat originX = textRect.origin.x; 196 | 197 | switch (self.textAlignment) { 198 | case NSTextAlignmentCenter: 199 | originX += textRect.size.width/2-self.placeholderLabel.bounds.size.width/2; 200 | break; 201 | case NSTextAlignmentRight: 202 | originX += textRect.size.width-self.placeholderLabel.bounds.size.width; 203 | break; 204 | default: 205 | break; 206 | } 207 | 208 | self.placeholderLabel.frame = CGRectMake(originX, textRect.size.height/2, CGRectGetWidth(self.placeholderLabel.bounds), CGRectGetHeight(self.placeholderLabel.bounds)); 209 | self.activePlaceholderPoint = CGPointMake(self.placeholderLabel.frame.origin.x, self.placeholderLabel.frame.origin.y-self.placeholderLabel.frame.size.height-placeholderInsets.y); 210 | } 211 | 212 | @end 213 | -------------------------------------------------------------------------------- /CCTextFieldEffects/KuroTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // KuroTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/29/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "KuroTextField.h" 10 | 11 | @interface KuroTextField () 12 | 13 | @property (strong ,nonatomic) CAShapeLayer *leftLayer; 14 | @property (strong, nonatomic) CAShapeLayer *rightLayer; 15 | @property (nonatomic) CGFloat placeholderHeight; 16 | 17 | @end 18 | 19 | 20 | /** 21 | When I implement the original effect for Kuro with two CAShpaLayer, there is a issue for text alignment (thoungh I do not think it is the problem of CAShapeLayer), So I made some change to Kuro. 22 | The current effect for Kuro can be implemented simply by a CALayer. There is not need to use two CAShapeLayer. But I am somehow lazy to modify the code. 23 | // TODO: Use single CALayer. 24 | */ 25 | @implementation KuroTextField 26 | 27 | # pragma mark - Constants 28 | static CGFloat const borderThickness = 3; 29 | static CGFloat const borderMoveDistance = 12; 30 | static CGPoint const placeholderInset = {10,2}; 31 | static CGPoint const textFieldInset = {6,0}; 32 | 33 | # pragma mark - Custom accessorys 34 | - (void)setBorderColor:(UIColor *)borderColor { 35 | _borderColor = borderColor; 36 | 37 | self.leftLayer.strokeColor = borderColor.CGColor; 38 | self.rightLayer.strokeColor = borderColor.CGColor; 39 | } 40 | 41 | - (void)setPlaceholderColor:(UIColor *)placeholderColor { 42 | _placeholderColor = placeholderColor; 43 | 44 | self.placeholderLabel.textColor = placeholderColor; 45 | } 46 | 47 | - (void)setPlaceholderFontScale:(CGFloat)placeholderFontScale { 48 | _placeholderFontScale = placeholderFontScale; 49 | 50 | self.placeholderLabel.font = [self placeholderFontFromFont:self.font]; 51 | } 52 | 53 | - (void)setPlaceholder:(NSString *)placeholder { 54 | [super setPlaceholder:placeholder]; 55 | 56 | self.placeholderLabel.text = placeholder; 57 | } 58 | 59 | - (CGFloat)placeholderHeight { 60 | return self.placeholderLabel.font.lineHeight; 61 | } 62 | 63 | # pragma mark - Lifecycle 64 | - (instancetype)initWithFrame:(CGRect)frame { 65 | self = [super initWithFrame:frame]; 66 | 67 | if (self) { 68 | [self commonInit]; 69 | } 70 | 71 | return self; 72 | } 73 | 74 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 75 | self = [super initWithCoder:aDecoder]; 76 | 77 | if (self) { 78 | [self commonInit]; 79 | } 80 | return self; 81 | } 82 | 83 | - (void) commonInit { 84 | self.leftLayer = [[CAShapeLayer alloc] init]; 85 | self.leftLayer.fillColor = [UIColor clearColor].CGColor; 86 | self.leftLayer.borderColor = self.leftLayer.fillColor; 87 | self.leftLayer.lineWidth = borderThickness; 88 | 89 | self.rightLayer = [[CAShapeLayer alloc] init]; 90 | self.rightLayer.fillColor = [UIColor clearColor].CGColor; 91 | self.rightLayer.borderColor = self.rightLayer.fillColor; 92 | self.rightLayer.lineWidth = borderThickness; 93 | 94 | self.placeholderLabel = [[UILabel alloc] init]; 95 | 96 | self.borderColor = [UIColor colorWithRed:0.4549 green:0.4745 blue:0.5059 alpha:1]; 97 | self.placeholderColor = [UIColor colorWithRed:0.8745 green:0.3961 blue:0.5373 alpha:1]; 98 | self.cursorColor = [UIColor colorWithRed:0.5686 green:0.5882 blue:0.6314 alpha:1]; 99 | self.textColor = self.cursorColor; 100 | 101 | self.placeholderFontScale = 0.85; 102 | } 103 | 104 | # pragma mark - Overridden methods 105 | - (void)drawRect:(CGRect)rect { 106 | UIBezierPath *leftPath = [UIBezierPath bezierPath]; 107 | [leftPath moveToPoint:CGPointMake(CGRectGetWidth(rect)/2+borderMoveDistance*2,borderThickness/2)]; 108 | [leftPath addLineToPoint:CGPointMake(borderMoveDistance+borderThickness,borderThickness/2)]; 109 | [leftPath addLineToPoint:CGPointMake(borderMoveDistance+borderThickness,CGRectGetHeight(rect)-borderThickness-placeholderInset.y-self.placeholderHeight)]; 110 | [leftPath addLineToPoint:CGPointMake(CGRectGetWidth(rect)/2+2*borderMoveDistance,CGRectGetHeight(rect)-borderThickness-placeholderInset.y-self.placeholderHeight)]; 111 | self.leftLayer.path = leftPath.CGPath; 112 | [self.layer addSublayer:self.leftLayer]; 113 | 114 | UIBezierPath *rightPath = [UIBezierPath bezierPath]; 115 | [rightPath moveToPoint:CGPointMake(CGRectGetWidth(rect)/2,borderThickness/2)]; 116 | [rightPath addLineToPoint:CGPointMake(CGRectGetWidth(rect)-borderMoveDistance-borderThickness,borderThickness/2)]; 117 | [rightPath addLineToPoint:CGPointMake(CGRectGetWidth(rect)-borderMoveDistance-borderThickness,CGRectGetHeight(rect)-borderThickness-placeholderInset.y-self.placeholderHeight)]; 118 | [rightPath addLineToPoint:CGPointMake(CGRectGetWidth(rect)/2,CGRectGetHeight(rect)-borderThickness-placeholderInset.y-self.placeholderHeight)]; 119 | self.rightLayer.path = rightPath.CGPath; 120 | [self.layer addSublayer:self.rightLayer]; 121 | 122 | self.placeholderLabel.frame = CGRectMake(placeholderInset.x+borderMoveDistance, (CGRectGetHeight([self textRectForBounds:rect])-self.placeholderHeight)/2+2*borderThickness, CGRectGetWidth(rect), self.placeholderHeight); 123 | [self.placeholderLabel sizeToFit]; 124 | [self addSubview:self.placeholderLabel]; 125 | } 126 | 127 | - (CGRect)textRectForBounds:(CGRect)bounds { 128 | CGRect newBounds = CGRectMake(0, 0, CGRectGetWidth(bounds), CGRectGetHeight(bounds)-borderThickness-placeholderInset.y-self.placeholderHeight); 129 | 130 | return CGRectInset(newBounds, 1.5*borderThickness+textFieldInset.x, 1.5*borderThickness); 131 | } 132 | 133 | - (CGRect)editingRectForBounds:(CGRect)bounds { 134 | CGRect newBounds = CGRectMake(0, 0, CGRectGetWidth(bounds), CGRectGetHeight(bounds)-borderThickness-placeholderInset.y-self.placeholderHeight); 135 | 136 | return CGRectInset(newBounds, 1.5*borderThickness+textFieldInset.x, 1.5*borderThickness); 137 | } 138 | 139 | - (void)animateViewsForTextEntry { 140 | if (self.text.length == 0) { 141 | // Hide cursor when animating. 142 | UIColor *originalCursorColor = self.cursorColor; 143 | self.cursorColor = [UIColor clearColor]; 144 | 145 | [UIView transitionWithView:self.placeholderLabel duration:0.35 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ 146 | self.placeholderLabel.transform = CGAffineTransformMakeScale(0.001, 0.001); 147 | self.leftLayer.frame = CGRectOffset(self.leftLayer.frame, -borderMoveDistance, 0); 148 | self.rightLayer.frame = CGRectOffset(self.rightLayer.frame, borderMoveDistance, 0); 149 | } completion:^(BOOL finished) { 150 | [UIView animateWithDuration:0.1 animations:^{ 151 | self.placeholderLabel.frame = CGRectOffset(self.placeholderLabel.frame, -borderMoveDistance, CGRectGetHeight(self.bounds)*0.5-0.75*borderThickness-0.5*placeholderInset.y); 152 | self.placeholderLabel.transform = CGAffineTransformIdentity; 153 | } completion:^(BOOL finished) { 154 | self.cursorColor = originalCursorColor; 155 | 156 | if (self.didBeginEditingHandler != nil) { 157 | self.didBeginEditingHandler(); 158 | } 159 | }]; 160 | }]; 161 | } 162 | } 163 | 164 | - (void)animateViewsForTextDisplay { 165 | if (self.text.length == 0) { 166 | [UIView transitionWithView:self.placeholderLabel duration:0.35 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ 167 | self.placeholderLabel.transform = CGAffineTransformMakeScale(0.001, 0.001); 168 | self.leftLayer.frame = CGRectOffset(self.leftLayer.frame, borderMoveDistance, 0); 169 | self.rightLayer.frame = CGRectOffset(self.rightLayer.frame, -borderMoveDistance, 0); 170 | } completion:^(BOOL finished) { 171 | [UIView animateWithDuration:0.2 animations:^{ 172 | self.placeholderLabel.frame = CGRectOffset(self.placeholderLabel.frame, borderMoveDistance, -CGRectGetHeight(self.bounds)*0.5+0.75*borderThickness+0.5*placeholderInset.y); 173 | self.placeholderLabel.transform = CGAffineTransformIdentity; 174 | } completion:^(BOOL finished) { 175 | if (self.didEndEditingHandler != nil) { 176 | self.didEndEditingHandler(); 177 | } 178 | }]; 179 | }]; 180 | } 181 | } 182 | 183 | # pragma mark - Private methods 184 | - (UIFont *)placeholderFontFromFont:(UIFont *)font { 185 | UIFont *smallerFont = [UIFont fontWithName:self.font.fontName size:self.font.pointSize*self.placeholderFontScale]; 186 | 187 | return smallerFont; 188 | } 189 | 190 | @end 191 | -------------------------------------------------------------------------------- /CCTextFieldEffects/YokoTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // YokoTextField.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/26/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "YokoTextField.h" 10 | 11 | @interface YokoTextField () 12 | 13 | @property (strong, nonatomic) UIView *foregroundView; 14 | @property (strong, nonatomic) CALayer *foregroundLayer; 15 | 16 | @end 17 | 18 | @implementation YokoTextField 19 | 20 | #pragma mark - Constants 21 | static CGFloat const borderThickness = 3; 22 | static CGPoint const textFieldInsets = {6, 6}; 23 | //static CGPoint const placeholderInsets = {6, 6}; 24 | 25 | #pragma mark - Custom accessorys 26 | - (void)setPlaceholderColor:(UIColor *)placeholderColor { 27 | _placeholderColor = placeholderColor; 28 | 29 | [self updatePlaceholder]; 30 | } 31 | 32 | - (void)setForegroundColor:(UIColor *)foregroundColor { 33 | _foregroundColor = foregroundColor; 34 | 35 | [self updateForeground]; 36 | } 37 | 38 | - (void)setPlaceholderFontScale:(CGFloat)placeholderFontScale { 39 | _placeholderFontScale = placeholderFontScale; 40 | 41 | [self updatePlaceholder]; 42 | } 43 | 44 | - (void)setPlaceholder:(NSString *)placeholder { 45 | [super setPlaceholder:placeholder]; 46 | 47 | [self updatePlaceholder]; 48 | } 49 | 50 | - (void)setBounds:(CGRect)bounds { 51 | [super setBounds:bounds]; 52 | 53 | [self updateForeground]; 54 | [self updatePlaceholder]; 55 | } 56 | 57 | #pragma mark - Lifecycle 58 | - (instancetype)initWithFrame:(CGRect)frame { 59 | self = [super initWithFrame:frame]; 60 | 61 | if (self) { 62 | [self commonInit]; 63 | } 64 | 65 | return self; 66 | } 67 | 68 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 69 | self = [super initWithCoder:aDecoder]; 70 | 71 | if (self) { 72 | [self commonInit]; 73 | } 74 | return self; 75 | } 76 | 77 | - (void) commonInit { 78 | self.foregroundView = [[UIView alloc] init]; 79 | self.foregroundLayer = [[CALayer alloc] init]; 80 | self.placeholderLabel = [[UILabel alloc] init]; 81 | 82 | self.placeholderColor = [UIColor colorWithRed:0.6902 green:0.2941 blue:0.2501 alpha:1.0]; 83 | self.foregroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1]; 84 | self.cursorColor = [UIColor colorWithRed:0.9608 green:0.9608 blue:0.9608 alpha:1.0]; 85 | self.textColor = self.cursorColor; 86 | 87 | self.placeholderFontScale = 0.7; 88 | } 89 | 90 | #pragma mark - Overridden methods 91 | - (void)drawRect:(CGRect)rect { 92 | [self updateForeground]; 93 | [self updatePlaceholder]; 94 | 95 | [self addSubview:self.foregroundView]; 96 | [self addSubview:self.placeholderLabel]; 97 | [self.layer addSublayer:self.foregroundLayer]; 98 | } 99 | 100 | - (CGRect)editingRectForBounds:(CGRect)bounds { 101 | CGRect newBounds = CGRectMake(0, 0, CGRectGetWidth(bounds), CGRectGetHeight(bounds)-self.font.lineHeight+textFieldInsets.y); 102 | 103 | return CGRectInset(newBounds, textFieldInsets.x, 0); 104 | } 105 | 106 | - (CGRect)textRectForBounds:(CGRect)bounds { 107 | CGRect newBounds = CGRectMake(0, 0, CGRectGetWidth(bounds), CGRectGetHeight(bounds)-self.font.lineHeight+textFieldInsets.y); 108 | 109 | return CGRectInset(newBounds, textFieldInsets.x, 0); 110 | } 111 | 112 | - (void)animateViewsForTextEntry { 113 | [UIView animateWithDuration:0.4 delay:0 usingSpringWithDamping:1.0 initialSpringVelocity:0.6 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ 114 | self.foregroundView.layer.transform = CATransform3DIdentity; 115 | } completion:^(BOOL finished) { 116 | if (self.didBeginEditingHandler != nil) { 117 | self.didBeginEditingHandler(); 118 | } 119 | }]; 120 | 121 | self.foregroundLayer.frame = [self rectForBorderBounds:self.foregroundView.frame isFilled:NO]; 122 | } 123 | 124 | - (void)animateViewsForTextDisplay { 125 | if (self.text.length == 0) { 126 | [UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:1.0 initialSpringVelocity:0.6 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ 127 | self.foregroundLayer.frame = [self rectForBorderBounds:self.foregroundView.frame isFilled:YES]; 128 | self.foregroundView.layer.transform = [self rotationAndPerspectiveTransformForView:self.foregroundView]; 129 | } completion:^(BOOL finished) { 130 | if (self.didEndEditingHandler != nil) { 131 | self.didEndEditingHandler(); 132 | } 133 | }]; 134 | } 135 | } 136 | 137 | #pragma mark - Private methods 138 | - (void)updatePlaceholder { 139 | self.placeholderLabel.font = [self placeholderFontFromFont:self.font]; 140 | self.placeholderLabel.text = self.placeholder; 141 | self.placeholderLabel.textColor = self.placeholderColor; 142 | [self.placeholderLabel sizeToFit]; 143 | [self layoutPlaceholderInTextRect]; 144 | 145 | if ([self isFirstResponder] || self.text.length!=0) { 146 | [self animateViewsForTextEntry]; 147 | } 148 | } 149 | 150 | - (void)updateForeground { 151 | self.foregroundView.frame = [self rectForForegroundBounds:self.frame]; 152 | self.foregroundView.userInteractionEnabled = NO; 153 | self.foregroundView.layer.transform = [self rotationAndPerspectiveTransformForView:self.foregroundView]; 154 | self.foregroundView.backgroundColor = [self colorWithColor:self.foregroundColor alphaFactor:0.5]; 155 | 156 | self.foregroundLayer.frame = [self rectForBorderBounds:self.foregroundView.frame isFilled:YES]; 157 | self.foregroundLayer.borderWidth = borderThickness; 158 | self.foregroundLayer.borderColor = [self colorWithColor:self.foregroundColor alphaFactor:0.5].CGColor; 159 | } 160 | 161 | - (UIFont *)placeholderFontFromFont:(UIFont *)font { 162 | UIFont *smallerFont = [UIFont fontWithName:font.fontName size:font.pointSize*self.placeholderFontScale]; 163 | 164 | return smallerFont; 165 | } 166 | 167 | - (CGRect)rectForForegroundBounds:(CGRect)bounds { 168 | return CGRectMake(0, 0, CGRectGetWidth(bounds), CGRectGetHeight(bounds)-self.font.lineHeight+textFieldInsets.y-borderThickness); 169 | } 170 | 171 | - (CGRect)rectForBorderBounds:(CGRect)bounds isFilled:(BOOL)isFilled { 172 | CGRect newRect = CGRectMake(0, CGRectGetHeight(bounds), CGRectGetWidth(bounds), isFilled?borderThickness:0); 173 | 174 | if (!CATransform3DIsIdentity(self.foregroundView.layer.transform)) { 175 | newRect = CGRectMake(0, bounds.origin.y, CGRectGetWidth(newRect), CGRectGetHeight(newRect)); 176 | } 177 | 178 | return newRect; 179 | } 180 | 181 | - (void)layoutPlaceholderInTextRect { 182 | CGRect textRect = [self textRectForBounds:self.bounds]; 183 | CGFloat originX = textRect.origin.x; 184 | 185 | switch (self.textAlignment) { 186 | case NSTextAlignmentCenter: 187 | originX += textRect.size.width/2-self.placeholderLabel.bounds.size.width/2; 188 | break; 189 | case NSTextAlignmentRight: 190 | originX += textRect.size.width-self.placeholderLabel.bounds.size.width; 191 | break; 192 | default: 193 | break; 194 | } 195 | 196 | self.placeholderLabel.frame = CGRectMake(originX, CGRectGetHeight(self.bounds)-CGRectGetHeight(self.placeholderLabel.frame), CGRectGetWidth(self.placeholderLabel.frame), CGRectGetHeight(self.placeholderLabel.frame)); 197 | } 198 | 199 | - (void)setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view { 200 | CGPoint newPoint = CGPointMake(CGRectGetWidth(view.bounds)*anchorPoint.x, CGRectGetHeight(view.bounds)*anchorPoint.y); 201 | CGPoint oldPoint = CGPointMake(CGRectGetWidth(view.bounds)*view.layer.anchorPoint.x, CGRectGetHeight(view.bounds)*view.layer.anchorPoint.y); 202 | 203 | newPoint = CGPointApplyAffineTransform(newPoint, view.transform); 204 | oldPoint = CGPointApplyAffineTransform(oldPoint, view.transform); 205 | 206 | CGPoint position = view.layer.position; 207 | 208 | position.x -= oldPoint.x; 209 | position.x += newPoint.x; 210 | 211 | position.y -= oldPoint.y; 212 | position.y += newPoint.y; 213 | 214 | view.layer.position = position; 215 | view.layer.anchorPoint = anchorPoint; 216 | } 217 | 218 | - (UIColor *)colorWithColor:(UIColor *)color alphaFactor:(CGFloat)factor { 219 | CGFloat hue = 0; 220 | CGFloat saturation = 0; 221 | CGFloat brightness = 0; 222 | CGFloat alpha = 0; 223 | 224 | if ([color getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha]) { 225 | return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:alpha*factor]; 226 | } else { 227 | return color; 228 | } 229 | } 230 | 231 | - (CATransform3D)rotationAndPerspectiveTransformForView:(UIView *)view { 232 | [self setAnchorPoint:CGPointMake(0.5, 1.0) forView:view]; 233 | 234 | CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity; 235 | rotationAndPerspectiveTransform.m34 = 1.0/800; 236 | CGFloat radians = -90/180.0*M_PI; 237 | rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, radians, 1.0, 0.0, 0.0); 238 | return rotationAndPerspectiveTransform; 239 | } 240 | 241 | @end 242 | -------------------------------------------------------------------------------- /CCTextFieldEffectsDemo/DetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DetailViewController.m 3 | // CCTextFieldEffects 4 | // 5 | // Created by Kelvin on 6/25/16. 6 | // Copyright © 2016 Cokile. All rights reserved. 7 | // 8 | 9 | #import "DetailViewController.h" 10 | #import "CCTextFieldEffects.h" 11 | 12 | @interface DetailViewController () 13 | 14 | @property (nonatomic) CGRect highFrame; 15 | @property (nonatomic) CGRect lowFrame; 16 | 17 | @end 18 | 19 | @implementation DetailViewController 20 | 21 | #pragma mark - Lifecycle 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | self.view.backgroundColor = [UIColor colorWithRed:self.red/255 green:self.green/255 blue:self.blue/255 alpha:1]; 26 | 27 | self.highFrame = CGRectMake(16, self.navigationController.navigationBar.frame.size.height+80, CGRectGetWidth(self.view.frame)-32, 70); 28 | 29 | self.lowFrame = CGRectMake(16, self.highFrame.origin.y+CGRectGetHeight(self.highFrame)+40, CGRectGetWidth(self.view.frame)-32, 70); 30 | } 31 | 32 | - (void)viewWillAppear:(BOOL)animated { 33 | [super viewWillAppear:animated]; 34 | 35 | if ([self.title isEqualToString:@"Akira"]) { 36 | AkiraTextField *tf1 = [[AkiraTextField alloc] initWithFrame:self.highFrame]; 37 | tf1.placeholder = @"First Name"; 38 | [self.view addSubview:tf1]; 39 | 40 | AkiraTextField *tf2 = [[AkiraTextField alloc] initWithFrame:self.lowFrame]; 41 | tf2.placeholder = @"Last Name"; 42 | [self.view addSubview:tf2]; 43 | } else if ([self.title isEqualToString:@"Hoshi"]) { 44 | HoshiTextField *tf1 = [[HoshiTextField alloc] initWithFrame:self.highFrame]; 45 | tf1.placeholder = @"First Name"; 46 | [self.view addSubview:tf1]; 47 | 48 | HoshiTextField *tf2 = [[HoshiTextField alloc] initWithFrame:self.lowFrame]; 49 | tf2.placeholder = @"Last Name"; 50 | [self.view addSubview:tf2]; 51 | } else if ([self.title isEqualToString:@"Isao"]) { 52 | IsaoTextField *tf1 = [[IsaoTextField alloc] initWithFrame:self.highFrame]; 53 | tf1.placeholder = @"First Name"; 54 | [self.view addSubview:tf1]; 55 | 56 | IsaoTextField *tf2 = [[IsaoTextField alloc] initWithFrame:self.lowFrame]; 57 | tf2.placeholder = @"Last Name"; 58 | [self.view addSubview:tf2]; 59 | } else if ([self.title isEqualToString:@"Jiro"]) { 60 | JiroTextField *tf1 = [[JiroTextField alloc] initWithFrame:self.highFrame]; 61 | tf1.placeholder = @"First Name"; 62 | [self.view addSubview:tf1]; 63 | 64 | JiroTextField *tf2 = [[JiroTextField alloc] initWithFrame:self.lowFrame]; 65 | tf2.placeholder = @"Last Name"; 66 | [self.view addSubview:tf2]; 67 | } else if ([self.title isEqualToString:@"Kaede"]) { 68 | KaedeTextField *tf1 = [[KaedeTextField alloc] initWithFrame:CGRectInset(self.highFrame, 0, 7)]; 69 | tf1.placeholder = @"First Name"; 70 | [self.view addSubview:tf1]; 71 | 72 | KaedeTextField *tf2 = [[KaedeTextField alloc] initWithFrame:CGRectInset(self.lowFrame, 0, 7)]; 73 | tf2.placeholder = @"Last Name"; 74 | [self.view addSubview:tf2]; 75 | } else if ([self.title isEqualToString:@"Madoka"]) { 76 | MadokaTextField *tf1 = [[MadokaTextField alloc] initWithFrame:self.highFrame]; 77 | tf1.placeholder = @"First Name"; 78 | [self.view addSubview:tf1]; 79 | 80 | MadokaTextField *tf2 = [[MadokaTextField alloc] initWithFrame:self.lowFrame]; 81 | tf2.placeholder = @"Last Name"; 82 | [self.view addSubview:tf2]; 83 | } else if ([self.title isEqualToString:@"Yoko"]) { 84 | YokoTextField *tf1 = [[YokoTextField alloc] initWithFrame:self.highFrame]; 85 | tf1.placeholder = @"First Name"; 86 | [self.view addSubview:tf1]; 87 | 88 | YokoTextField *tf2 = [[YokoTextField alloc] initWithFrame:self.lowFrame]; 89 | tf2.placeholder = @"Last Name"; 90 | [self.view addSubview:tf2]; 91 | } else if ([self.title isEqualToString:@"Yoshiko"]) { 92 | YoshikoTextField *tf1 = [[YoshikoTextField alloc] initWithFrame:self.highFrame]; 93 | tf1.placeholder = @"First Name"; 94 | [self.view addSubview:tf1]; 95 | 96 | YoshikoTextField *tf2 = [[YoshikoTextField alloc] initWithFrame:self.lowFrame]; 97 | tf2.placeholder = @"Last Name"; 98 | [self.view addSubview:tf2]; 99 | } else if ([self.title isEqualToString:@"Hoshi"]) { 100 | HoshiTextField *tf1 = [[HoshiTextField alloc] initWithFrame:self.highFrame]; 101 | tf1.placeholder = @"First Name"; 102 | [self.view addSubview:tf1]; 103 | 104 | HoshiTextField *tf2 = [[HoshiTextField alloc] initWithFrame:self.lowFrame]; 105 | tf2.placeholder = @"Last Name"; 106 | [self.view addSubview:tf2]; 107 | } else if ([self.title isEqualToString:@"Hideo"]) { 108 | HideoTextField *tf1 = [[HideoTextField alloc] initWithFrame:CGRectInset(self.highFrame, 0, 7)]; 109 | tf1.image = [UIImage imageNamed:@"mail.png"]; 110 | [self.view addSubview:tf1]; 111 | 112 | HideoTextField *tf2 = [[HideoTextField alloc] initWithFrame:CGRectInset(self.lowFrame, 0, 7)]; 113 | tf2.image = [UIImage imageNamed:@"user.png"]; 114 | [self.view addSubview:tf2]; 115 | } else if ([self.title isEqualToString:@"Haruki"]) { 116 | HarukiTextField *tf1 = [[HarukiTextField alloc] initWithFrame:self.highFrame]; 117 | tf1.placeholder = @"First Name"; 118 | [self.view addSubview:tf1]; 119 | 120 | HarukiTextField *tf2 = [[HarukiTextField alloc] initWithFrame:self.lowFrame]; 121 | tf2.placeholder = @"Last Name"; 122 | [self.view addSubview:tf2]; 123 | } else if ([self.title isEqualToString:@"Minoru"]) { 124 | MinoruTextField *tf1 = [[MinoruTextField alloc] initWithFrame:self.highFrame]; 125 | tf1.placeholder = @"First Name"; 126 | [self.view addSubview:tf1]; 127 | 128 | MinoruTextField *tf2 = [[MinoruTextField alloc] initWithFrame:self.lowFrame]; 129 | tf2.placeholder = @"Last Name"; 130 | [self.view addSubview:tf2]; 131 | } else if ([self.title isEqualToString:@"Kyo"]) { 132 | KyoTextField *tf1 = [[KyoTextField alloc] initWithFrame:self.highFrame]; 133 | tf1.placeholder = @"First Name"; 134 | [self.view addSubview:tf1]; 135 | 136 | KyoTextField *tf2 = [[KyoTextField alloc] initWithFrame:self.lowFrame]; 137 | tf2.placeholder = @"Last Name"; 138 | [self.view addSubview:tf2]; 139 | } else if ([self.title isEqualToString:@"Kuro"]) { 140 | KuroTextField *tf1 = [[KuroTextField alloc] initWithFrame:self.highFrame]; 141 | tf1.placeholder = @"First Name"; 142 | [self.view addSubview:tf1]; 143 | 144 | KuroTextField *tf2 = [[KuroTextField alloc] initWithFrame:self.lowFrame]; 145 | tf2.placeholder = @"Last Name"; 146 | [self.view addSubview:tf2]; 147 | } else if ([self.title isEqualToString:@"Ruri"]) { 148 | RuriTextField *tf1 = [[RuriTextField alloc] initWithFrame:self.highFrame]; 149 | tf1.placeholder = @"First Name"; 150 | [self.view addSubview:tf1]; 151 | 152 | RuriTextField *tf2 = [[RuriTextField alloc] initWithFrame:self.lowFrame]; 153 | tf2.placeholder = @"Last Name"; 154 | [self.view addSubview:tf2]; 155 | } else if ([self.title isEqualToString:@"Chisato"]) { 156 | ChisatoTextField *tf1 = [[ChisatoTextField alloc] initWithFrame:self.highFrame]; 157 | tf1.placeholder = @"First Name"; 158 | [self.view addSubview:tf1]; 159 | 160 | ChisatoTextField *tf2 = [[ChisatoTextField alloc] initWithFrame:self.lowFrame]; 161 | tf2.placeholder = @"Last Name"; 162 | [self.view addSubview:tf2]; 163 | } else if ([self.title isEqualToString:@"Manami"]) { 164 | ManamiTextField *tf1 = [[ManamiTextField alloc] initWithFrame:self.highFrame]; 165 | tf1.placeholder = @"First Name"; 166 | [self.view addSubview:tf1]; 167 | 168 | ManamiTextField *tf2 = [[ManamiTextField alloc] initWithFrame:self.lowFrame]; 169 | tf2.placeholder = @"Last Name"; 170 | [self.view addSubview:tf2]; 171 | } else if ([self.title isEqualToString:@"Nariko"]) { 172 | NarikoTextField *tf1 = [[NarikoTextField alloc] initWithFrame:self.highFrame]; 173 | tf1.placeholder = @"First Name"; 174 | [self.view addSubview:tf1]; 175 | 176 | NarikoTextField *tf2 = [[NarikoTextField alloc] initWithFrame:self.lowFrame]; 177 | tf2.placeholder = @"Last Name"; 178 | [self.view addSubview:tf2]; 179 | } else if ([self.title isEqualToString:@"Sae"]) { 180 | SaeTextField *tf1 = [[SaeTextField alloc] initWithFrame:CGRectInset(self.highFrame, 80, 0)]; 181 | tf1.placeholder = @"First Name"; 182 | [self.view addSubview:tf1]; 183 | 184 | SaeTextField *tf2 = [[SaeTextField alloc] initWithFrame:CGRectInset(self.lowFrame, 80, 0)]; 185 | tf2.placeholder = @"Last Name"; 186 | [self.view addSubview:tf2]; 187 | } else if ([self.title isEqualToString:@"Kohana"]) { 188 | KohanaTextField *tf1 = [[KohanaTextField alloc] initWithFrame:CGRectInset(self.highFrame, 0, 7)]; 189 | tf1.placeholder = @"Mail"; 190 | tf1.image = [UIImage imageNamed:@"mail.png"]; 191 | [self.view addSubview:tf1]; 192 | 193 | KohanaTextField *tf2 = [[KohanaTextField alloc] initWithFrame:CGRectInset(self.lowFrame, 0, 7)]; 194 | tf2.placeholder = @"User Name"; 195 | tf2.image = [UIImage imageNamed:@"user.png"]; 196 | [self.view addSubview:tf2]; 197 | } 198 | } 199 | 200 | #pragma mark - Pirvate methods 201 | 202 | 203 | @end 204 | --------------------------------------------------------------------------------