Skip to content

Commit

Permalink
Simplified scroll view implementation; automatically calculate correc…
Browse files Browse the repository at this point in the history
…t content inset when not set
  • Loading branch information
michaeltyson committed Jul 10, 2013
1 parent 1ad420e commit f336ae2
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 39 deletions.
7 changes: 0 additions & 7 deletions TPKeyboardAvoidingSample/FirstViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,6 @@ @implementation FirstViewController
- (void)viewDidLoad
{
[super viewDidLoad];

// Calculate content size given contents
CGRect contentRect = CGRectZero;
for ( UIView *subview in self.scrollView.subviews ) {
contentRect = CGRectUnion(contentRect, subview.frame);
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.bounds.size.width, CGRectGetMaxY(contentRect)+10);
}


Expand Down
1 change: 0 additions & 1 deletion TPKeyboardAvoidingScrollView.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#import <UIKit/UIKit.h>

@interface TPKeyboardAvoidingScrollView : UIScrollView
@property (assign, nonatomic) BOOL autoAdjustsContentSizeToBounds;
- (BOOL)focusNextTextField;
- (void)scrollToActiveTextField;
@end
63 changes: 32 additions & 31 deletions TPKeyboardAvoidingScrollView.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@

#define _UIKeyboardFrameEndUserInfoKey (&UIKeyboardFrameEndUserInfoKey != NULL ? UIKeyboardFrameEndUserInfoKey : @"UIKeyboardBoundsUserInfoKey")

const CGFloat kCalculatedContentPadding = 10;

@interface TPKeyboardAvoidingScrollView () <UITextFieldDelegate, UITextViewDelegate> {
UIEdgeInsets _priorInset;
BOOL _priorInsetSaved;
BOOL _keyboardVisible;
CGRect _keyboardRect;
CGSize _originalContentSize;
CGSize _contentsSize;
CGSize _priorContentSize;
}
- (UIView*)findFirstResponderBeneathView:(UIView*)view;
- (UIEdgeInsets)contentInsetForKeyboard;
Expand All @@ -27,10 +29,6 @@ @implementation TPKeyboardAvoidingScrollView
#pragma mark - Setup/Teardown

- (void)setup {
_priorInsetSaved = NO;
if ( CGSizeEqualToSize(self.contentSize, CGSizeZero) ) {
self.contentSize = self.bounds.size;
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
Expand All @@ -54,20 +52,20 @@ -(void)dealloc {

-(void)setFrame:(CGRect)frame {
[super setFrame:frame];

[self handleContentSize];
if ( _keyboardVisible ) {
self.contentInset = [self contentInsetForKeyboard];
}
}

-(void)setContentSize:(CGSize)contentSize {
_originalContentSize = contentSize;

[self handleContentSize];
[super setContentSize:contentSize];
if ( _keyboardVisible ) {
self.contentInset = [self contentInsetForKeyboard];
}
}

-(void)setAutoAdjustsContentSizeToBounds:(BOOL)autoAdjustsContentSizeToBounds {
_autoAdjustsContentSizeToBounds = autoAdjustsContentSizeToBounds;

[self handleContentSize];
-(void)didAddSubview:(UIView *)subview {
_contentsSize = [self contentsSizeFromSubviewFrames];
}

#pragma mark - Responders, events
Expand All @@ -78,6 +76,11 @@ - (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
}

- (void)keyboardWillShow:(NSNotification*)notification {
if ( CGSizeEqualToSize(self.contentSize, CGSizeZero) ) {
// Set the content size, if it's not set
self.contentSize = CGSizeMake(_contentsSize.width + kCalculatedContentPadding, _contentsSize.height + kCalculatedContentPadding);
}

_keyboardRect = [[[notification userInfo] objectForKey:_UIKeyboardFrameEndUserInfoKey] CGRectValue];
_keyboardVisible = YES;

Expand All @@ -87,17 +90,18 @@ - (void)keyboardWillShow:(NSNotification*)notification {
return;
}

if (!_priorInsetSaved) {
_priorInset = self.contentInset;
_priorInsetSaved = YES;
}
_priorInset = self.contentInset;
_priorContentSize = self.contentSize;

// Shrink view's inset by the keyboard's height, and scroll to show the text field/view being edited
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:[[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
[UIView setAnimationDuration:[[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]];



self.contentInset = [self contentInsetForKeyboard];

[self setContentOffset:CGPointMake(self.contentOffset.x,
[self idealOffsetForView:firstResponder withSpace:[self keyboardRect].origin.y - self.bounds.origin.y])
animated:YES];
Expand All @@ -114,9 +118,9 @@ - (void)keyboardWillHide:(NSNotification*)notification {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:[[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
[UIView setAnimationDuration:[[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]];
self.contentSize = _priorContentSize;
self.contentInset = _priorInset;
[self setScrollIndicatorInsets:self.contentInset];
_priorInsetSaved = NO;
[UIView commitAnimations];
}

Expand Down Expand Up @@ -172,17 +176,6 @@ -(void)scrollToActiveTextField {

#pragma mark - Helpers

-(void)handleContentSize {
CGSize contentSize = _autoAdjustsContentSizeToBounds ? self.bounds.size : _originalContentSize;
contentSize.width = MAX(contentSize.width, self.frame.size.width);
contentSize.height = MAX(contentSize.height, self.frame.size.height);
[super setContentSize:contentSize];

if ( _keyboardVisible ) {
self.contentInset = [self contentInsetForKeyboard];
}
}

- (UIView*)findFirstResponderBeneathView:(UIView*)view {
// Search recursively for first responder
for ( UIView *childView in view.subviews ) {
Expand Down Expand Up @@ -220,6 +213,14 @@ - (void)initializeViewsBeneathView:(UIView*)view {
}
}

-(CGSize)contentsSizeFromSubviewFrames {
CGRect rect = CGRectZero;
for ( UIView *view in self.subviews ) {
rect = CGRectUnion(rect, view.frame);
}
return rect.size;
}

- (UIEdgeInsets)contentInsetForKeyboard {
UIEdgeInsets newInset = self.contentInset;
CGRect keyboardRect = [self keyboardRect];
Expand Down

0 comments on commit f336ae2

Please sign in to comment.