diff --git a/JSTokenField.xcodeproj/project.pbxproj b/JSTokenField.xcodeproj/project.pbxproj index 23652b8..2fff879 100644 --- a/JSTokenField.xcodeproj/project.pbxproj +++ b/JSTokenField.xcodeproj/project.pbxproj @@ -23,6 +23,10 @@ 1A1A06C413FEE2D900CA6645 /* tokenNormal@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A06C013FEE2D900CA6645 /* tokenNormal@2x.png */; }; 1A1A06CF13FF000C00CA6645 /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A06CD13FF000C00CA6645 /* AddressBook.framework */; }; 1A1A06D013FF000C00CA6645 /* AddressBookUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A06CE13FF000C00CA6645 /* AddressBookUI.framework */; }; + 8223ECC516672B0100221221 /* tokenHighlightedDark.png in Resources */ = {isa = PBXBuildFile; fileRef = 8223ECC116672B0100221221 /* tokenHighlightedDark.png */; }; + 8223ECC616672B0100221221 /* tokenHighlightedDark@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8223ECC216672B0100221221 /* tokenHighlightedDark@2x.png */; }; + 8223ECC716672B0100221221 /* tokenNormalDark.png in Resources */ = {isa = PBXBuildFile; fileRef = 8223ECC316672B0100221221 /* tokenNormalDark.png */; }; + 8223ECC816672B0100221221 /* tokenNormalDark@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8223ECC416672B0100221221 /* tokenNormalDark@2x.png */; }; B71650D1144399F800EBF2C7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A069C13FEDEEC00CA6645 /* Foundation.framework */; }; B71650DB14439A0500EBF2C7 /* JSTokenField.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A1A06B913FEE01C00CA6645 /* JSTokenField.h */; }; B71650DC14439A0500EBF2C7 /* JSTokenField.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A06BA13FEE01C00CA6645 /* JSTokenField.m */; }; @@ -54,6 +58,10 @@ 1A1A06C013FEE2D900CA6645 /* tokenNormal@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "tokenNormal@2x.png"; sourceTree = ""; }; 1A1A06CD13FF000C00CA6645 /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; }; 1A1A06CE13FF000C00CA6645 /* AddressBookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBookUI.framework; path = System/Library/Frameworks/AddressBookUI.framework; sourceTree = SDKROOT; }; + 8223ECC116672B0100221221 /* tokenHighlightedDark.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tokenHighlightedDark.png; sourceTree = ""; }; + 8223ECC216672B0100221221 /* tokenHighlightedDark@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "tokenHighlightedDark@2x.png"; sourceTree = ""; }; + 8223ECC316672B0100221221 /* tokenNormalDark.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tokenNormalDark.png; sourceTree = ""; }; + 8223ECC416672B0100221221 /* tokenNormalDark@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "tokenNormalDark@2x.png"; sourceTree = ""; }; B71650D0144399F800EBF2C7 /* libJSTokenFieldLibrary.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libJSTokenFieldLibrary.a; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -131,6 +139,10 @@ 1A1A06A113FEDEEC00CA6645 /* Supporting Files */ = { isa = PBXGroup; children = ( + 8223ECC116672B0100221221 /* tokenHighlightedDark.png */, + 8223ECC216672B0100221221 /* tokenHighlightedDark@2x.png */, + 8223ECC316672B0100221221 /* tokenNormalDark.png */, + 8223ECC416672B0100221221 /* tokenNormalDark@2x.png */, 1A1A06A213FEDEEC00CA6645 /* JSTokenField-Info.plist */, 1A1A06A313FEDEEC00CA6645 /* InfoPlist.strings */, 1A1A06A613FEDEEC00CA6645 /* main.m */, @@ -230,6 +242,10 @@ 1A1A06C213FEE2D900CA6645 /* tokenHighlighted@2x.png in Resources */, 1A1A06C313FEE2D900CA6645 /* tokenNormal.png in Resources */, 1A1A06C413FEE2D900CA6645 /* tokenNormal@2x.png in Resources */, + 8223ECC516672B0100221221 /* tokenHighlightedDark.png in Resources */, + 8223ECC616672B0100221221 /* tokenHighlightedDark@2x.png in Resources */, + 8223ECC716672B0100221221 /* tokenNormalDark.png in Resources */, + 8223ECC816672B0100221221 /* tokenNormalDark@2x.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/JSTokenField/DemoViewController.m b/JSTokenField/DemoViewController.m index 08cc9ac..6e61ee5 100644 --- a/JSTokenField/DemoViewController.m +++ b/JSTokenField/DemoViewController.m @@ -28,6 +28,7 @@ #import "DemoViewController.h" #import "JSTokenField.h" +#import "JSTokenButton.h" @implementation DemoViewController @@ -62,7 +63,13 @@ - (void)viewDidLoad [[_toField label] setText:@"To:"]; [_toField setDelegate:self]; [self.view addSubview:_toField]; - + + //Enable to change default button texture and title color + [JSTokenButton setDefaultHighlightedButtonImage:[[UIImage imageNamed:@"tokenHighlightedDark"] stretchableImageWithLeftCapWidth:14 topCapHeight:0]]; + [JSTokenButton setDefaultNormalButtonImage:[[UIImage imageNamed:@"tokenNormalDark"] stretchableImageWithLeftCapWidth:14 topCapHeight:0]]; + [JSTokenButton setDefaultNormalButtonTitleColor:[UIColor whiteColor]]; + [JSTokenButton setDefaultHighlightedButtonTitleColor:[UIColor blackColor]]; + UIView *separator1 = [[[UIView alloc] initWithFrame:CGRectMake(0, _toField.bounds.size.height-1, _toField.bounds.size.width, 1)] autorelease]; [separator1 setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin]; [_toField addSubview:separator1]; @@ -160,4 +167,11 @@ - (void)handleTokenFieldFrameDidChange:(NSNotification *)note } } +- (void)tokenField:(JSTokenField *)tokenField token:(JSTokenButton *)tokBtn toggledTo:(BOOL)toggleValue { + NSLog(@"Token %@ toggled to %d", tokBtn.representedObject, toggleValue); +} + +- (void)tokenField:(JSTokenField *)tokenField tokenTouchedUpInside:(JSTokenButton *)tokBtn { + NSLog(@"Token button %@ touched", tokBtn.representedObject); +} @end diff --git a/JSTokenField/JSTokenButton.h b/JSTokenField/JSTokenButton.h index 1223204..5cc675e 100644 --- a/JSTokenField/JSTokenButton.h +++ b/JSTokenField/JSTokenButton.h @@ -37,7 +37,6 @@ UIImage *_highlightedBg; id _representedObject; - } @property (nonatomic, getter=isToggled) BOOL toggled; @@ -48,7 +47,17 @@ @property (nonatomic, retain) id representedObject; @property (nonatomic, assign) JSTokenField *parentField; +@property (nonatomic, strong) UIColor *normalTitleColor; +@property (nonatomic, strong) UIColor *highlightedTitleColor; + + (JSTokenButton *)tokenWithString:(NSString *)string representedObject:(id)obj; ++ (JSTokenButton *)tokenWithString:(NSString *)string representedObject:(id)obj normalBG:(UIImage *)nbg highlightedBG:(UIImage *)hbg normalTitleColor:(UIColor *)normalTColor highlightedTitleColor:(UIColor *)hiTColor; + +//Customization related methods ++ (void)setDefaultNormalButtonImage:(UIImage *)image; ++ (void)setDefaultHighlightedButtonImage:(UIImage *)image; ++ (void)setDefaultNormalButtonTitleColor:(UIColor *)nColor; ++ (void)setDefaultHighlightedButtonTitleColor:(UIColor *)hColor; @end diff --git a/JSTokenField/JSTokenButton.m b/JSTokenField/JSTokenButton.m index f20112b..f00be37 100644 --- a/JSTokenField/JSTokenButton.m +++ b/JSTokenField/JSTokenButton.m @@ -38,13 +38,84 @@ @implementation JSTokenButton @synthesize representedObject = _representedObject; @synthesize parentField = _parentField; +/*- (id)init +{ + self = [super init]; + if (self) { + self.ty + } + return self; +}*/ + +static __strong UIImage *_defaultNormalButtonImage = nil; +static __strong UIImage *_defaultHighlightedButtonImage = nil; +static __strong UIColor *_defaultNormalButtonTitleColor = nil; +static __strong UIColor *_defaultHighlightedButtonTitleColor = nil; + + (JSTokenButton *)tokenWithString:(NSString *)string representedObject:(id)obj { + return [JSTokenButton tokenWithString:string + representedObject:obj + normalBG:nil + highlightedBG:nil + normalTitleColor:nil + highlightedTitleColor:nil + ]; +} + ++ (JSTokenButton *)tokenWithString:(NSString *)string representedObject:(id)obj normalBG:(UIImage *)nbg highlightedBG:(UIImage *)hbg normalTitleColor:(UIColor *)normalTColor highlightedTitleColor:(UIColor *)hiTColor { JSTokenButton *button = (JSTokenButton *)[self buttonWithType:UIButtonTypeCustom]; - [button setNormalBg:[[UIImage imageNamed:@"tokenNormal.png"] stretchableImageWithLeftCapWidth:14 topCapHeight:0]]; - [button setHighlightedBg:[[UIImage imageNamed:@"tokenHighlighted.png"] stretchableImageWithLeftCapWidth:14 topCapHeight:0]]; + if (nbg == nil) { + if (_defaultNormalButtonImage == nil) { + button.normalBg = [[UIImage imageNamed:@"tokenNormal"] + stretchableImageWithLeftCapWidth:14 + topCapHeight:0]; + } + else { + button.normalBg = _defaultNormalButtonImage; + } + } + else { + button.normalBg = nbg; + } + if (hbg == nil) { + if (_defaultHighlightedButtonImage == nil) { + button.highlightedBg = [[UIImage imageNamed:@"tokenHighlighted"] + stretchableImageWithLeftCapWidth:14 + topCapHeight:0]; + } + else { + button.highlightedBg = _defaultHighlightedButtonImage; + } + } + else { + button.highlightedBg = hbg; + } [button setAdjustsImageWhenHighlighted:NO]; - [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + if (normalTColor == nil) { + if (_defaultNormalButtonTitleColor == nil) { + button.normalTitleColor = [UIColor blackColor]; + } + else { + button.normalTitleColor = _defaultNormalButtonTitleColor; + } + } + else { + button.normalTitleColor = normalTColor; + } + if (hiTColor == nil) { + if (_defaultHighlightedButtonTitleColor == nil) { + button.highlightedTitleColor = [UIColor whiteColor]; + } + else { + button.highlightedTitleColor = _defaultHighlightedButtonTitleColor; + } + } + else { + button.highlightedTitleColor = hiTColor; + } + [button setTitleColor:button.normalTitleColor forState:UIControlStateNormal]; + [[button titleLabel] setFont:[UIFont fontWithName:@"Helvetica Neue" size:15]]; [[button titleLabel] setLineBreakMode:UILineBreakModeTailTruncation]; [button setTitleEdgeInsets:UIEdgeInsetsMake(2, 10, 0, 10)]; @@ -61,7 +132,7 @@ + (JSTokenButton *)tokenWithString:(NSString *)string representedObject:(id)obj [button setRepresentedObject:obj]; - return button; + return button; } - (void)setToggled:(BOOL)toggled @@ -71,12 +142,12 @@ - (void)setToggled:(BOOL)toggled if (_toggled) { [self setBackgroundImage:self.highlightedBg forState:UIControlStateNormal]; - [self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [self setTitleColor:self.highlightedTitleColor forState:UIControlStateNormal]; } else { [self setBackgroundImage:self.normalBg forState:UIControlStateNormal]; - [self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [self setTitleColor:self.normalTitleColor forState:UIControlStateNormal]; } } @@ -121,4 +192,21 @@ - (BOOL)canBecomeFirstResponder { return YES; } +#pragma mark - Customization related methods + ++ (void)setDefaultNormalButtonImage:(UIImage *)image { + _defaultNormalButtonImage = [image copy]; +} + ++ (void)setDefaultHighlightedButtonImage:(UIImage *)image { + _defaultHighlightedButtonImage = [image copy]; +} + ++ (void)setDefaultNormalButtonTitleColor:(UIColor *)nColor { + _defaultNormalButtonTitleColor = [nColor copy]; +} + ++ (void)setDefaultHighlightedButtonTitleColor:(UIColor *)hColor { + _defaultHighlightedButtonTitleColor = [hColor copy]; +} @end diff --git a/JSTokenField/JSTokenField.h b/JSTokenField/JSTokenField.h index 415ef05..5438d8e 100644 --- a/JSTokenField/JSTokenField.h +++ b/JSTokenField/JSTokenField.h @@ -58,6 +58,11 @@ extern NSString *const JSDeletedTokenKey; - (void)removeTokenForString:(NSString *)string; - (void)removeTokenWithRepresentedObject:(id)representedObject; +- (void)setNormalButtonImage:(UIImage *)image; +- (void)setHighlightedButtonImage:(UIImage *)image; +- (void)setNormalButtonTitleColor:(UIColor *)nColor; +- (void)setHighlightedButtonTitleColor:(UIColor *)hColor; + @end @protocol JSTokenFieldDelegate @@ -70,4 +75,6 @@ extern NSString *const JSDeletedTokenKey; - (BOOL)tokenFieldShouldReturn:(JSTokenField *)tokenField; - (void)tokenFieldDidEndEditing:(JSTokenField *)tokenField; +- (void)tokenField:(JSTokenField *)tokenField token:(JSTokenButton *)tokBtn toggledTo:(BOOL)toggleValue; +- (void)tokenField:(JSTokenField *)tokenField tokenTouchedUpInside:(JSTokenButton *)tokBtn; @end diff --git a/JSTokenField/JSTokenField.m b/JSTokenField/JSTokenField.m index 4bd5907..6b17809 100644 --- a/JSTokenField/JSTokenField.m +++ b/JSTokenField/JSTokenField.m @@ -48,6 +48,11 @@ - (JSTokenButton *)tokenWithString:(NSString *)string representedObject:(id)obj; - (void)deleteHighlightedToken; - (void)commonSetup; + +@property (nonatomic, strong) UIImage *buttonNormalImage; +@property (nonatomic, strong) UIImage *buttonHightlightedImage; +@property (nonatomic, strong) UIColor *buttonNormalTitleColor; +@property (nonatomic, strong) UIColor *buttonHighlightedTitleColor; @end @@ -117,6 +122,10 @@ - (void)commonSetup { selector:@selector(handleTextDidChange:) name:UITextFieldTextDidChangeNotification object:_textField]; + + //Initialize JSTokenButton background images to nil so the default background images are used by default + _buttonHightlightedImage = nil; + _buttonNormalImage = nil; } - (void)dealloc @@ -146,7 +155,6 @@ - (void)addTokenWithTitle:(NSString *)string representedObject:(id)obj { [self.delegate tokenField:self didAddToken:aString representedObject:obj]; } - [self setNeedsLayout]; } } @@ -215,7 +223,12 @@ - (void)deleteHighlightedToken - (JSTokenButton *)tokenWithString:(NSString *)string representedObject:(id)obj { - JSTokenButton *token = [JSTokenButton tokenWithString:string representedObject:obj]; + JSTokenButton *token = [JSTokenButton tokenWithString:string representedObject:obj + normalBG:self.buttonNormalImage + highlightedBG:self.buttonHightlightedImage + normalTitleColor:self.buttonNormalTitleColor + highlightedTitleColor:self.buttonHighlightedTitleColor]; + CGRect frame = [token frame]; if (frame.size.width > self.frame.size.width) @@ -295,12 +308,24 @@ - (void)toggle:(id)sender { for (JSTokenButton *token in _tokens) { - [token setToggled:NO]; + if (token != (JSTokenButton *)sender) { + [token setToggled:NO]; + if ([self.delegate respondsToSelector:@selector(tokenField:token:toggledTo:)]) { + [self.delegate tokenField:self token:token toggledTo:NO]; + } + } + else { + BOOL toggleValue = (token.isToggled)?NO:YES; + [token setToggled:toggleValue]; + [token becomeFirstResponder]; + if ([self.delegate respondsToSelector:@selector(tokenField:tokenTouchedUpInside:)]) { + [self.delegate tokenField:self tokenTouchedUpInside:token]; + } + if ([self.delegate respondsToSelector:@selector(tokenField:token:toggledTo:)]) { + [self.delegate tokenField:self token:token toggledTo:toggleValue]; + } + } } - - JSTokenButton *token = (JSTokenButton *)sender; - [token setToggled:YES]; - [token becomeFirstResponder]; } - (void)setFrame:(CGRect)frame @@ -322,6 +347,44 @@ - (void)setFrame:(CGRect)frame } } +#pragma mark - +#pragma mark JSTokenButton customization methods +- (void)setNormalButtonImage:(UIImage *)image { + if (image != nil) { + self.buttonNormalImage = image; + for (JSTokenButton *token in _tokens) { + [token setNormalBg:self.buttonNormalImage]; + } + } +} + +- (void)setHighlightedButtonImage:(UIImage *)image { + if (image != nil) { + self.buttonHightlightedImage = image; + for (JSTokenButton *token in _tokens) { + [token setHighlightedBg:self.buttonHightlightedImage]; + } + } +} + +- (void)setNormalButtonTitleColor:(UIColor *)nColor { + if (nColor != nil) { + self.buttonNormalTitleColor = nColor; + for (JSTokenButton *token in _tokens) { + token.normalTitleColor = self.buttonNormalTitleColor; + } + } +} + +- (void)setHighlightedButtonTitleColor:(UIColor *)hColor { + if (hColor != nil) { + self.buttonHighlightedTitleColor = hColor; + for (JSTokenButton *token in _tokens) { + token.highlightedTitleColor = self.buttonHighlightedTitleColor; + } + } +} + #pragma mark - #pragma mark UITextFieldDelegate diff --git a/JSTokenField/tokenHighlightedDark.png b/JSTokenField/tokenHighlightedDark.png new file mode 100644 index 0000000..cf4c46a Binary files /dev/null and b/JSTokenField/tokenHighlightedDark.png differ diff --git a/JSTokenField/tokenHighlightedDark@2x.png b/JSTokenField/tokenHighlightedDark@2x.png new file mode 100644 index 0000000..d4f2098 Binary files /dev/null and b/JSTokenField/tokenHighlightedDark@2x.png differ diff --git a/JSTokenField/tokenNormalDark.png b/JSTokenField/tokenNormalDark.png new file mode 100644 index 0000000..34b6c4e Binary files /dev/null and b/JSTokenField/tokenNormalDark.png differ diff --git a/JSTokenField/tokenNormalDark@2x.png b/JSTokenField/tokenNormalDark@2x.png new file mode 100644 index 0000000..d92e53d Binary files /dev/null and b/JSTokenField/tokenNormalDark@2x.png differ