Closed alexeyndru closed 11 years ago
1.The textView grows at each letter typed and not only at pressing the return key -in setupview change [self.textView setScrollEnabled:NO]; => //[self.textView setScrollEnabled:NO]; -in resizeTextViewByHeight change self.textView.scrollEnabled = (numLines >= 4); => //self.textView.scrollEnabled = (numLines >= 4);
Hi @alexeyndru, apparently in iOS7 the contentSize's height of the textview is always increasing for whatever reason. I have to change the way I'm using to compute the new text height, I should be able to fix it today. As for the animation quirks I need to figure out what's happening :) I'll get back to you as soon as possible.
Thank you very much! Your library helped me a lot.
Hey Andremazz, have you managed to find the solution yet?
Not yet, sorry, I've been swamped at work. I noticed similiar issues in other chat components, so I might need to rethink part of the text input handling and animation. I should have time to work on it this weekend, I'll keep you posted
Thanks, do you also experience lag?
On Sat, Oct 5, 2013 at 3:31 PM, Andrea Mazzini notifications@github.com wrote:
Not yet, sorry, I've been swamped at work. I noticed similiar issues in other chat components, so I might need to rethink part of the text input handling and animation. I should have time to work on it this weekend, I'll keep you posted
Reply to this email directly or view it on GitHub: https://github.com/andreamazz/AMBubbleTableView/issues/12#issuecomment-25743730
What kind of lag?
Anyway, I was able to fix the animation quirkiness in commit 7570af3 I'm still trying to figure out how to fix the textview's sizing though.
Sorry, I meant quirkiness. Yeah the text view is really odd, and the problem shows up in all the other open source message projects.
If you uncomment the lines around 419 in AMBubbleTableViewController.m, the problem mitigates, but the position is then messed up and it won't scroll.
// // AMBubbleTableViewController.m // BubbleTableDemo // // Created by Andrea Mazzini on 30/06/13. // Copyright (c) 2013 Andrea Mazzini. All rights reserved. //
@interface AMBubbleTableViewController () <UITableViewDataSource, UITableViewDelegate, UITextViewDelegate>
@property (strong, nonatomic) NSMutableDictionary* options; @property (nonatomic, strong) UIImageView* imageInput; @property (nonatomic, strong) UITextView* textView; @property (nonatomic, strong) UIImageView* imageInputBack; @property (nonatomic, strong) UIButton* buttonSend; @property (nonatomic, strong) NSDateFormatter* dateFormatter; @property (nonatomic, assign) float previousTextFieldHeight;
@end
@implementation AMBubbleTableViewController
(void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleKeyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleKeyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; }
(void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; }
(void)setupView { UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)]; // Table View CGRect tableFrame = CGRectMake(0.0f, 0.0f, self.view.frame.size.width, self.view.frame.size.height - kInputHeight); self.tableView = [[UITableView alloc] initWithFrame:tableFrame style:UITableViewStylePlain]; [self.tableView addGestureRecognizer:gestureRecognizer]; [self.tableView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; [self.tableView setDataSource:self]; [self.tableView setDelegate:self]; [self.tableView setBackgroundColor:self.options[AMOptionsBubbleTableBackground]]; [self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone]; [self.view addSubview:self.tableView];
// Input background CGRect inputFrame = CGRectMake(0.0f, self.view.frame.size.height - kInputHeight, self.view.frame.size.width, kInputHeight); self.imageInput = [[UIImageView alloc] initWithImage:self.options[AMOptionsImageBar]]; [self.imageInput setFrame:inputFrame]; [self.imageInput setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin)]; [self.imageInput setUserInteractionEnabled:YES];
[self.view addSubview:self.imageInput];
// Input field CGFloat width = self.imageInput.frame.size.width - kButtonWidth;
self.textView = [[UITextView alloc] initWithFrame:CGRectMake(6.0f, 3.0f, width, kLineHeight)]; [self.textView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; [self.textView setScrollIndicatorInsets:UIEdgeInsetsMake(10.0f, 0.0f, 10.0f, 8.0f)]; [self.textView setContentInset:UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f)]; //[self.textView setScrollEnabled:NO]; [self.textView setScrollsToTop:NO]; [self.textView setUserInteractionEnabled:YES]; [self.textView setFont:self.options[AMOptionsTextFieldFont]]; [self.textView setTextColor:self.options[AMOptionsTextFieldFontColor]]; [self.textView setBackgroundColor:self.options[AMOptionsTextFieldBackground]]; [self.textView setKeyboardAppearance:UIKeyboardAppearanceDefault]; [self.textView setKeyboardType:UIKeyboardTypeDefault]; [self.textView setReturnKeyType:UIReturnKeyDefault];
[self.textView setDelegate:self]; [self.imageInput addSubview:self.textView]; // self.previousTextFieldHeight = self.textView.contentSize.height; // if ([[UIDevice currentDevice].systemVersion intValue]==7) // self.previousTextFieldHeight=34;
UITextView *tempTextView = [[UITextView alloc] init]; tempTextView.font = self.textView.font; tempTextView.text = @""; CGSize size = [tempTextView sizeThatFits:CGSizeMake(self.textView.frame.size.width, FLT_MAX)]; self.previousTextFieldHeight = size.height;
// Input field's background self.imageInputBack = [[UIImageView alloc] initWithFrame:CGRectMake(self.textView.frame.origin.x - 1.0f, 0.0f, self.textView.frame.size.width + 2.0f, self.imageInput.frame.size.height)]; [self.imageInputBack setImage:self.options[AMOptionsImageInput]]; [self.imageInputBack setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)]; [self.imageInputBack setBackgroundColor:[UIColor clearColor]]; [self.imageInputBack setUserInteractionEnabled:NO]; [self.imageInput addSubview:self.imageInputBack];
// Send button self.buttonSend = [UIButton buttonWithType:UIButtonTypeCustom]; [self.buttonSend setAutoresizingMask:(UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin)];
UIImage sendBack = self.options[AMOptionsImageButton]; UIImage sendBackHighLighted = self.options[AMOptionsImageButtonHighlight]; [self.buttonSend setBackgroundImage:sendBack forState:UIControlStateNormal]; [self.buttonSend setBackgroundImage:sendBack forState:UIControlStateDisabled]; [self.buttonSend setBackgroundImage:sendBackHighLighted forState:UIControlStateHighlighted]; [self.buttonSend.titleLabel setFont:self.options[AMOptionsButtonFont]];
NSString *title = NSLocalizedString(@"Send",); [self.buttonSend setTitle:title forState:UIControlStateNormal]; [self.buttonSend setTitle:title forState:UIControlStateHighlighted]; [self.buttonSend setTitle:title forState:UIControlStateDisabled]; self.buttonSend.titleLabel.font = [UIFont boldSystemFontOfSize:16.0f];
UIColor *titleShadow = [UIColor colorWithRed:0.325f green:0.463f blue:0.675f alpha:1.0f]; [self.buttonSend setTitleShadowColor:titleShadow forState:UIControlStateNormal]; [self.buttonSend setTitleShadowColor:titleShadow forState:UIControlStateHighlighted]; self.buttonSend.titleLabel.shadowOffset = CGSizeMake(0.0f, -1.0f);
[self.buttonSend setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [self.buttonSend setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted]; [self.buttonSend setTitleColor:[UIColor colorWithWhite:1.0f alpha:0.5f] forState:UIControlStateDisabled];
[self.buttonSend setEnabled:NO]; [self.buttonSend setFrame:CGRectMake(self.imageInput.frame.size.width - 65.0f, [self.options[AMOptionsButtonOffset] floatValue], 59.0f, 26.0f)]; [self.buttonSend addTarget:self action:@selector(sendPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.imageInput addSubview:self.buttonSend]; }
(UITableViewCell)tableView:(UITableView )tableView cellForRowAtIndexPath:(NSIndexPath )indexPath { AMBubbleCellType type = [self.dataSource cellTypeForRowAtIndexPath:indexPath]; NSString cellID = [NSString stringWithFormat:@"cell_%d", type]; NSString* text = [self.dataSource textForRowAtIndexPath:indexPath]; NSDate* date = [self.dataSource timestampForRowAtIndexPath:indexPath]; AMBubbleTableCell* cell = [tableView dequeueReusableCellWithIdentifier:cellID];
UIImage* avatar; UIColor* color;
if ([self.dataSource respondsToSelector:@selector(usernameColorForRowAtIndexPath:)]) { color = [self.dataSource usernameColorForRowAtIndexPath:indexPath]; } if ([self.dataSource respondsToSelector:@selector(avatarForRowAtIndexPath:)]) { avatar = [self.dataSource avatarForRowAtIndexPath:indexPath]; }
if (cell == nil) { cell = [[AMBubbleTableCell alloc] initWithOptions:self.options reuseIdentifier:cellID];
// iPad cells are set by default to 320 pixels, this fixes the quirk
cell.contentView.frame = CGRectMake(cell.contentView.frame.origin.x,
cell.contentView.frame.origin.y,
self.tableView.frame.size.width,
cell.contentView.frame.size.height);
if ([self.options[AMOptionsBubbleSwipeEnabled] boolValue]) {
UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeGesture:)];
swipeGesture.direction = UISwipeGestureRecognizerDirectionLeft|UISwipeGestureRecognizerDirectionRight;
[cell addGestureRecognizer:swipeGesture];
}
if ([self.options[AMOptionsBubblePressEnabled] boolValue]) {
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressGesture:)];
[cell addGestureRecognizer:longPressGesture];
}
}
// Used by the gesture recognizer cell.tag = indexPath.row; cell.delegate=self;
NSString* stringDate; if (type == AMBubbleCellTimestamp) { [self.dateFormatter setDateStyle:NSDateFormatterMediumStyle]; // Jan 1, 2000 [self.dateFormatter setTimeStyle:NSDateFormatterShortStyle]; // 1:23 PM stringDate = [self.dateFormatter stringFromDate:date]; [cell setupCellWithType:type withWidth:self.tableView.frame.size.width andParams:@{ @"date": stringDate }]; } else { [self.dateFormatter setDateFormat:@"HH:mm"]; // 13:23 NSString* username; if ([self.dataSource respondsToSelector:@selector(usernameForRowAtIndexPath:)]) { username = [self.dataSource usernameForRowAtIndexPath:indexPath]; } stringDate = [self.dateFormatter stringFromDate:date]; [cell setupCellWithType:type withWidth:self.tableView.frame.size.width andParams:@{ @"text": text, @"date": stringDate, @"index": @(indexPath.row), @"username": (username ? username : @""), @"avatar": (avatar ? avatar: @""), @"color": (color ? color: @"") }]; }
return cell; }
(CGFloat)tableView:(UITableView )tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { AMBubbleCellType type = [self.dataSource cellTypeForRowAtIndexPath:indexPath]; NSString text = [self.dataSource textForRowAtIndexPath:indexPath]; NSString* username = @"";
if ([self.dataSource respondsToSelector:@selector(usernameForRowAtIndexPath:)]) { username = [self.dataSource usernameForRowAtIndexPath:indexPath]; }
if (type == AMBubbleCellTimestamp) { return [self.options[AMOptionsTimestampHeight] floatValue]; }
// Set MessageCell height. CGSize size = [text sizeWithFont:self.options[AMOptionsBubbleTextFont] constrainedToSize:CGSizeMake(kMessageTextWidth, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
CGSize usernameSize = CGSizeZero;
if (![username isEqualToString:@""] && type == AMBubbleCellReceived) { usernameSize = [username sizeWithFont:self.options[AMOptionsTimestampFont] constrainedToSize:CGSizeMake(kMessageTextWidth, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping]; }
// Account for either the bubble or accessory size return MAX(size.height + 17.0f + usernameSize.height, [self.options[AMOptionsAccessorySize] floatValue] + [self.options[AMOptionsAccessoryMargin] floatValue]); }
(void)resizeView:(NSNotification*)notification { CGRect keyboardRect = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; UIViewAnimationCurve curve = [[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue]; double duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGFloat viewHeight = (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation) ? MIN(self.view.frame.size.width,self.view.frame.size.height) : MAX(self.view.frame.size.width,self.view.frame.size.height)); CGFloat keyboardY = [self.view convertRect:keyboardRect fromView:nil].origin.y; CGFloat diff = keyboardY - viewHeight;
// This check prevents an issue when the view is inside a UITabBarController if (diff > 0) { double fraction = diff/keyboardY; duration *= (1-fraction); keyboardY = viewHeight; }
// Thanks to Raja Baz (@raja-baz) for the delay's animation fix. CGFloat delay = 0.0f; CGRect beginRect = [[notification.userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue]; diff = beginRect.origin.y - viewHeight; if (diff > 0) { double fraction = diff/beginRect.origin.y; delay = duration * fraction; duration -= delay; }
void (^completition)(void) = ^{ CGFloat inputViewFrameY = keyboardY - self.imageInput.frame.size.height;
self.imageInput.frame = CGRectMake(self.imageInput.frame.origin.x,
inputViewFrameY,
self.imageInput.frame.size.width,
self.imageInput.frame.size.height);
UIEdgeInsets insets = UIEdgeInsetsMake(0.0f,
0.0f,
viewHeight - self.imageInput.frame.origin.y - kInputHeight,
0.0f);
self.tableView.contentInset = insets;
self.tableView.scrollIndicatorInsets = insets;
};
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) { [UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:500.0f initialSpringVelocity:0.0f options:UIViewAnimationOptionCurveLinear animations:completition completion:nil]; } else { [UIView animateWithDuration:duration delay:delay options:[AMBubbleGlobals animationOptionsForCurve:curve] animations:completition completion:nil]; } }
(void)resizeTextViewByHeight:(CGFloat)delta { int numLines = self.textView.contentSize.height / self.textView.font.lineHeight;
self.textView.contentInset = UIEdgeInsetsMake((numLines >= 6 ? 4.0f : 0.0f), 0.0f, (numLines >= 6 ? 4.0f : 0.0f), 0.0f);
//self.textView.scrollEnabled = (numLines >= 4);
// Adjust table view's insets CGFloat viewHeight = (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) ? self.view.frame.size.width : self.view.frame.size.height; UIEdgeInsets insets = UIEdgeInsetsMake(0.0f, 0.0f, viewHeight - self.imageInput.frame.origin.y - kInputHeight, 0.0f);
self.tableView.contentInset = insets; self.tableView.scrollIndicatorInsets = insets;
// Slightly scroll the table [self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y + delta) animated:YES]; }
(void)textViewDidChange:(UITextView *)textView { [self.buttonSend setEnabled:([textView.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]].length > 0)];
CGFloat maxHeight = self.textView.font.lineHeight * 5; // CGFloat textViewContentHeight = textView.contentSize.height; // NSLog(@"textViewContentHeight1 =%f",textViewContentHeight); //workaround for iOS7, still not working wuite right... UITextView *tempTextView = [[UITextView alloc] init]; tempTextView.font = self.textView.font; tempTextView.text = self.textView.text; CGSize size = [tempTextView sizeThatFits:CGSizeMake(self.textView.frame.size.width, FLT_MAX)]; CGFloat textViewContentHeight = size.height; NSLog(@"textViewContentHeight =%f",textViewContentHeight);
CGFloat delta = textViewContentHeight - self.previousTextFieldHeight; BOOL isShrinking = textViewContentHeight < self.previousTextFieldHeight;
delta = (textViewContentHeight + delta >= maxHeight) ? 0.0f : delta;
if(!isShrinking) [self resizeTextViewByHeight:delta];
if(delta != 0.0f) { [UIView animateWithDuration:0.25f animations:^{ UIEdgeInsets insets = UIEdgeInsetsMake(0.0f, 0.0f, self.tableView.contentInset.bottom + delta, 0.0f); self.tableView.contentInset = insets; self.tableView.scrollIndicatorInsets = insets;
[self scrollToBottomAnimated:NO];
self.imageInput.frame = CGRectMake(0.0f,
self.imageInput.frame.origin.y - delta,
self.imageInput.frame.size.width,
self.imageInput.frame.size.height + delta);
}
completion:^(BOOL finished) {
if(isShrinking)
[self resizeTextViewByHeight:delta];
}];
self.previousTextFieldHeight = MIN(textViewContentHeight, maxHeight);
NSLog(@"self.previousTextFieldHeight =%f",self.previousTextFieldHeight);
} }
@end
Hi @vutrongtung, as you can see it's kinda hard to make out what part of the file you modified :) Can you please modify your comment by including the source in a comment tag (by using three backquotes as described here. Or you can create a new pull request. Thanks you for your contribution.
Ok, all fixed in the last commit. Version 0.5 pushed to cocoapods. Thanks again @vutrongtung