diff --git a/SIAlertView/SIAlertView.h b/SIAlertView/SIAlertView.h index 1062f68..d0a93bb 100644 --- a/SIAlertView/SIAlertView.h +++ b/SIAlertView/SIAlertView.h @@ -32,6 +32,11 @@ typedef NS_ENUM(NSInteger, SIAlertViewTransitionStyle) { SIAlertViewTransitionStyleDropDown }; +typedef NS_ENUM(NSInteger, SIAlertViewStyle) { + SIAlertViewStyleDefault = 0, + SIAlertViewStylePlainTextInput +}; + @class SIAlertView; typedef void(^SIAlertViewHandler)(SIAlertView *alertView); @@ -39,7 +44,9 @@ typedef void(^SIAlertViewHandler)(SIAlertView *alertView); @property (nonatomic, copy) NSString *title; @property (nonatomic, copy) NSString *message; +@property (nonatomic, copy, readonly) NSString *inputText; +@property (nonatomic, assign) SIAlertViewStyle alertViewStyle; // default is SIAlertViewStyleDefault @property (nonatomic, assign) SIAlertViewTransitionStyle transitionStyle; // default is SIAlertViewTransitionStyleSlideFromBottom @property (nonatomic, assign) SIAlertViewBackgroundStyle backgroundStyle; // default is SIAlertViewButtonTypeGradient diff --git a/SIAlertView/SIAlertView.m b/SIAlertView/SIAlertView.m index e9237e3..97a19e4 100644 --- a/SIAlertView/SIAlertView.m +++ b/SIAlertView/SIAlertView.m @@ -24,6 +24,7 @@ #define CONTENT_PADDING_TOP 12 #define CONTENT_PADDING_BOTTOM 10 #define BUTTON_HEIGHT 44 +#define TEXTFIELD_HEIGHT 28 #define CONTAINER_WIDTH 300 const UIWindowLevel UIWindowLevelSIAlert = 1999.0; // don't overlap system's alert @@ -44,9 +45,12 @@ @interface SIAlertView () @property (nonatomic, strong) UILabel *titleLabel; @property (nonatomic, strong) UILabel *messageLabel; +@property (nonatomic, strong) UITextField *textField; @property (nonatomic, strong) UIView *containerView; @property (nonatomic, strong) NSMutableArray *buttons; +@property (nonatomic, assign) CGFloat keyboardOffset; + @property (nonatomic, assign, getter = isLayoutDirty) BOOL layoutDirty; + (NSMutableArray *)sharedQueue; @@ -167,6 +171,9 @@ - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrie #pragma mark - SIAlert +@interface SIAlertView() +@end + @implementation SIAlertView + (void)initialize @@ -262,6 +269,12 @@ + (void)hideBackgroundAnimated:(BOOL)animated }]; } +#pragma mark - Getters + +- (NSString *)inputText { + return self.textField ? self.textField.text : @""; +} + #pragma mark - Setters - (void)setTitle:(NSString *)title @@ -346,6 +359,8 @@ - (void)show NSInteger index = [[SIAlertView sharedQueue] indexOfObject:self]; if (index < [SIAlertView sharedQueue].count - 1) { [self dismissAnimated:YES cleanup:NO]; // dismiss to show next alert view + } else if(self.textField) { + [self.textField becomeFirstResponder]; } }]; } @@ -363,6 +378,13 @@ - (void)dismissAnimated:(BOOL)animated cleanup:(BOOL)cleanup if (self.willDismissHandler) { self.willDismissHandler(self); } + + if(self.textField) { + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; + [self.textField resignFirstResponder]; + } + [[NSNotificationCenter defaultCenter] postNotificationName:SIAlertViewWillDismissNotification object:self userInfo:nil]; } @@ -625,9 +647,10 @@ - (void)validateLayout NSLog(@"%@, %@", self, NSStringFromSelector(_cmd)); #endif + CGFloat availableHeight = self.bounds.size.height - self.keyboardOffset; CGFloat height = [self preferredHeight]; CGFloat left = (self.bounds.size.width - CONTAINER_WIDTH) * 0.5; - CGFloat top = (self.bounds.size.height - height) * 0.5; + CGFloat top = (availableHeight - height) * 0.5; self.containerView.transform = CGAffineTransformIdentity; self.containerView.frame = CGRectMake(left, top, CONTAINER_WIDTH, height); self.containerView.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:self.containerView.bounds cornerRadius:self.containerView.layer.cornerRadius].CGPath; @@ -648,6 +671,15 @@ - (void)validateLayout self.messageLabel.frame = CGRectMake(CONTENT_PADDING_LEFT, y, self.containerView.bounds.size.width - CONTENT_PADDING_LEFT * 2, height); y += height; } + if(self.textField) { + if (y > CONTENT_PADDING_TOP) { + y += GAP; + } + CGFloat height = TEXTFIELD_HEIGHT; + self.textField.frame = CGRectMake(CONTENT_PADDING_LEFT, y, self.containerView.bounds.size.width - CONTENT_PADDING_LEFT * 2, height); + y += height; + + } if (self.items.count > 0) { if (y > CONTENT_PADDING_TOP) { y += GAP; @@ -687,6 +719,12 @@ - (CGFloat)preferredHeight } height += [self heightForMessageLabel]; } + if (self.textField) { + if (height > CONTENT_PADDING_TOP) { + height += GAP; + } + height += TEXTFIELD_HEIGHT; + } if (self.items.count > 0) { if (height > CONTENT_PADDING_TOP) { height += GAP; @@ -742,6 +780,9 @@ - (void)setup [self setupContainerView]; [self updateTitleLabel]; [self updateMessageLabel]; + if(self.alertViewStyle == SIAlertViewStylePlainTextInput) { + [self setupTextField]; + } [self setupButtons]; [self invaliadateLayout]; } @@ -819,6 +860,23 @@ - (void)updateMessageLabel [self invaliadateLayout]; } +- (void)setupTextField +{ + if(!self.textField) { + self.textField = [[UITextField alloc] initWithFrame:self.bounds]; + self.textField.delegate = self; + self.textField.text = @""; + self.textField.borderStyle = UITextBorderStyleBezel; + [self.containerView addSubview:self.textField]; +#if DEBUG_LAYOUT + self.textField.backgroundColor = [UIColor redColor]; +#endif + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShowNotification:) name:UIKeyboardWillShowNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHideNotification:) name:UIKeyboardWillHideNotification object:nil]; + } + [self invaliadateLayout]; +} + - (void)setupButtons { self.buttons = [[NSMutableArray alloc] initWithCapacity:self.items.count]; @@ -894,6 +952,55 @@ - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag } } +#pragma mark - UITextField delegate + +- (BOOL)textFieldShouldReturn:(UITextField *)textField { + [textField resignFirstResponder]; + return YES; +} + +#pragma mark - Keyboard notification handlers + +-(void)keyboardWillShowNotification:(NSNotification *)notification { + [self moveAlertForKeyboard:notification up:YES]; +} +-(void)keyboardWillHideNotification:(NSNotification *)notification { + [self moveAlertForKeyboard:notification up:NO]; +} + +- (void)moveAlertForKeyboard:(NSNotification*)notification up:(BOOL)up { + NSDictionary* userInfo = [notification userInfo]; + NSTimeInterval animationDuration; + UIViewAnimationCurve animationCurve; + CGRect keyboardEndFrame; + + [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve]; + [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration]; + [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame]; + + //calculate new position + CGRect containerFrame = self.containerView.frame; + CGRect convertedKeyboardFrame = [self convertRect:keyboardEndFrame fromView:self.window]; + CGFloat adjustedHeight = self.bounds.size.height; + if(up) { + adjustedHeight -= convertedKeyboardFrame.size.height; + } + containerFrame.origin.y = (adjustedHeight - containerFrame.size.height) / 2; + + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:animationDuration]; + [UIView setAnimationCurve:animationCurve]; + self.containerView.frame = containerFrame; + [UIView commitAnimations]; + + //keyboardOffset is used to adjust the alertView y position on willRotate, i.e. before the rotation occurs. Therefore the height is set dependent of the current orientation + if(up) { + self.keyboardOffset = UIInterfaceOrientationIsPortrait([[UIDevice currentDevice] orientation]) ? keyboardEndFrame.size.height : keyboardEndFrame.size.width; + } else { + self.keyboardOffset = 0; + } +} + #pragma mark - UIAppearance setters - (void)setViewBackgroundColor:(UIColor *)viewBackgroundColor diff --git a/SIAlertViewExample/SIAlertViewExample/ViewController.m b/SIAlertViewExample/SIAlertViewExample/ViewController.m index 449d258..c238b5c 100644 --- a/SIAlertViewExample/SIAlertViewExample/ViewController.m +++ b/SIAlertViewExample/SIAlertViewExample/ViewController.m @@ -135,6 +135,7 @@ - (IBAction)alert2:(id)sender - (IBAction)alert3:(id)sender { SIAlertView *alertView = [[SIAlertView alloc] initWithTitle:nil andMessage:@"Message3"]; + alertView.alertViewStyle = SIAlertViewStylePlainTextInput; [alertView addButtonWithTitle:@"Cancel" type:SIAlertViewButtonTypeCancel handler:^(SIAlertView *alertView) { @@ -144,6 +145,7 @@ - (IBAction)alert3:(id)sender type:SIAlertViewButtonTypeDefault handler:^(SIAlertView *alertView) { NSLog(@"OK Clicked"); + NSLog(@"Textinput: %@", alertView.inputText); }]; alertView.transitionStyle = SIAlertViewTransitionStyleDropDown; alertView.backgroundStyle = SIAlertViewBackgroundStyleSolid;