Skip to content

Commit 97387c0

Browse files
committed
Fix iOS content size issue
Added KVO to adjust the textview frame. Fix the new line visible issue in iOS 7
1 parent 8af1559 commit 97387c0

File tree

2 files changed

+37
-31
lines changed

2 files changed

+37
-31
lines changed

JSMessagesViewController/Classes/JSMessageInputView.m

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ - (instancetype)initWithFrame:(CGRect)frame
141141
_textView.delegate = delegate;
142142
_textView.keyboardDelegate = delegate;
143143
_textView.dismissivePanGestureRecognizer = panGestureRecognizer;
144+
145+
// From iOS 7, the content size will be calculated after the delegate method calls complete. So we are adding KVO to the content size of the text view to accomadate the content size for the new line text.
146+
[_textView addObserver:delegate forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
144147
}
145148
return self;
146149
}
@@ -190,19 +193,24 @@ - (void)adjustTextViewHeightBy:(CGFloat)changeInHeight
190193
int numLines = MAX([self.textView numberOfLinesOfText],
191194
[self.textView.text js_numberOfLines]);
192195

196+
// Below iOS 7, if you set the text view frame programmatically, the KVO will keep on notify the observer method. So to avoid that, we are removing the observer before setting the frame and add the observer after setting frame here.
197+
[self.textView removeObserver:_textView.keyboardDelegate forKeyPath:@"contentSize"];
193198
self.textView.frame = CGRectMake(prevFrame.origin.x,
194199
prevFrame.origin.y,
195200
prevFrame.size.width,
196201
prevFrame.size.height + changeInHeight);
197-
202+
[self.textView addObserver:_textView.keyboardDelegate forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
203+
198204
self.textView.contentInset = UIEdgeInsetsMake((numLines >= 6 ? 4.0f : 0.0f),
199205
0.0f,
200206
(numLines >= 6 ? 4.0f : 0.0f),
201207
0.0f);
202208

203-
self.textView.scrollEnabled = (numLines >= 4);
209+
// From iOS 7, the content size will be accurate only if the scrolling is enabled.
210+
self.textView.scrollEnabled = YES;
204211

205-
if(numLines >= 6) {
212+
// Set the content offset only when user enters the new line.
213+
if(numLines >= 6 && [self.textView.text hasSuffix:@"\n"]) {
206214
CGPoint bottomOffset = CGPointMake(0.0f, self.textView.contentSize.height - self.textView.bounds.size.height);
207215
[self.textView setContentOffset:bottomOffset animated:YES];
208216
}

JSMessagesViewController/Classes/JSMessagesViewController.m

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -396,41 +396,18 @@ - (void)textViewDidEndEditing:(UITextView *)textView
396396
[textView resignFirstResponder];
397397
}
398398

399-
- (void)textViewDidChange:(UITextView *)textView
400-
{
399+
- (void)refreshViewFrames:(UITextView *)textView {
401400
CGFloat maxHeight = [JSMessageInputView maxHeight];
402401

403-
// TODO:
404-
//
405-
// CGFloat textViewContentHeight = textView.contentSize.height;
406-
//
407-
// The line above is broken as of iOS 7.0
408-
//
409-
// There seems to be a bug in Apple's code for textView.contentSize
410-
// The following code was implemented as a workaround for calculating the appropriate textViewContentHeight
411-
//
412-
// https://devforums.apple.com/thread/192052
413-
// https://github.com/jessesquires/MessagesTableViewController/issues/50
414-
// https://github.com/jessesquires/MessagesTableViewController/issues/47
415-
//
416-
// BEGIN HACK
417-
//
418-
CGSize size = [textView sizeThatFits:CGSizeMake(textView.frame.size.width, maxHeight)];
419-
CGFloat textViewContentHeight = size.height;
420-
//
421-
// END HACK
422-
//
423-
424-
BOOL isShrinking = textViewContentHeight < self.previousTextViewContentHeight;
425-
CGFloat changeInHeight = textViewContentHeight - self.previousTextViewContentHeight;
426-
402+
BOOL isShrinking = textView.contentSize.height < self.previousTextViewContentHeight;
403+
CGFloat changeInHeight = textView.contentSize.height - self.previousTextViewContentHeight;
404+
427405
if(!isShrinking && (self.previousTextViewContentHeight == maxHeight || textView.text.length == 0)) {
428406
changeInHeight = 0;
429407
}
430408
else {
431409
changeInHeight = MIN(changeInHeight, maxHeight - self.previousTextViewContentHeight);
432410
}
433-
434411
if(changeInHeight != 0.0f) {
435412

436413
[UIView animateWithDuration:0.25f
@@ -463,12 +440,33 @@ - (void)textViewDidChange:(UITextView *)textView
463440
completion:^(BOOL finished) {
464441
}];
465442

466-
self.previousTextViewContentHeight = MIN(textViewContentHeight, maxHeight);
443+
self.previousTextViewContentHeight = MIN(textView.contentSize.height, maxHeight);
444+
}
445+
446+
// Once we reached the max height, we have to consider the bottom offset for the text view.
447+
// To make visible the last line, again we have to set the content offset.
448+
if (self.previousTextViewContentHeight == maxHeight && [textView.text hasSuffix:@"\n"]) {
449+
double delayInSeconds = 0.01;
450+
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
451+
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
452+
CGPoint bottomOffset = CGPointMake(0.0f, textView.contentSize.height - textView.bounds.size.height);
453+
[textView setContentOffset:bottomOffset animated:YES];
454+
});
467455
}
468456

469457
self.messageInputView.sendButton.enabled = ([textView.text js_stringByTrimingWhitespace].length > 0);
470458
}
471459

460+
#pragma mark - KVO observer method
461+
462+
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
463+
UITextView *textView = (UITextView *)object;
464+
if ([textView isKindOfClass:[UITextView class]] && [keyPath isEqualToString:@"contentSize"]) {
465+
[self refreshViewFrames:textView];
466+
}
467+
}
468+
469+
472470
#pragma mark - Keyboard notifications
473471

474472
- (void)handleWillShowKeyboardNotification:(NSNotification *)notification

0 commit comments

Comments
 (0)