From 3601e82d29c327131f1b4203ff6cb33aee66472a Mon Sep 17 00:00:00 2001 From: Neeraj Baid Date: Thu, 14 May 2015 09:36:17 -0700 Subject: [PATCH 01/12] Position tokens properly. --- VENTokenField/VENTokenField.h | 7 ++++++ VENTokenField/VENTokenField.m | 45 +++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/VENTokenField/VENTokenField.h b/VENTokenField/VENTokenField.h index 73ea5dd..2a575b3 100644 --- a/VENTokenField/VENTokenField.h +++ b/VENTokenField/VENTokenField.h @@ -39,6 +39,12 @@ - (UIColor *)tokenField:(VENTokenField *)tokenField colorSchemeForTokenAtIndex:(NSUInteger)index; @end +typedef NS_ENUM(NSInteger, VENTokenFieldAlignment) { + VENTokenFieldAlignmentLeft = 0, + VENTokenFieldAlignmentCenter, + VENTokenFieldAlignmentRight +}; + @interface VENTokenField : UIView @@ -61,6 +67,7 @@ @property (assign, nonatomic) CGFloat tokenPadding; @property (assign, nonatomic) CGFloat minInputWidth; +@property (assign, nonatomic) VENTokenFieldAlignment alignment; @property (assign, nonatomic) UIKeyboardType inputTextFieldKeyboardType; @property (assign, nonatomic) UITextAutocorrectionType autocorrectionType; @property (assign, nonatomic) UITextAutocapitalizationType autocapitalizationType; diff --git a/VENTokenField/VENTokenField.m b/VENTokenField/VENTokenField.m index 63c63a6..31941fd 100644 --- a/VENTokenField/VENTokenField.m +++ b/VENTokenField/VENTokenField.m @@ -212,6 +212,7 @@ - (void)layoutTokensAndInputWithFrameAdjustment:(BOOL)shouldAdjustFrame [self layoutToLabelInView:self.scrollView origin:CGPointZero currentX:¤tX]; [self layoutTokensWithCurrentX:¤tX currentY:¤tY]; + [self realignTokensWithAlignment:self.alignment]; [self layoutInputTextFieldWithCurrentX:¤tX currentY:¤tY]; if (shouldAdjustFrame) { @@ -326,6 +327,50 @@ - (void)layoutTokensWithCurrentX:(CGFloat *)currentX currentY:(CGFloat *)current } } +- (void)realignTokensWithAlignment:(VENTokenFieldAlignment)alignment { + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + for (VENToken *token in self.tokens) { + if (dict[@(token.y)]) { + dict[@(token.y)] = [dict[@(token.y)] arrayByAddingObject:token]; + } else { + dict[@(token.y)] = @[token]; + } + } + // Could be parallelized: compute all new frames on background threads. + // Once done, assign new frames to tokens on main thread. + for (NSNumber *rowY in [dict allKeys]) { + [self realignRowOfTokens:dict[rowY] withAlignment:alignment]; + } +} + +- (void)realignRowOfTokens:(NSArray *)tokens withAlignment:(VENTokenFieldAlignment)alignment { + // This method is unreliant on the order of tokens. It could be faster if it was reliant. + VENToken *firstToken = tokens[0]; + CGFloat totalLineWidth = 0; + for (VENToken *token in tokens) { + if (token.x < firstToken.x) { + firstToken = token; + } + totalLineWidth += token.width; + } + CGFloat frameAdjustment = 0; + switch (self.alignment) { + case VENTokenFieldAlignmentRight: { + frameAdjustment = self.scrollView.contentSize.width - firstToken.x - totalLineWidth; + break; + } + case VENTokenFieldAlignmentCenter: { + frameAdjustment = (self.scrollView.contentSize.width - firstToken.x - totalLineWidth) / 2.0; + break; + } + default: + break; + } + for (VENToken *token in tokens) { + token.x += frameAdjustment; + } +} + #pragma mark - Private From ad089cf23f1fd168c24748d5b295de5e5595bc80 Mon Sep 17 00:00:00 2001 From: Neeraj Baid Date: Thu, 14 May 2015 09:52:02 -0700 Subject: [PATCH 02/12] Update currentX so inputTextField repositions properly for VENTokenFieldAlignmentRight. --- VENTokenField/VENTokenField.m | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/VENTokenField/VENTokenField.m b/VENTokenField/VENTokenField.m index 31941fd..2913998 100644 --- a/VENTokenField/VENTokenField.m +++ b/VENTokenField/VENTokenField.m @@ -212,7 +212,6 @@ - (void)layoutTokensAndInputWithFrameAdjustment:(BOOL)shouldAdjustFrame [self layoutToLabelInView:self.scrollView origin:CGPointZero currentX:¤tX]; [self layoutTokensWithCurrentX:¤tX currentY:¤tY]; - [self realignTokensWithAlignment:self.alignment]; [self layoutInputTextFieldWithCurrentX:¤tX currentY:¤tY]; if (shouldAdjustFrame) { @@ -325,9 +324,11 @@ - (void)layoutTokensWithCurrentX:(CGFloat *)currentX currentY:(CGFloat *)current *currentX += token.width + self.tokenPadding; [self.scrollView addSubview:token]; } + [self realignTokensWithCurrentX:currentX alignment:self.alignment]; } -- (void)realignTokensWithAlignment:(VENTokenFieldAlignment)alignment { +- (void)realignTokensWithCurrentX:(CGFloat *)currentX alignment:(VENTokenFieldAlignment)alignment +{ NSMutableDictionary *dict = [NSMutableDictionary dictionary]; for (VENToken *token in self.tokens) { if (dict[@(token.y)]) { @@ -338,19 +339,28 @@ - (void)realignTokensWithAlignment:(VENTokenFieldAlignment)alignment { } // Could be parallelized: compute all new frames on background threads. // Once done, assign new frames to tokens on main thread. + CGFloat currentY = 0; for (NSNumber *rowY in [dict allKeys]) { - [self realignRowOfTokens:dict[rowY] withAlignment:alignment]; + [self realignRowOfTokens:dict[rowY] currentX:currentX currentY:¤tY alignment:alignment]; } } -- (void)realignRowOfTokens:(NSArray *)tokens withAlignment:(VENTokenFieldAlignment)alignment { +- (void)realignRowOfTokens:(NSArray *)tokens + currentX:(CGFloat *)currentX + currentY:(CGFloat *)currentY + alignment:(VENTokenFieldAlignment)alignment +{ // This method is unreliant on the order of tokens. It could be faster if it was reliant. - VENToken *firstToken = tokens[0]; + VENToken *firstToken = [tokens firstObject]; + VENToken *lastToken = [tokens firstObject]; CGFloat totalLineWidth = 0; for (VENToken *token in tokens) { if (token.x < firstToken.x) { firstToken = token; } + if (token.x > lastToken.x) { + lastToken = token; + } totalLineWidth += token.width; } CGFloat frameAdjustment = 0; @@ -369,6 +379,9 @@ - (void)realignRowOfTokens:(NSArray *)tokens withAlignment:(VENTokenFieldAlignme for (VENToken *token in tokens) { token.x += frameAdjustment; } + if (firstToken.y >= *currentY) { + *currentX = lastToken.x + lastToken.width; + } } From 07537026d34815a5bfacd473decf2adae0b1407a Mon Sep 17 00:00:00 2001 From: Neeraj Baid Date: Thu, 14 May 2015 10:05:16 -0700 Subject: [PATCH 03/12] VENTokenFieldAlignment now mirrors NSTextAlignment. collapsedLabel textAlignment mirrors tokenField alignment. --- VENTokenField/VENTokenField.h | 6 +++--- VENTokenField/VENTokenField.m | 7 +++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/VENTokenField/VENTokenField.h b/VENTokenField/VENTokenField.h index 2a575b3..6b385e7 100644 --- a/VENTokenField/VENTokenField.h +++ b/VENTokenField/VENTokenField.h @@ -40,9 +40,9 @@ @end typedef NS_ENUM(NSInteger, VENTokenFieldAlignment) { - VENTokenFieldAlignmentLeft = 0, - VENTokenFieldAlignmentCenter, - VENTokenFieldAlignmentRight + VENTokenFieldAlignmentLeft = NSTextAlignmentLeft, + VENTokenFieldAlignmentCenter = NSTextAlignmentCenter, + VENTokenFieldAlignmentRight = NSTextAlignmentRight }; diff --git a/VENTokenField/VENTokenField.m b/VENTokenField/VENTokenField.m index 2913998..e905084 100644 --- a/VENTokenField/VENTokenField.m +++ b/VENTokenField/VENTokenField.m @@ -95,6 +95,7 @@ - (void)setUpInit self.colorScheme = [UIColor blueColor]; self.toLabelTextColor = [UIColor colorWithRed:112/255.0f green:124/255.0f blue:124/255.0f alpha:1.0f]; self.inputTextFieldTextColor = [UIColor colorWithRed:38/255.0f green:39/255.0f blue:41/255.0f alpha:1.0f]; + self.alignment = VENTokenFieldAlignmentLeft; // Accessing bare value to avoid kicking off a premature layout run. _toLabelText = NSLocalizedString(@"To:", nil); @@ -168,6 +169,11 @@ - (NSString *)inputText return self.inputTextField.text; } +- (void)setAlignment:(VENTokenFieldAlignment)alignment { + _alignment = alignment; + self.collapsedLabel.textAlignment = (NSTextAlignment)alignment; +} + #pragma mark - View Layout @@ -191,6 +197,7 @@ - (void)layoutCollapsedLabel CGFloat currentX = 0; [self layoutToLabelInView:self origin:CGPointMake(self.horizontalInset, self.verticalInset) currentX:¤tX]; [self layoutCollapsedLabelWithCurrentX:¤tX]; + self.collapsedLabel.textAlignment = (NSTextAlignment)self.alignment; self.tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)]; From c6994e444fc8340f3099209b4ee92ea69919e092 Mon Sep 17 00:00:00 2001 From: Neeraj Baid Date: Thu, 14 May 2015 10:23:52 -0700 Subject: [PATCH 04/12] Fix assignment of *currentY in realignRowOfTokens:. Remove VENTokenFieldAlignmentRight. --- VENTokenField/VENTokenField.h | 3 +-- VENTokenField/VENTokenField.m | 5 +---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/VENTokenField/VENTokenField.h b/VENTokenField/VENTokenField.h index 6b385e7..9704297 100644 --- a/VENTokenField/VENTokenField.h +++ b/VENTokenField/VENTokenField.h @@ -41,8 +41,7 @@ typedef NS_ENUM(NSInteger, VENTokenFieldAlignment) { VENTokenFieldAlignmentLeft = NSTextAlignmentLeft, - VENTokenFieldAlignmentCenter = NSTextAlignmentCenter, - VENTokenFieldAlignmentRight = NSTextAlignmentRight + VENTokenFieldAlignmentCenter = NSTextAlignmentCenter }; diff --git a/VENTokenField/VENTokenField.m b/VENTokenField/VENTokenField.m index e905084..978f49a 100644 --- a/VENTokenField/VENTokenField.m +++ b/VENTokenField/VENTokenField.m @@ -372,10 +372,6 @@ - (void)realignRowOfTokens:(NSArray *)tokens } CGFloat frameAdjustment = 0; switch (self.alignment) { - case VENTokenFieldAlignmentRight: { - frameAdjustment = self.scrollView.contentSize.width - firstToken.x - totalLineWidth; - break; - } case VENTokenFieldAlignmentCenter: { frameAdjustment = (self.scrollView.contentSize.width - firstToken.x - totalLineWidth) / 2.0; break; @@ -388,6 +384,7 @@ - (void)realignRowOfTokens:(NSArray *)tokens } if (firstToken.y >= *currentY) { *currentX = lastToken.x + lastToken.width; + *currentY = lastToken.y; } } From 72746d4b1626756337b94906dd7a02c5eab6d389 Mon Sep 17 00:00:00 2001 From: Neeraj Baid Date: Thu, 14 May 2015 11:54:34 -0700 Subject: [PATCH 05/12] Use placeholder token for input text field positioning. Live update text field location based on text length. --- VENTokenField/VENBackspaceTextField.m | 5 +- VENTokenField/VENTokenField.m | 71 ++++++++++++++++++--------- 2 files changed, 50 insertions(+), 26 deletions(-) diff --git a/VENTokenField/VENBackspaceTextField.m b/VENTokenField/VENBackspaceTextField.m index 326b282..fd61224 100644 --- a/VENTokenField/VENBackspaceTextField.m +++ b/VENTokenField/VENBackspaceTextField.m @@ -24,15 +24,12 @@ @implementation VENBackspaceTextField -- (BOOL)keyboardInputShouldDelete:(UITextField *)textField -{ +- (void)deleteBackward { if (self.text.length == 0) { if ([self.backspaceDelegate respondsToSelector:@selector(textFieldDidEnterBackspace:)]) { [self.backspaceDelegate textFieldDidEnterBackspace:self]; } } - - return YES; } @end diff --git a/VENTokenField/VENTokenField.m b/VENTokenField/VENTokenField.m index 978f49a..8dd972c 100644 --- a/VENTokenField/VENTokenField.m +++ b/VENTokenField/VENTokenField.m @@ -30,7 +30,7 @@ static const CGFloat VENTokenFieldDefaultHorizontalInset = 15.0; static const CGFloat VENTokenFieldDefaultToLabelPadding = 5.0; static const CGFloat VENTokenFieldDefaultTokenPadding = 2.0; -static const CGFloat VENTokenFieldDefaultMinInputWidth = 80.0; +static const CGFloat VENTokenFieldDefaultMinInputWidth = 20.0; static const CGFloat VENTokenFieldDefaultMaxHeight = 150.0; @@ -44,6 +44,7 @@ @interface VENTokenField () @property (strong, nonatomic) VENBackspaceTextField *inputTextField; @property (strong, nonatomic) UIColor *colorScheme; @property (strong, nonatomic) UILabel *collapsedLabel; +@property (strong, nonatomic) NSString *inputTextFieldText; @end @@ -257,16 +258,9 @@ - (void)layoutScrollView - (void)layoutInputTextFieldWithCurrentX:(CGFloat *)currentX currentY:(CGFloat *)currentY { - CGFloat inputTextFieldWidth = self.scrollView.contentSize.width - *currentX; - if (inputTextFieldWidth < self.minInputWidth) { - inputTextFieldWidth = self.scrollView.contentSize.width; - *currentY += [self heightForToken]; - *currentX = 0; - } - VENBackspaceTextField *inputTextField = self.inputTextField; - inputTextField.text = @""; - inputTextField.frame = CGRectMake(*currentX, *currentY + 1, inputTextFieldWidth, [self heightForToken] - 1); + inputTextField.text = self.inputTextFieldText; + inputTextField.frame = CGRectMake(*currentX, *currentY + 1, self.scrollView.contentSize.width - *currentX, [self heightForToken] - 1); inputTextField.tintColor = self.colorScheme; [self.scrollView addSubview:inputTextField]; } @@ -305,7 +299,6 @@ - (void)layoutTokensWithCurrentX:(CGFloat *)currentX currentY:(CGFloat *)current for (NSUInteger i = 0; i < [self numberOfTokens]; i++) { NSString *title = [self titleForTokenAtIndex:i]; VENToken *token = [[VENToken alloc] init]; - __weak VENToken *weakToken = token; __weak VENTokenField *weakSelf = self; token.didTapTokenBlock = ^{ @@ -331,13 +324,32 @@ - (void)layoutTokensWithCurrentX:(CGFloat *)currentX currentY:(CGFloat *)current *currentX += token.width + self.tokenPadding; [self.scrollView addSubview:token]; } - [self realignTokensWithCurrentX:currentX alignment:self.alignment]; + + VENToken *placeholderToken = [[VENToken alloc] init]; + [placeholderToken setTitleText:[self.inputTextFieldText stringByAppendingString:@"| "]]; // account for text field cursor and space + if (*currentX + placeholderToken.width <= self.scrollView.contentSize.width) { // token fits in current line + placeholderToken.frame = CGRectMake(*currentX, *currentY, placeholderToken.width, placeholderToken.height); + } else { + *currentY += placeholderToken.height; + *currentX = 0; + CGFloat tokenWidth = placeholderToken.width; + if (tokenWidth > self.scrollView.contentSize.width) { // token is wider than max width + tokenWidth = self.scrollView.contentSize.width; + } + placeholderToken.frame = CGRectMake(*currentX, *currentY, tokenWidth, placeholderToken.height); + } + + [self realignTokens:[self.tokens arrayByAddingObject:placeholderToken] + currentX:currentX + alignment:self.alignment]; } -- (void)realignTokensWithCurrentX:(CGFloat *)currentX alignment:(VENTokenFieldAlignment)alignment +- (void)realignTokens:(NSArray *)tokens + currentX:(CGFloat *)currentX + alignment:(VENTokenFieldAlignment)alignment { NSMutableDictionary *dict = [NSMutableDictionary dictionary]; - for (VENToken *token in self.tokens) { + for (VENToken *token in tokens) { if (dict[@(token.y)]) { dict[@(token.y)] = [dict[@(token.y)] arrayByAddingObject:token]; } else { @@ -383,7 +395,7 @@ - (void)realignRowOfTokens:(NSArray *)tokens token.x += frameAdjustment; } if (firstToken.y >= *currentY) { - *currentX = lastToken.x + lastToken.width; + *currentX = lastToken.x; *currentY = lastToken.y; } } @@ -560,11 +572,14 @@ - (UIColor *)colorSchemeForTokenAtIndex:(NSUInteger)index { return self.colorScheme; } + #pragma mark - Data Source - (NSString *)titleForTokenAtIndex:(NSUInteger)index { - if ([self.dataSource respondsToSelector:@selector(tokenField:titleForTokenAtIndex:)]) { + if (index == [self numberOfTokens]) { + return self.inputTextFieldText; + } else if ([self.dataSource respondsToSelector:@selector(tokenField:titleForTokenAtIndex:)]) { return [self.dataSource tokenField:self titleForTokenAtIndex:index]; } @@ -590,16 +605,23 @@ - (NSString *)collapsedText } -#pragma mark - UITextFieldDelegate +#pragma mark - Delegate -- (BOOL)textFieldShouldReturn:(UITextField *)textField -{ +- (void)didEnterText:(NSString *)text { if ([self.delegate respondsToSelector:@selector(tokenField:didEnterText:)]) { - if ([textField.text length]) { - [self.delegate tokenField:self didEnterText:textField.text]; + if ([text length]) { + self.inputTextFieldText = @""; + [self.delegate tokenField:self didEnterText:text]; } } - +} + + +#pragma mark - UITextFieldDelegate + +- (BOOL)textFieldShouldReturn:(UITextField *)textField +{ + [self didEnterText:textField.text]; return NO; } @@ -613,6 +635,11 @@ - (void)textFieldDidBeginEditing:(UITextField *)textField - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { [self unhighlightAllTokens]; + if (textField == self.inputTextField) { + self.inputTextFieldText = [textField.text stringByReplacingCharactersInRange:range withString:string]; + [self reloadData]; + return NO; + } return YES; } From debd011a6ef96634ab97b0fee9def92436da96ef Mon Sep 17 00:00:00 2001 From: Neeraj Baid Date: Thu, 14 May 2015 12:29:45 -0700 Subject: [PATCH 06/12] Use placeholderTextLabel. --- VENTokenField/VENTokenField.m | 41 ++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/VENTokenField/VENTokenField.m b/VENTokenField/VENTokenField.m index 8dd972c..fb02c53 100644 --- a/VENTokenField/VENTokenField.m +++ b/VENTokenField/VENTokenField.m @@ -45,6 +45,7 @@ @interface VENTokenField () @property (strong, nonatomic) UIColor *colorScheme; @property (strong, nonatomic) UILabel *collapsedLabel; @property (strong, nonatomic) NSString *inputTextFieldText; +@property (strong, nonatomic) UILabel *placeholderTextLabel; @end @@ -123,7 +124,8 @@ - (void)reloadData - (void)setPlaceholderText:(NSString *)placeholderText { _placeholderText = placeholderText; - self.inputTextField.placeholder = _placeholderText; + self.placeholderTextLabel.text = _placeholderText; + self.placeholderTextLabel.width = [_placeholderText sizeWithAttributes:@{NSFontAttributeName:self.placeholderTextLabel.font}].width; } -(void)setInputTextFieldAccessibilityLabel:(NSString *)inputTextFieldAccessibilityLabel { @@ -170,9 +172,11 @@ - (NSString *)inputText return self.inputTextField.text; } -- (void)setAlignment:(VENTokenFieldAlignment)alignment { +- (void)setAlignment:(VENTokenFieldAlignment)alignment +{ _alignment = alignment; self.collapsedLabel.textAlignment = (NSTextAlignment)alignment; + self.placeholderTextLabel.textAlignment = (NSTextAlignment)alignment; } @@ -228,7 +232,7 @@ - (void)layoutTokensAndInputWithFrameAdjustment:(BOOL)shouldAdjustFrame [self.scrollView setContentSize:CGSizeMake(self.scrollView.contentSize.width, currentY + [self heightForToken])]; - [self updateInputTextField]; + [self updatePlaceholderTextLabel]; if (inputFieldShouldBecomeFirstResponder) { [self inputTextFieldBecomeFirstResponder]; @@ -445,6 +449,18 @@ - (UILabel *)toLabel return _toLabel; } +- (UILabel *)placeholderTextLabel +{ + if (!_placeholderTextLabel) { + _placeholderTextLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 0, + [self heightForToken])]; + _placeholderTextLabel.font = self.inputTextField.font; + _placeholderTextLabel.textAlignment = (NSTextAlignment)self.alignment; + _placeholderTextLabel.textColor = [UIColor colorWithWhite:.8 alpha:1]; + } + return _placeholderTextLabel; +} + - (void)adjustHeightForCurrentY:(CGFloat)currentY { if (currentY + [self heightForToken] > CGRectGetHeight(self.frame)) { // needs to grow @@ -474,7 +490,6 @@ - (VENBackspaceTextField *)inputTextField _inputTextField.tintColor = self.colorScheme; _inputTextField.delegate = self; _inputTextField.backspaceDelegate = self; - _inputTextField.placeholder = self.placeholderText; _inputTextField.accessibilityLabel = self.inputTextFieldAccessibilityLabel ?: NSLocalizedString(@"To", nil); _inputTextField.inputAccessoryView = self.inputTextFieldAccessoryView; [_inputTextField addTarget:self action:@selector(inputTextFieldDidChange:) forControlEvents:UIControlEventEditingChanged]; @@ -549,9 +564,23 @@ - (void)setCursorVisibility } } -- (void)updateInputTextField +- (void)updatePlaceholderTextLabel { - self.inputTextField.placeholder = [self.tokens count] ? nil : self.placeholderText; + if (![self.tokens count] && self.inputTextFieldText.length == 0) { + switch (self.alignment) { + case VENTokenFieldAlignmentCenter: + self.placeholderTextLabel.centerX = self.inputTextField.x; + break; + case VENTokenFieldAlignmentLeft: + self.placeholderTextLabel.x = self.inputTextField.x; + break; + default: + break; + } + [self.scrollView addSubview:self.placeholderTextLabel]; + } else { + [self.placeholderTextLabel removeFromSuperview]; + } } - (void)focusInputTextField From 8c6245fdc2f81f3ddcb569043ac7951ea6d99298 Mon Sep 17 00:00:00 2001 From: Neeraj Baid Date: Thu, 14 May 2015 12:33:06 -0700 Subject: [PATCH 07/12] Insert placeholderTextLabel below inputTextField. --- VENTokenField/VENTokenField.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VENTokenField/VENTokenField.m b/VENTokenField/VENTokenField.m index fb02c53..2e6e292 100644 --- a/VENTokenField/VENTokenField.m +++ b/VENTokenField/VENTokenField.m @@ -577,7 +577,7 @@ - (void)updatePlaceholderTextLabel default: break; } - [self.scrollView addSubview:self.placeholderTextLabel]; + [self.scrollView insertSubview:self.placeholderTextLabel belowSubview:self.inputTextField]; } else { [self.placeholderTextLabel removeFromSuperview]; } From dbeda17c7ce41f88a5efd89bf11391ee212d6a79 Mon Sep 17 00:00:00 2001 From: Neeraj Baid Date: Thu, 14 May 2015 12:41:50 -0700 Subject: [PATCH 08/12] Remove now unused minInputWidth property. --- VENTokenField/VENTokenField.h | 1 - VENTokenField/VENTokenField.m | 2 -- 2 files changed, 3 deletions(-) diff --git a/VENTokenField/VENTokenField.h b/VENTokenField/VENTokenField.h index 9704297..e63e152 100644 --- a/VENTokenField/VENTokenField.h +++ b/VENTokenField/VENTokenField.h @@ -64,7 +64,6 @@ typedef NS_ENUM(NSInteger, VENTokenFieldAlignment) { @property (assign, nonatomic) CGFloat verticalInset; @property (assign, nonatomic) CGFloat horizontalInset; @property (assign, nonatomic) CGFloat tokenPadding; -@property (assign, nonatomic) CGFloat minInputWidth; @property (assign, nonatomic) VENTokenFieldAlignment alignment; @property (assign, nonatomic) UIKeyboardType inputTextFieldKeyboardType; diff --git a/VENTokenField/VENTokenField.m b/VENTokenField/VENTokenField.m index 2e6e292..2e7adfe 100644 --- a/VENTokenField/VENTokenField.m +++ b/VENTokenField/VENTokenField.m @@ -30,7 +30,6 @@ static const CGFloat VENTokenFieldDefaultHorizontalInset = 15.0; static const CGFloat VENTokenFieldDefaultToLabelPadding = 5.0; static const CGFloat VENTokenFieldDefaultTokenPadding = 2.0; -static const CGFloat VENTokenFieldDefaultMinInputWidth = 20.0; static const CGFloat VENTokenFieldDefaultMaxHeight = 150.0; @@ -93,7 +92,6 @@ - (void)setUpInit self.verticalInset = VENTokenFieldDefaultVerticalInset; self.horizontalInset = VENTokenFieldDefaultHorizontalInset; self.tokenPadding = VENTokenFieldDefaultTokenPadding; - self.minInputWidth = VENTokenFieldDefaultMinInputWidth; self.colorScheme = [UIColor blueColor]; self.toLabelTextColor = [UIColor colorWithRed:112/255.0f green:124/255.0f blue:124/255.0f alpha:1.0f]; self.inputTextFieldTextColor = [UIColor colorWithRed:38/255.0f green:39/255.0f blue:41/255.0f alpha:1.0f]; From babd933807613c0c705191e7ef4767aa1713b313 Mon Sep 17 00:00:00 2001 From: Neeraj Baid Date: Thu, 14 May 2015 12:44:14 -0700 Subject: [PATCH 09/12] Readd but deprecate minInputWidth. --- VENTokenField/VENTokenField.h | 1 + 1 file changed, 1 insertion(+) diff --git a/VENTokenField/VENTokenField.h b/VENTokenField/VENTokenField.h index e63e152..e12b454 100644 --- a/VENTokenField/VENTokenField.h +++ b/VENTokenField/VENTokenField.h @@ -64,6 +64,7 @@ typedef NS_ENUM(NSInteger, VENTokenFieldAlignment) { @property (assign, nonatomic) CGFloat verticalInset; @property (assign, nonatomic) CGFloat horizontalInset; @property (assign, nonatomic) CGFloat tokenPadding; +@property (assign, nonatomic) CGFloat minInputWidth DEPRECATED_ATTRIBUTE; @property (assign, nonatomic) VENTokenFieldAlignment alignment; @property (assign, nonatomic) UIKeyboardType inputTextFieldKeyboardType; From 41fb5f2ff3ae39148ff1e827cae95844e0711e22 Mon Sep 17 00:00:00 2001 From: Neeraj Baid Date: Thu, 14 May 2015 12:47:50 -0700 Subject: [PATCH 10/12] Rename alignment to tokenAlignment to better mirror UITextField textAlignment property. --- VENTokenField/VENTokenField.h | 2 +- VENTokenField/VENTokenField.m | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/VENTokenField/VENTokenField.h b/VENTokenField/VENTokenField.h index e12b454..68aed6e 100644 --- a/VENTokenField/VENTokenField.h +++ b/VENTokenField/VENTokenField.h @@ -66,7 +66,7 @@ typedef NS_ENUM(NSInteger, VENTokenFieldAlignment) { @property (assign, nonatomic) CGFloat tokenPadding; @property (assign, nonatomic) CGFloat minInputWidth DEPRECATED_ATTRIBUTE; -@property (assign, nonatomic) VENTokenFieldAlignment alignment; +@property (assign, nonatomic) VENTokenFieldAlignment tokenAlignment; @property (assign, nonatomic) UIKeyboardType inputTextFieldKeyboardType; @property (assign, nonatomic) UITextAutocorrectionType autocorrectionType; @property (assign, nonatomic) UITextAutocapitalizationType autocapitalizationType; diff --git a/VENTokenField/VENTokenField.m b/VENTokenField/VENTokenField.m index 2e7adfe..a3a7582 100644 --- a/VENTokenField/VENTokenField.m +++ b/VENTokenField/VENTokenField.m @@ -95,7 +95,7 @@ - (void)setUpInit self.colorScheme = [UIColor blueColor]; self.toLabelTextColor = [UIColor colorWithRed:112/255.0f green:124/255.0f blue:124/255.0f alpha:1.0f]; self.inputTextFieldTextColor = [UIColor colorWithRed:38/255.0f green:39/255.0f blue:41/255.0f alpha:1.0f]; - self.alignment = VENTokenFieldAlignmentLeft; + self.tokenAlignment = VENTokenFieldAlignmentLeft; // Accessing bare value to avoid kicking off a premature layout run. _toLabelText = NSLocalizedString(@"To:", nil); @@ -170,9 +170,9 @@ - (NSString *)inputText return self.inputTextField.text; } -- (void)setAlignment:(VENTokenFieldAlignment)alignment +- (void)setTokenAlignment:(VENTokenFieldAlignment)alignment { - _alignment = alignment; + _tokenAlignment = alignment; self.collapsedLabel.textAlignment = (NSTextAlignment)alignment; self.placeholderTextLabel.textAlignment = (NSTextAlignment)alignment; } @@ -200,7 +200,7 @@ - (void)layoutCollapsedLabel CGFloat currentX = 0; [self layoutToLabelInView:self origin:CGPointMake(self.horizontalInset, self.verticalInset) currentX:¤tX]; [self layoutCollapsedLabelWithCurrentX:¤tX]; - self.collapsedLabel.textAlignment = (NSTextAlignment)self.alignment; + self.collapsedLabel.textAlignment = (NSTextAlignment)self.tokenAlignment; self.tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)]; @@ -343,7 +343,7 @@ - (void)layoutTokensWithCurrentX:(CGFloat *)currentX currentY:(CGFloat *)current [self realignTokens:[self.tokens arrayByAddingObject:placeholderToken] currentX:currentX - alignment:self.alignment]; + alignment:self.tokenAlignment]; } - (void)realignTokens:(NSArray *)tokens @@ -385,7 +385,7 @@ - (void)realignRowOfTokens:(NSArray *)tokens totalLineWidth += token.width; } CGFloat frameAdjustment = 0; - switch (self.alignment) { + switch (self.tokenAlignment) { case VENTokenFieldAlignmentCenter: { frameAdjustment = (self.scrollView.contentSize.width - firstToken.x - totalLineWidth) / 2.0; break; @@ -453,7 +453,7 @@ - (UILabel *)placeholderTextLabel _placeholderTextLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 0, [self heightForToken])]; _placeholderTextLabel.font = self.inputTextField.font; - _placeholderTextLabel.textAlignment = (NSTextAlignment)self.alignment; + _placeholderTextLabel.textAlignment = (NSTextAlignment)self.tokenAlignment; _placeholderTextLabel.textColor = [UIColor colorWithWhite:.8 alpha:1]; } return _placeholderTextLabel; @@ -565,7 +565,7 @@ - (void)setCursorVisibility - (void)updatePlaceholderTextLabel { if (![self.tokens count] && self.inputTextFieldText.length == 0) { - switch (self.alignment) { + switch (self.tokenAlignment) { case VENTokenFieldAlignmentCenter: self.placeholderTextLabel.centerX = self.inputTextField.x; break; From 1f615c166fad18e79cfb1c2e55a7b25429742361 Mon Sep 17 00:00:00 2001 From: Neeraj Baid Date: Thu, 14 May 2015 13:02:48 -0700 Subject: [PATCH 11/12] Pull out token frame generator into own method. --- VENTokenField/VENTokenField.m | 37 ++++++++++++++++------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/VENTokenField/VENTokenField.m b/VENTokenField/VENTokenField.m index a3a7582..e05e905 100644 --- a/VENTokenField/VENTokenField.m +++ b/VENTokenField/VENTokenField.m @@ -312,38 +312,32 @@ - (void)layoutTokensWithCurrentX:(CGFloat *)currentX currentY:(CGFloat *)current [self.tokens addObject:token]; - if (*currentX + token.width <= self.scrollView.contentSize.width) { // token fits in current line - token.frame = CGRectMake(*currentX, *currentY, token.width, token.height); - } else { - *currentY += token.height; - *currentX = 0; - CGFloat tokenWidth = token.width; - if (tokenWidth > self.scrollView.contentSize.width) { // token is wider than max width - tokenWidth = self.scrollView.contentSize.width; - } - token.frame = CGRectMake(*currentX, *currentY, tokenWidth, token.height); - } + token.frame = [self frameForToken:token currentX:currentX currentY:currentY]; *currentX += token.width + self.tokenPadding; [self.scrollView addSubview:token]; } VENToken *placeholderToken = [[VENToken alloc] init]; [placeholderToken setTitleText:[self.inputTextFieldText stringByAppendingString:@"| "]]; // account for text field cursor and space - if (*currentX + placeholderToken.width <= self.scrollView.contentSize.width) { // token fits in current line - placeholderToken.frame = CGRectMake(*currentX, *currentY, placeholderToken.width, placeholderToken.height); + placeholderToken.frame = [self frameForToken:placeholderToken currentX:currentX currentY:currentY]; + + [self realignTokens:[self.tokens arrayByAddingObject:placeholderToken] + currentX:currentX + alignment:self.tokenAlignment]; +} + +- (CGRect)frameForToken:(VENToken *)token currentX:(CGFloat *)currentX currentY:(CGFloat *)currentY { + if (*currentX + token.width <= self.scrollView.contentSize.width) { // token fits in current line + return CGRectMake(*currentX, *currentY, token.width, token.height); } else { - *currentY += placeholderToken.height; + *currentY += token.height; *currentX = 0; - CGFloat tokenWidth = placeholderToken.width; + CGFloat tokenWidth = token.width; if (tokenWidth > self.scrollView.contentSize.width) { // token is wider than max width tokenWidth = self.scrollView.contentSize.width; } - placeholderToken.frame = CGRectMake(*currentX, *currentY, tokenWidth, placeholderToken.height); + return CGRectMake(*currentX, *currentY, tokenWidth, token.height); } - - [self realignTokens:[self.tokens arrayByAddingObject:placeholderToken] - currentX:currentX - alignment:self.tokenAlignment]; } - (void)realignTokens:(NSArray *)tokens @@ -455,6 +449,9 @@ - (UILabel *)placeholderTextLabel _placeholderTextLabel.font = self.inputTextField.font; _placeholderTextLabel.textAlignment = (NSTextAlignment)self.tokenAlignment; _placeholderTextLabel.textColor = [UIColor colorWithWhite:.8 alpha:1]; + [_placeholderTextLabel addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self.inputTextField + action:@selector(becomeFirstResponder)]]; + _placeholderTextLabel.userInteractionEnabled = YES; } return _placeholderTextLabel; } From b7101d8b5d68c762361fb84b1680bd7355241dea Mon Sep 17 00:00:00 2001 From: Neeraj Baid Date: Thu, 14 May 2015 13:11:48 -0700 Subject: [PATCH 12/12] Move inputTextField to edge of placeholderTextLabel like native centered UITextField. --- VENTokenField/VENTokenField.m | 1 + 1 file changed, 1 insertion(+) diff --git a/VENTokenField/VENTokenField.m b/VENTokenField/VENTokenField.m index e05e905..8decdc1 100644 --- a/VENTokenField/VENTokenField.m +++ b/VENTokenField/VENTokenField.m @@ -565,6 +565,7 @@ - (void)updatePlaceholderTextLabel switch (self.tokenAlignment) { case VENTokenFieldAlignmentCenter: self.placeholderTextLabel.centerX = self.inputTextField.x; + self.inputTextField.x = self.placeholderTextLabel.x; break; case VENTokenFieldAlignmentLeft: self.placeholderTextLabel.x = self.inputTextField.x;