From 06c0713b2b2d3912c9cee46099e1cf2ea3e8f6cb Mon Sep 17 00:00:00 2001 From: zzzworm Date: Wed, 18 May 2016 11:31:42 +0800 Subject: [PATCH 01/11] make scroll horizontal --- Classes/THContactPickerView.h | 2 + Classes/THContactPickerView.m | 43 ++++++++++++++++--- .../THContactPickerViewControllerDemo.m | 2 + 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/Classes/THContactPickerView.h b/Classes/THContactPickerView.h index 603942f..8dde38b 100755 --- a/Classes/THContactPickerView.h +++ b/Classes/THContactPickerView.h @@ -34,6 +34,8 @@ @property (nonatomic, assign) NSInteger maxNumberOfLines; // maximum number of lines the view will display before scrolling @property (nonatomic, strong) UIFont *font; +@property (nonatomic, assign) BOOL scrollHorizontal; // scroll to horizontal + - (void)addContact:(id)contact withName:(NSString *)name; - (void)addContact:(id)contact withName:(NSString *)name withStyle:(THContactViewStyle*)bubbleStyle andSelectedStyle:(THContactViewStyle*) selectedStyle; - (void)removeContact:(id)contact; diff --git a/Classes/THContactPickerView.m b/Classes/THContactPickerView.m index 8b50979..2b6a2a2 100755 --- a/Classes/THContactPickerView.m +++ b/Classes/THContactPickerView.m @@ -293,13 +293,23 @@ - (BOOL)becomeFirstResponder { - (void)scrollToBottomWithAnimation:(BOOL)animated { if (animated){ CGSize size = self.scrollView.contentSize; - CGRect frame = CGRectMake(0, size.height - self.scrollView.frame.size.height, size.width, self.scrollView.frame.size.height); - + CGRect frame; + if (self.scrollHorizontal) { + frame = CGRectMake(size.width - self.scrollView.frame.size.width, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height); + } + else{ + frame = CGRectMake(0, size.height - self.scrollView.frame.size.height, size.width, self.scrollView.frame.size.height); + } [self.scrollView scrollRectToVisible:frame animated:animated]; } else { // this block is here because scrollRectToVisible with animated NO causes crashes on iOS 5 when the user tries to delete many contacts really quickly CGPoint offset = self.scrollView.contentOffset; - offset.y = self.scrollView.contentSize.height - self.scrollView.frame.size.height; + if (self.scrollHorizontal) { + offset.x = self.scrollView.contentSize.width - self.scrollView.frame.size.width; + } + else{ + offset.y = self.scrollView.contentSize.height - self.scrollView.frame.size.height; + } self.scrollView.contentOffset = offset; } } @@ -386,7 +396,7 @@ - (void)layoutContactViews { } else { // Check if contact view will fit on the current line CGFloat width = contactViewFrame.size.width + 2 * _contactHorizontalPadding; - if (self.frame.size.width - kHorizontalSidePadding - _frameOfLastView.origin.x - _frameOfLastView.size.width - width >= 0){ + if (self.frame.size.width - kHorizontalSidePadding - _frameOfLastView.origin.x - _frameOfLastView.size.width - width >= 0 || self.scrollHorizontal){ // add to the same line // Place contact view just after last contact view on the same line contactViewFrame.origin.x = _frameOfLastView.origin.x + _frameOfLastView.size.width + _contactHorizontalPadding * 2; @@ -413,9 +423,16 @@ - (void)layoutContactViews { CGRect textFieldFrame = CGRectMake(0, 0, self.textField.frame.size.width, textFieldHeight); // Check if we can add the text field on the same line as the last contact view - if (self.frame.size.width - kHorizontalSidePadding - _frameOfLastView.origin.x - _frameOfLastView.size.width - minWidth >= 0){ // add to the same line - textFieldFrame.origin.x = _frameOfLastView.origin.x + _frameOfLastView.size.width + _contactHorizontalPadding; - textFieldFrame.size.width = self.frame.size.width - textFieldFrame.origin.x; + if (self.frame.size.width - kHorizontalSidePadding - _frameOfLastView.origin.x - _frameOfLastView.size.width - minWidth >= 0 || self.scrollHorizontal){ // add to the same line + if (self.contacts.count == 0 && self.scrollHorizontal){ + _lineCount = 0; + textFieldFrame.origin.x = [self firstLineXOffset]; + textFieldFrame.size.width = self.bounds.size.width - textFieldFrame.origin.x; + } + else{ + textFieldFrame.origin.x = _frameOfLastView.origin.x + _frameOfLastView.size.width + _contactHorizontalPadding; + textFieldFrame.size.width = self.frame.size.width - textFieldFrame.origin.x; + } } else { // place text view on the next line _lineCount++; @@ -465,6 +482,18 @@ - (void)layoutSubviews { - (void)layoutScrollView { // Adjust scroll view content size CGRect frame = self.bounds; + if (_scrollHorizontal) { + self.scrollView.contentSize = CGSizeMake(self.textField.frame.origin.x + self.textField.frame.size.width, self.lineHeight + 2 * self.verticalPadding); + frame.size.height = self.scrollView.contentSize.height; + self.scrollView.frame = frame; + CGRect selfFrame = self.frame; + selfFrame.size.height = frame.size.height; + self.frame = selfFrame; + if ([self.delegate respondsToSelector:@selector(contactPickerDidResize:)]){ + [self.delegate contactPickerDidResize:self]; + } + return; + } CGFloat maxFrameHeight = self.maxNumberOfLines * self.lineHeight + 2 * self.verticalPadding; // limit frame to two lines of content CGFloat newHeight = (_lineCount + 1) * self.lineHeight + 2 * self.verticalPadding; self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width, newHeight); diff --git a/ContactPicker/THContactPickerViewControllerDemo.m b/ContactPicker/THContactPickerViewControllerDemo.m index d9daa19..de622aa 100755 --- a/ContactPicker/THContactPickerViewControllerDemo.m +++ b/ContactPicker/THContactPickerViewControllerDemo.m @@ -50,6 +50,8 @@ - (void)viewDidLoad { self.contactPickerView.delegate = self; [self.contactPickerView setPlaceholderLabelText:@"Who would you like to message?"]; [self.contactPickerView setPromptLabelText:@"To:"]; + [self.contactPickerView setMaxNumberOfLines:1]; + self.contactPickerView.scrollHorizontal = YES; //[self.contactPickerView setLimitToOne:YES]; [self.view addSubview:self.contactPickerView]; From 6a2093e9879a03350c3046b0ba307769d37bf7db Mon Sep 17 00:00:00 2001 From: zzzworm Date: Wed, 18 May 2016 17:20:31 +0800 Subject: [PATCH 02/11] export the textfield --- Classes/THContactPickerView.h | 1 + Classes/THContactPickerView.m | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/THContactPickerView.h b/Classes/THContactPickerView.h index 8dde38b..57b3c1c 100755 --- a/Classes/THContactPickerView.h +++ b/Classes/THContactPickerView.h @@ -26,6 +26,7 @@ @interface THContactPickerView : UIView +@property (nonatomic, strong) THContactTextField *textField; @property (nonatomic, strong) THContactView *selectedContactView; @property (nonatomic, assign) IBOutlet id delegate; diff --git a/Classes/THContactPickerView.m b/Classes/THContactPickerView.m index 2b6a2a2..0f382a4 100755 --- a/Classes/THContactPickerView.m +++ b/Classes/THContactPickerView.m @@ -24,7 +24,6 @@ @interface THContactPickerView (){ @property (nonatomic, strong) UILabel *placeholderLabel; @property (nonatomic, strong) UILabel *promptLabel; @property (nonatomic, assign) CGFloat lineHeight; -@property (nonatomic, strong) THContactTextField *textField; @property (nonatomic, strong) THContactViewStyle *contactViewStyle; @property (nonatomic, strong) THContactViewStyle *contactViewSelectedStyle; From 713c12a81ead9e64cef7ea1d914e33e7cf48ff51 Mon Sep 17 00:00:00 2001 From: zzzworm Date: Thu, 19 May 2016 10:31:06 +0800 Subject: [PATCH 03/11] min textfield padding to right, fixed scroll for textfield --- Classes/THContactPickerView.m | 44 +++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/Classes/THContactPickerView.m b/Classes/THContactPickerView.m index 0f382a4..dc1af50 100755 --- a/Classes/THContactPickerView.m +++ b/Classes/THContactPickerView.m @@ -36,7 +36,8 @@ @implementation THContactPickerView #define kHorizontalPaddingWithBackground 2 // the amount of padding to the left and right of each contact view (when bubbles have a non white background) #define kHorizontalSidePadding 10 // the amount of padding on the left and right of the view #define kVerticalPadding 2 // amount of padding above and below each contact view -#define kTextFieldMinWidth 20 // minimum width of trailing text view +#define kContactViewMinWidth 20 // minimum width of trailing text view +#define kTextFieldMinWidth 120 // minimum width of trailing text view #define KMaxNumberOfLinesDefault 2 - (id)initWithCoder:(NSCoder *)aDecoder { @@ -179,7 +180,7 @@ - (void)addContact:(id)contact withName:(NSString *)name withStyle:(THContactVie THContactView *contactView = [[THContactView alloc] initWithName:name style:bubbleStyle selectedStyle:selectedStyle showComma:_showComma]; contactView.maxWidth = self.frame.size.width - self.promptLabel.frame.origin.x - 2 * _contactHorizontalPadding - 2 * kHorizontalSidePadding; - contactView.minWidth = kTextFieldMinWidth + 2 * _contactHorizontalPadding; + contactView.minWidth = kContactViewMinWidth + 2 * _contactHorizontalPadding; contactView.keyboardAppearance = self.keyboardAppearance; contactView.returnKeyType = self.returnKeyType; contactView.delegate = self; @@ -292,27 +293,34 @@ - (BOOL)becomeFirstResponder { - (void)scrollToBottomWithAnimation:(BOOL)animated { if (animated){ CGSize size = self.scrollView.contentSize; - CGRect frame; - if (self.scrollHorizontal) { - frame = CGRectMake(size.width - self.scrollView.frame.size.width, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height); - } - else{ - frame = CGRectMake(0, size.height - self.scrollView.frame.size.height, size.width, self.scrollView.frame.size.height); - } + CGRect frame = CGRectMake(0, size.height - self.scrollView.frame.size.height, size.width, self.scrollView.frame.size.height); + [self.scrollView scrollRectToVisible:frame animated:animated]; } else { // this block is here because scrollRectToVisible with animated NO causes crashes on iOS 5 when the user tries to delete many contacts really quickly CGPoint offset = self.scrollView.contentOffset; - if (self.scrollHorizontal) { - offset.x = self.scrollView.contentSize.width - self.scrollView.frame.size.width; - } - else{ - offset.y = self.scrollView.contentSize.height - self.scrollView.frame.size.height; - } + offset.y = self.scrollView.contentSize.height - self.scrollView.frame.size.height; self.scrollView.contentOffset = offset; } } + +//- (void)scrollToRightWithAnimation:(BOOL)animated { +// if (animated){ +// CGSize size = self.scrollView.contentSize; +// CGRect frame = CGRectMake(size.width - self.scrollView.frame.size.width, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height); +// +// [self.scrollView scrollRectToVisible:frame animated:animated]; +// } else { +// // this block is here because scrollRectToVisible with animated NO causes crashes on iOS 5 when the user tries to delete many contacts really quickly +// CGPoint offset = self.scrollView.contentOffset; +// +// offset.x = self.scrollView.contentSize.width - self.scrollView.frame.size.width; +// +// self.scrollView.contentOffset = offset; +// } +//} + - (void)removeContactView:(THContactView *)contactView { id contact = [self contactForContactView:contactView]; @@ -426,11 +434,11 @@ - (void)layoutContactViews { if (self.contacts.count == 0 && self.scrollHorizontal){ _lineCount = 0; textFieldFrame.origin.x = [self firstLineXOffset]; - textFieldFrame.size.width = self.bounds.size.width - textFieldFrame.origin.x; + //textFieldFrame.size.width = self.bounds.size.width - textFieldFrame.origin.x; } else{ textFieldFrame.origin.x = _frameOfLastView.origin.x + _frameOfLastView.size.width + _contactHorizontalPadding; - textFieldFrame.size.width = self.frame.size.width - textFieldFrame.origin.x; + //textFieldFrame.size.width = self.frame.size.width - textFieldFrame.origin.x; } } else { // place text view on the next line @@ -445,7 +453,7 @@ - (void)layoutContactViews { textFieldFrame.size.width = self.bounds.size.width - textFieldFrame.origin.x; } } - + textFieldFrame.size.width = fmax(minWidth,textFieldFrame.size.width); textFieldFrame.origin.y = _lineCount * self.lineHeight + kVerticalPadding + self.verticalPadding; self.textField.frame = textFieldFrame; From d27bb04cdcedbf8ec80a75095775c393ec7d3744 Mon Sep 17 00:00:00 2001 From: zzzworm Date: Thu, 19 May 2016 10:43:56 +0800 Subject: [PATCH 04/11] fixed scroll for textfield --- Classes/THContactPickerView.m | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Classes/THContactPickerView.m b/Classes/THContactPickerView.m index dc1af50..7cce71f 100755 --- a/Classes/THContactPickerView.m +++ b/Classes/THContactPickerView.m @@ -552,9 +552,17 @@ - (void)textFieldDidChange:(THContactTextField *)textField { } CGPoint offset = self.scrollView.contentOffset; - offset.y = self.scrollView.contentSize.height - self.scrollView.frame.size.height; - if (offset.y > self.scrollView.contentOffset.y){ - [self scrollToBottomWithAnimation:YES]; + if (self.scrollHorizontal) { + offset.x = self.scrollView.contentSize.width - self.scrollView.frame.size.width; + if (offset.x > self.scrollView.contentOffset.x){ + [self scrollToBottomWithAnimation:YES]; + } + } + else{ + offset.y = self.scrollView.contentSize.height - self.scrollView.frame.size.height; + if (offset.y > self.scrollView.contentOffset.y){ + [self scrollToBottomWithAnimation:YES]; + } } } From 200ae50aba4eaf93074f894e44a655f577011637 Mon Sep 17 00:00:00 2001 From: zzzworm Date: Thu, 19 May 2016 11:07:32 +0800 Subject: [PATCH 05/11] textfield padding size --- Classes/THContactPickerView.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/THContactPickerView.m b/Classes/THContactPickerView.m index 7cce71f..af3587d 100755 --- a/Classes/THContactPickerView.m +++ b/Classes/THContactPickerView.m @@ -37,7 +37,7 @@ @implementation THContactPickerView #define kHorizontalSidePadding 10 // the amount of padding on the left and right of the view #define kVerticalPadding 2 // amount of padding above and below each contact view #define kContactViewMinWidth 20 // minimum width of trailing text view -#define kTextFieldMinWidth 120 // minimum width of trailing text view +#define kTextFieldMinWidth 80 // minimum width of trailing text view #define KMaxNumberOfLinesDefault 2 - (id)initWithCoder:(NSCoder *)aDecoder { From 0b9f79bb99e603cd16fa929e361eabcdbc7dca5a Mon Sep 17 00:00:00 2001 From: zzzworm Date: Thu, 19 May 2016 15:58:24 +0800 Subject: [PATCH 06/11] add header import --- Classes/THContactPickerView.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/THContactPickerView.h b/Classes/THContactPickerView.h index 57b3c1c..4aa8606 100755 --- a/Classes/THContactPickerView.h +++ b/Classes/THContactPickerView.h @@ -8,7 +8,7 @@ #import #import "THContactView.h" - +#import "THContactTextField.h" @class THContactPickerView; @protocol THContactPickerDelegate From 9aac63f7611cea976584e22fb5873b6be39dd635 Mon Sep 17 00:00:00 2001 From: zzzworm Date: Fri, 3 Jun 2016 18:56:39 +0800 Subject: [PATCH 07/11] placeholder can set by attributed text --- Classes/THContactPickerView.h | 1 + Classes/THContactPickerView.m | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/Classes/THContactPickerView.h b/Classes/THContactPickerView.h index 4aa8606..22206f3 100755 --- a/Classes/THContactPickerView.h +++ b/Classes/THContactPickerView.h @@ -47,6 +47,7 @@ - (void)setContactViewStyle:(THContactViewStyle *)color selectedStyle:(THContactViewStyle *)selectedColor; - (void)setPlaceholderLabelText:(NSString *)text; - (void)setPlaceholderLabelTextColor:(UIColor *)color; +- (void)setPlaceholderLabelAttributedText:(NSAttributedString *)attributedText; - (void)setPromptLabelText:(NSString *)text; - (void)setPromptLabelAttributedText:(NSAttributedString *)attributedText; - (void)setPromptLabelTextColor:(UIColor *)color; diff --git a/Classes/THContactPickerView.m b/Classes/THContactPickerView.m index af3587d..6320040 100755 --- a/Classes/THContactPickerView.m +++ b/Classes/THContactPickerView.m @@ -139,6 +139,11 @@ - (void)setPlaceholderLabelTextColor:(UIColor *)color{ self.placeholderLabel.textColor = color; } +- (void)setPlaceholderLabelAttributedText:(NSAttributedString *)attributedText +{ + self.placeholderLabel.attributedText = attributedText; +} + - (void)setPromptLabelTextColor:(UIColor *)color{ self.promptLabel.textColor = color; } From 10483a4fe3db6da3d672e74f6beccfb946bb00b4 Mon Sep 17 00:00:00 2001 From: zzzworm Date: Tue, 7 Jun 2016 15:22:54 +0800 Subject: [PATCH 08/11] unselected not auto highlight textfield --- Classes/THContactPickerView.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Classes/THContactPickerView.m b/Classes/THContactPickerView.m index 6320040..99bcd6b 100755 --- a/Classes/THContactPickerView.m +++ b/Classes/THContactPickerView.m @@ -612,8 +612,8 @@ - (void)contactViewWasUnSelected:(THContactView *)contactView { if (self.selectedContactView == contactView){ self.selectedContactView = nil; } - - [self selectTextField]; + self.textField.hidden = NO; + //[self selectTextField]; // transfer the text fromt he textField within the ContactView if there was any // ***This is important if the user starts to type when a contact view is selected self.textField.text = contactView.textField.text; From ba0c32fd3f5c81ff309ab7b69255aae8d0147d70 Mon Sep 17 00:00:00 2001 From: zzzworm Date: Tue, 7 Jun 2016 16:56:16 +0800 Subject: [PATCH 09/11] fixed hit the textfield --- Classes/THContactPickerView.m | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Classes/THContactPickerView.m b/Classes/THContactPickerView.m index 99bcd6b..d9055e1 100755 --- a/Classes/THContactPickerView.m +++ b/Classes/THContactPickerView.m @@ -90,7 +90,7 @@ - (void)setup { self.backgroundColor = [UIColor whiteColor]; - UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture)]; + UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)]; tapGesture.numberOfTapsRequired = 1; tapGesture.numberOfTouchesRequired = 1; [self addGestureRecognizer:tapGesture]; @@ -630,10 +630,15 @@ - (void)contactViewShouldBeRemoved:(THContactView *)contactView { #pragma mark - Gesture Recognizer -- (void)handleTapGesture { +- (void)handleTapGesture:(UITapGestureRecognizer*)gesture { if (self.limitToOne && self.contactKeys.count == 1){ return; } + CGPoint tapPoint = [gesture locationInView:self.scrollView]; + if (!CGRectContainsPoint(self.textField.frame, tapPoint)) { + // Do stuff if they tapped anywhere outside the text field + return; + } [self scrollToBottomWithAnimation:YES]; // Show textField From 7b970839d28ee62b91565489ddc0cc25db7b38c1 Mon Sep 17 00:00:00 2001 From: zzzworm Date: Mon, 13 Jun 2016 14:07:53 +0800 Subject: [PATCH 10/11] fixed textfield when first line --- Classes/THContactPickerView.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Classes/THContactPickerView.m b/Classes/THContactPickerView.m index d9055e1..6b492f3 100755 --- a/Classes/THContactPickerView.m +++ b/Classes/THContactPickerView.m @@ -439,11 +439,11 @@ - (void)layoutContactViews { if (self.contacts.count == 0 && self.scrollHorizontal){ _lineCount = 0; textFieldFrame.origin.x = [self firstLineXOffset]; - //textFieldFrame.size.width = self.bounds.size.width - textFieldFrame.origin.x; + textFieldFrame.size.width = self.bounds.size.width - textFieldFrame.origin.x; } else{ textFieldFrame.origin.x = _frameOfLastView.origin.x + _frameOfLastView.size.width + _contactHorizontalPadding; - //textFieldFrame.size.width = self.frame.size.width - textFieldFrame.origin.x; + textFieldFrame.size.width = self.frame.size.width - textFieldFrame.origin.x; } } else { // place text view on the next line From 1ad64a2f272c0a851188687f11da2c5f3e682f59 Mon Sep 17 00:00:00 2001 From: zzzworm Date: Mon, 13 Jun 2016 14:08:13 +0800 Subject: [PATCH 11/11] fixed textfield when first line --- Classes/THContactPickerView.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Classes/THContactPickerView.m b/Classes/THContactPickerView.m index 6b492f3..3a4289c 100755 --- a/Classes/THContactPickerView.m +++ b/Classes/THContactPickerView.m @@ -439,12 +439,11 @@ - (void)layoutContactViews { if (self.contacts.count == 0 && self.scrollHorizontal){ _lineCount = 0; textFieldFrame.origin.x = [self firstLineXOffset]; - textFieldFrame.size.width = self.bounds.size.width - textFieldFrame.origin.x; } else{ textFieldFrame.origin.x = _frameOfLastView.origin.x + _frameOfLastView.size.width + _contactHorizontalPadding; - textFieldFrame.size.width = self.frame.size.width - textFieldFrame.origin.x; } + textFieldFrame.size.width = self.frame.size.width - textFieldFrame.origin.x; } else { // place text view on the next line _lineCount++;