Skip to content

Commit

Permalink
Merge pull request hanspinckaers#4 from auibrian/master
Browse files Browse the repository at this point in the history
Pull for nib based implementations and ios4 animation styles
  • Loading branch information
hanspinckaers committed Sep 7, 2011
2 parents de30b5f + a6d6966 commit 48d27e7
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 77 deletions.
156 changes: 97 additions & 59 deletions class/HPGrowingTextView.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
#import "HPGrowingTextView.h"
#import "HPTextViewInternal.h"

@interface HPGrowingTextView(private)
-(void)commonInitialiser;
-(void)resizeTextView:(NSInteger)newSizeH;
-(void)growDidStop;
@end

@implementation HPGrowingTextView
@synthesize internalTextView;
Expand All @@ -42,35 +47,48 @@ @implementation HPGrowingTextView
@synthesize animateHeightChange;
@synthesize returnKeyType;

// having initwithcoder allows us to use HPGrowingTextView in a Nib. -- aob, 9/2011
- (id)initWithCoder:(NSCoder *)aDecoder
{
if ((self = [super initWithCoder:aDecoder])) {
[self commonInitialiser];
}
return self;
}

- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
// Initialization code
CGRect r = frame;
r.origin.y = 0;
r.origin.x = 0;
internalTextView = [[HPTextViewInternal alloc] initWithFrame:r];
internalTextView.delegate = self;
internalTextView.scrollEnabled = NO;
internalTextView.font = [UIFont fontWithName:@"Helvetica" size:13];
internalTextView.contentInset = UIEdgeInsetsZero;
internalTextView.showsHorizontalScrollIndicator = NO;
internalTextView.text = @"-";
[self addSubview:internalTextView];

UIView *internal = (UIView*)[[internalTextView subviews] objectAtIndex:0];
minHeight = internal.frame.size.height;
minNumberOfLines = 1;

animateHeightChange = YES;

internalTextView.text = @"";

[self setMaxNumberOfLines:3];
[self commonInitialiser];
}
return self;
}

-(void)commonInitialiser
{
// Initialization code
CGRect r = self.frame;
r.origin.y = 0;
r.origin.x = 0;
internalTextView = [[HPTextViewInternal alloc] initWithFrame:r];
internalTextView.delegate = self;
internalTextView.scrollEnabled = NO;
internalTextView.font = [UIFont fontWithName:@"Helvetica" size:13];
internalTextView.contentInset = UIEdgeInsetsZero;
internalTextView.showsHorizontalScrollIndicator = NO;
internalTextView.text = @"-";
[self addSubview:internalTextView];

UIView *internal = (UIView*)[[internalTextView subviews] objectAtIndex:0];
minHeight = internal.frame.size.height;
minNumberOfLines = 1;

animateHeightChange = YES;

internalTextView.text = @"";

[self setMaxNumberOfLines:3];
}

-(void)sizeToFit
{
CGRect r = self.frame;
Expand All @@ -91,7 +109,7 @@ -(void)setFrame:(CGRect)aframe
r.origin.y = 0;
r.origin.x = contentInset.left;
r.size.width -= contentInset.left + contentInset.right;

internalTextView.frame = r;

[super setFrame:aframe];
Expand Down Expand Up @@ -181,7 +199,7 @@ - (void)textViewDidChange:(UITextView *)textView
//size of content, so we can set the frame of self
NSInteger newSizeH = internalTextView.contentSize.height;
if(newSizeH < minHeight || !internalTextView.hasText) newSizeH = minHeight; //not smalles than minHeight
if (internalTextView.frame.size.height != newSizeH)
{
// [fixed] Pasting too much text into the view failed to fire the height change,
Expand All @@ -194,41 +212,44 @@ - (void)textViewDidChange:(UITextView *)textView

if (newSizeH <= maxHeight)
{
if(animateHeightChange){
[UIView beginAnimations:@"" context:nil];
[UIView setAnimationDuration:0.1f];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(growDidStop)];
[UIView setAnimationBeginsFromCurrentState:YES];
}

if ([delegate respondsToSelector:@selector(growingTextView:willChangeHeight:)]) {
[delegate growingTextView:self willChangeHeight:newSizeH];
}

// internalTextView
CGRect internalTextViewFrame = self.frame;
internalTextViewFrame.size.height = newSizeH; // + padding
self.frame = internalTextViewFrame;

internalTextViewFrame.origin.y = contentInset.top - contentInset.bottom;
internalTextViewFrame.origin.x = contentInset.left;
internalTextViewFrame.size.height = newSizeH;
internalTextViewFrame.size.width = internalTextView.contentSize.width;

internalTextView.frame = internalTextViewFrame;

// [fixed] The growingTextView:didChangeHeight: delegate method was not called at all when not animating height changes.
// thanks to Gwynne <http://blog.darkrainfall.org/>

if(animateHeightChange){
[UIView commitAnimations];
} else if ([delegate respondsToSelector:@selector(growingTextView:didChangeHeight:)]) {
[delegate growingTextView:self didChangeHeight:newSizeH];
}
if(animateHeightChange) {

if ([UIView resolveClassMethod:@selector(animateWithDuration:animations:)]) {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
[UIView animateWithDuration:0.1f
delay:0
options:(UIViewAnimationOptionAllowUserInteraction|
UIViewAnimationOptionBeginFromCurrentState)
animations:^(void) {
[self resizeTextView:newSizeH];
}
completion:^(BOOL finished) {
if ([delegate respondsToSelector:@selector(growingTextView:didChangeHeight:)]) {
[delegate growingTextView:self didChangeHeight:newSizeH];
}
}];
#endif
} else {
[UIView beginAnimations:@"" context:nil];
[UIView setAnimationDuration:0.1f];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(growDidStop)];
[UIView setAnimationBeginsFromCurrentState:YES];
[self resizeTextView:newSizeH];
[UIView commitAnimations];
}
} else {
[self resizeTextView:newSizeH];
// [fixed] The growingTextView:didChangeHeight: delegate method was not called at all when not animating height changes.
// thanks to Gwynne <http://blog.darkrainfall.org/>

if ([delegate respondsToSelector:@selector(growingTextView:didChangeHeight:)]) {
[delegate growingTextView:self didChangeHeight:newSizeH];
}
}
}

// if our new height is greater than the maxHeight
// sets not set the height or move things
// around and enable scrolling
Expand All @@ -252,6 +273,23 @@ - (void)textViewDidChange:(UITextView *)textView

}

-(void)resizeTextView:(NSInteger)newSizeH
{
if ([delegate respondsToSelector:@selector(growingTextView:willChangeHeight:)]) {
[delegate growingTextView:self willChangeHeight:newSizeH];
}

CGRect internalTextViewFrame = self.frame;
internalTextViewFrame.size.height = newSizeH; // + padding
self.frame = internalTextViewFrame;

internalTextViewFrame.origin.y = contentInset.top - contentInset.bottom;
internalTextViewFrame.origin.x = contentInset.left;
internalTextViewFrame.size.width = internalTextView.contentSize.width;

internalTextView.frame = internalTextViewFrame;
}

-(void)growDidStop
{
if ([delegate respondsToSelector:@selector(growingTextView:didChangeHeight:)]) {
Expand Down Expand Up @@ -444,7 +482,7 @@ - (void)textViewDidEndEditing:(UITextView *)textView {

///////////////////////////////////////////////////////////////////////////////////////////////////
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range
replacementText:(NSString *)atext {
replacementText:(NSString *)atext {

//weird 1 pixel bug when clicking backspace when textView is empty
if(![textView hasText] && [atext isEqualToString:@""]) return NO;
Expand All @@ -462,7 +500,7 @@ - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range

return YES;


}

///////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
43 changes: 25 additions & 18 deletions example/Classes/GrowingTextViewExampleViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ - (void)loadView {
imageView.frame = CGRectMake(0, 0, containerView.frame.size.width, containerView.frame.size.height);
imageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;

textView.autoresizingMask = UIViewAutoresizingFlexibleWidth;

// view hierachy
[containerView addSubview:imageView];
[containerView addSubview:textView];
Expand All @@ -95,7 +97,7 @@ - (void)loadView {

UIButton *doneBtn = [UIButton buttonWithType:UIButtonTypeCustom];
doneBtn.frame = CGRectMake(containerView.frame.size.width - 69, 8, 63, 27);
doneBtn.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
doneBtn.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin;
[doneBtn setTitle:@"Done" forState:UIControlStateNormal];

[doneBtn setTitleShadowColor:[UIColor colorWithWhite:0 alpha:0.4] forState:UIControlStateNormal];
Expand All @@ -106,7 +108,8 @@ - (void)loadView {
[doneBtn addTarget:self action:@selector(resignTextView) forControlEvents:UIControlEventTouchUpInside];
[doneBtn setBackgroundImage:sendBtnBackground forState:UIControlStateNormal];
[doneBtn setBackgroundImage:selectedSendBtnBackground forState:UIControlStateSelected];
[containerView addSubview:doneBtn];
[containerView addSubview:doneBtn];
containerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
}

-(void)resignTextView
Expand All @@ -119,18 +122,20 @@ -(void) keyboardWillShow:(NSNotification *)note{
// get keyboard size and loctaion
CGRect keyboardBounds;
[[note.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] getValue: &keyboardBounds];

// get the height since this is the main value that we need.
NSInteger kbSizeH = keyboardBounds.size.height;

NSNumber *duration = [note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
NSNumber *curve = [note.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey];

// Need to translate the bounds to account for rotation.
keyboardBounds = [self.view convertRect:keyboardBounds toView:nil];

// get a rect for the textView frame
CGRect containerFrame = containerView.frame;
containerFrame.origin.y -= kbSizeH;

containerFrame.origin.y = self.view.bounds.size.height - (keyboardBounds.size.height + containerFrame.size.height);
// animations settings
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.25f];
[UIView setAnimationDuration:[duration doubleValue]];
[UIView setAnimationCurve:[curve intValue]];

// set views with new info
containerView.frame = containerFrame;
Expand All @@ -140,22 +145,19 @@ -(void) keyboardWillShow:(NSNotification *)note{
}

-(void) keyboardWillHide:(NSNotification *)note{
// get keyboard size and location
CGRect keyboardBounds;
[[note.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] getValue: &keyboardBounds];

// get the height since this is the main value that we need.
NSInteger kbSizeH = keyboardBounds.size.height;
NSNumber *duration = [note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
NSNumber *curve = [note.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey];

// get a rect for the textView frame
CGRect containerFrame = containerView.frame;
containerFrame.origin.y += kbSizeH;
containerFrame.origin.y = self.view.bounds.size.height - containerFrame.size.height;

// animations settings
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.25f];

[UIView setAnimationDuration:[duration doubleValue]];
[UIView setAnimationCurve:[curve intValue]];

// set views with new info
containerView.frame = containerFrame;

Expand All @@ -173,6 +175,11 @@ - (void)growingTextView:(HPGrowingTextView *)growingTextView willChangeHeight:(f
containerView.frame = r;
}

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return YES;
}

- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
Expand Down

0 comments on commit 48d27e7

Please sign in to comment.