Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Adapting code to work with an array of text fields

  • Loading branch information...
commit b8a704e6a29d60b571d4f4ee6e036ff7cc6cb752 1 parent bd682a6
@hellhound hellhound authored
Showing with 494 additions and 415 deletions.
  1. +29 −2 TSAlertView/TSAlertView.h
  2. +465 −413 TSAlertView/TSAlertView.m
View
31 TSAlertView/TSAlertView.h
@@ -57,7 +57,6 @@ didDismissWithButtonIndex:(NSInteger)buttonIndex;
UILabel *_messageLabel;
UITextView *_messageTextView;
UIImageView *_messageTextViewMaskImageView;
- UITextField *_inputTextField;
NSMutableArray *_buttons;
NSInteger _cancelButtonIndex;
TSAlertViewButtonLayout _buttonLayout;
@@ -66,11 +65,15 @@ didDismissWithButtonIndex:(NSInteger)buttonIndex;
CGFloat _maxHeight;
BOOL _usesMessageTextView;
TSAlertViewStyle _style;
+ // TSAlertView (TSCustomizableAlertView)
+ NSMutableArray *_textFields;
+ BOOL overrodeHeight;
+ CGFloat textFieldHeightoffset;
}
@property(nonatomic, copy) NSString *title;
@property(nonatomic, copy) NSString *message;
@property(nonatomic, assign) id<TSAlertViewDelegate> delegate;
-@property(nonatomic) NSInteger cancelButtonIndex;
+@property(nonatomic, assign) NSInteger cancelButtonIndex;
@property(nonatomic, readonly) NSInteger firstOtherButtonIndex;
@property(nonatomic, readonly) NSInteger numberOfButtons;
@property(nonatomic, readonly, getter=isVisible) BOOL visible;
@@ -94,3 +97,27 @@ didDismissWithButtonIndex:(NSInteger)buttonIndex;
animated:(BOOL)animated;
- (void)show;
@end
+
+@interface TSAlertView (TSCustomizableAlertView)
+
+// Returns the number of text fields added to the current instance
+@property (nonatomic, readonly) NSInteger numberOfTextFields;
+// Returns the first text field, identical to the message textFieldForIndex:
+// with 0 as it argument, with the exception that firstTextField will return nil
+// if there aren't any text fields, whereas textFieldForIndex: will throw an
+// exception
+@property (nonatomic, readonly) UITextField *firstTextField;
+
+// Allows you to add a UITextField directly, without having TSAlertView to
+// create it for you
+- (void)addTextField:(UITextField *)textField;
+// Creates and adds a UITextField, setting the placeholder value to the label
+// parameter
+- (UITextField *)addTextFieldWithLabel:(NSString *)label;
+// Creates and adds a UITextField, setting the placeholder value to the label
+// parameter, and the text value to the value parameter
+- (UITextField *)addTextFieldWithLabel:(NSString *)label
+ value:(NSString *)value;
+// Returns the UITextField instance at the specified index. Note: this method
+- (UITextField *)textFieldAtIndex:(NSInteger)index;
+@end
View
878 TSAlertView/TSAlertView.m
@@ -9,6 +9,12 @@
#import "TSAlertView.h"
+const CGFloat kTSAlertView_LeftMargin = 10.;
+const CGFloat kTSAlertView_TopMargin = 16.;
+const CGFloat kTSAlertView_BottomMargin = 15.;
+const CGFloat kTSAlertView_RowMargin = 5.;
+const CGFloat kTSAlertView_ColumnMargin = 10.;
+
@interface TSAlertOverlayWindow : UIWindow
{
UIWindow *_oldKeyWindow;
@@ -90,29 +96,6 @@ - (void)setRootController:(UIViewController *)controller
}
@end
-@interface TSAlertView (private)
-
-@property (nonatomic, readonly) NSMutableArray *buttons;
-@property (nonatomic, readonly) UILabel *titleLabel;
-@property (nonatomic, readonly) UILabel *messageLabel;
-@property (nonatomic, readonly) UITextView *messageTextView;
-- (void)TSAlertView_commonInit;
-- (void)releaseWindow:(int)buttonIndex;
-- (void)pulse;
-- (void)pulseDidStop1:(NSString *)animationID
- finished:(NSNumber *)finished
- context:(void *)context;
-- (void)pulseDidStop2:(NSString *)animationID
- finished:(NSNumber *)finished
- context:(void *)context;
-- (CGSize)titleLabelSize;
-- (CGSize)messageLabelSize;
-- (CGSize)inputTextFieldSize;
-- (CGSize)buttonsAreaSize_Stacked;
-- (CGSize)buttonsAreaSize_SideBySide;
-- (CGSize)recalcSizeAndLayout:(BOOL)layout;
-@end
-
@interface TSAlertViewController: UIViewController
@end
@@ -156,6 +139,53 @@ - (void)willAnimateRotationToInterfaceOrientation:
}
@end
+@interface UITextField (TSSize)
+
+- (CGSize)sizeForAlertView:(TSAlertView *)alertView;
+@end
+
+@implementation UITextField (TSSize)
+
+- (CGSize)sizeForAlertView:(TSAlertView *)alertView
+{
+ if ([alertView style] == TSAlertViewStyleNormal)
+ return CGSizeZero;
+
+ CGFloat maxWidth = [alertView width] - (kTSAlertView_LeftMargin * 2.);
+ CGSize size = [self sizeThatFits:CGSizeZero];
+
+ return CGSizeMake(maxWidth, size.height);
+}
+@end
+
+@interface TSAlertView (Private)
+
+@property (nonatomic, readonly) NSMutableArray *buttons;
+@property (nonatomic, readonly) UILabel *titleLabel;
+@property (nonatomic, readonly) UILabel *messageLabel;
+@property (nonatomic, readonly) UITextView *messageTextView;
+@property (nonatomic, readonly) UIImageView *messageTextViewMaskView;
+@property (nonatomic, readonly) NSMutableArray *textFields;
+- (void)TSAlertView_commonInit;
+- (void)releaseWindow:(int)buttonIndex;
+- (void)pulse;
+- (void)pulseDidStop1:(NSString *)animationID
+ finished:(NSNumber *)finished
+ context:(void *)context;
+- (void)pulseDidStop2:(NSString *)animationID
+ finished:(NSNumber *)finished
+ context:(void *)context;
+- (CGSize)titleLabelSize;
+- (CGSize)messageLabelSize;
+- (CGSize)inputTextFieldSize;
+- (CGSize)buttonsAreaSize_Stacked;
+- (CGSize)buttonsAreaSize_SideBySide;
+- (CGSize)recalcSizeAndLayout:(BOOL)layout;
+- (void)onKeyboardWillShow:(NSNotification *)note;
+- (void)onKeyboardWillHide:(NSNotification *)note;
+- (void)onButtonPress:(id)sender;
+@end
+
@implementation TSAlertView
@synthesize delegate = _delegate;
@@ -168,11 +198,8 @@ @implementation TSAlertView
@synthesize usesMessageTextView = _usesMessageTextView;
@synthesize style = _style;
-const CGFloat kTSAlertView_LeftMargin = 10.;
-const CGFloat kTSAlertView_TopMargin = 16.;
-const CGFloat kTSAlertView_BottomMargin = 15.;
-const CGFloat kTSAlertView_RowMargin = 5.;
-const CGFloat kTSAlertView_ColumnMargin = 10.;
+#pragma mark -
+#pragma mark NSObject
- (id)init
{
@@ -181,6 +208,23 @@ - (id)init
return self;
}
+- (void)dealloc
+{
+ _delegate = nil;
+ [_backgroundImage release];
+ [_buttons release];
+ [_titleLabel release];
+ [_messageLabel release];
+ [_messageTextView release];
+ [_messageTextViewMaskImageView release];
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ NSLog(@"TSAlertView: TSAlertOverlayWindow dealloc");
+ [super dealloc];
+}
+
+#pragma mark -
+#pragma mark UIView
+
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame]) != nil) {
@@ -194,40 +238,6 @@ - (id)initWithFrame:(CGRect)frame
return self;
}
-- (id)initWithTitle:(NSString *)title
- message:(NSString *)message
- delegate:(id)delegate
- cancelButtonTitle:(NSString *)cancelButtonTitle
- otherButtonTitles:(NSString *)otherButtonTitles, ...
-{
- // Will call into initWithFrame, thus TSAlertView_commonInit is called
- if ((self = [super init]) != nil) {
- [self setTitle:title];
- [self setMessage:message];
- [self setDelegate:delegate];
- if (nil != cancelButtonTitle) {
- [self addButtonWithTitle:cancelButtonTitle];
- [self setCancelButtonIndex:.0];
- }
-
- if (nil != otherButtonTitles) {
- _firstOtherButtonIndex = [self.buttons count];
- [self addButtonWithTitle: otherButtonTitles];
-
- va_list args;
- va_start(args, otherButtonTitles);
- id arg;
-
- while (nil != (arg = va_arg(args, id))) {
- if (![arg isKindOfClass:[NSString class]])
- return nil;
- [self addButtonWithTitle:(NSString*)arg];
- }
- }
- }
- return self;
-}
-
- (CGSize)sizeThatFits:(CGSize)unused
{
CGSize size = [self recalcSizeAndLayout:NO];
@@ -245,123 +255,8 @@ - (void)drawRect:(CGRect)rect
[[self backgroundImage] drawInRect: rect];
}
-- (void)dealloc
-{
- _delegate = nil;
- [_backgroundImage release];
- [_buttons release];
- [_titleLabel release];
- [_messageLabel release];
- [_messageTextView release];
- [_messageTextViewMaskImageView release];
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- NSLog(@"TSAlertView: TSAlertOverlayWindow dealloc");
- [super dealloc];
-}
-
-- (void)TSAlertView_commonInit
-{
- [self setBackgroundColor:[UIColor clearColor]];
- [self setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin |
- UIViewAutoresizingFlexibleRightMargin |
- UIViewAutoresizingFlexibleTopMargin |
- UIViewAutoresizingFlexibleBottomMargin];
- // defaults:
- _style = TSAlertViewStyleNormal;
- [self setWidth:.0]; // set to default
- [self setMaxHeight:.0]; // set to default
- _buttonLayout = TSAlertViewButtonLayoutNormal;
- _cancelButtonIndex = -1;
- _firstOtherButtonIndex = -1;
-}
-
-- (void)setWidth:(CGFloat)width
-{
- if (_width <= 0)
- _width = 284;
- _width = MAX(width, [[self backgroundImage] size].width);
-}
-
-- (CGFloat)width
-{
- if (nil == [self superview])
- return _width;
-
- CGFloat maxWidth = [[self superview] bounds].size.width - 20;
-
- return MIN(_width, maxWidth);
-}
-
-- (void)setMaxHeight:(CGFloat)height
-{
- if (height <= 0)
- height = 358;
- _maxHeight = MAX(height, [[self backgroundImage] size].height);
-}
-
-- (CGFloat)maxHeight
-{
- if (nil == [self superview])
- return _maxHeight;
- return MIN(_maxHeight, [[self superview] bounds].size.height - 20);
-}
-
-- (void)setStyle:(TSAlertViewStyle)style
-{
- if (_style != style) {
- _style = style;
- if (style == TSAlertViewStyleInput) {
- // need to watch for keyboard
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(onKeyboardWillShow:)
- name:UIKeyboardWillShowNotification object:nil];
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(onKeyboardWillHide:)
- name:UIKeyboardWillHideNotification object:nil];
- }
- }
-}
-
-- (void)onKeyboardWillShow:(NSNotification *)note
-{
- NSValue *boundsValue =
- [[note userInfo] objectForKey:UIKeyboardBoundsUserInfoKey];
- NSValue *centerValue =
- [[note userInfo] objectForKey:UIKeyboardCenterEndUserInfoKey];
- CGPoint kbCenter = [[self superview] convertPoint:[centerValue CGPointValue]
- fromView:nil];
- CGRect kbBounds = [boundsValue CGRectValue];
- CGRect kbFrame = CGRectOffset(kbBounds,
- kbCenter.x - kbBounds.size.width / 2.,
- kbCenter.y - kbBounds.size.height / 2.);
-
- if (CGRectIntersectsRect([self frame], kbFrame)) {
- CGPoint c = [self center];
-
- if ([self frame].size.height > kbFrame.origin.y - 20.) {
- [self setMaxHeight:kbFrame.origin.y - 20.];
- [self sizeToFit];
- [self layoutSubviews];
- }
- c.y = kbFrame.origin.y / 2.;
- [UIView beginAnimations:nil context:NULL];
- [UIView setAnimationDuration:.2];
- [self setCenter:c];
- [self setFrame:CGRectIntegral(self.frame)];
- [UIView commitAnimations];
- }
-}
-
-- (void)onKeyboardWillHide:(NSNotification *)note
-{
- [UIView beginAnimations:nil context:NULL];
- [UIView setAnimationDuration:.2];
- CGRect bounds = [[self superview] bounds];
-
- [self setCenter:CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds))];
- [self setFrame:CGRectIntegral([self frame])];
- [UIView commitAnimations];
-}
+#pragma mark -
+#pragma mark TSAlertView (Private)
- (NSMutableArray *)buttons
{
@@ -433,31 +328,401 @@ - (UIImageView *)messageTextViewMaskView
return _messageTextViewMaskImageView;
}
-- (UITextField *)inputTextField
-{
- if (_inputTextField == nil) {
- _inputTextField = [[UITextField alloc] init];
- [_inputTextField setBorderStyle:UITextBorderStyleRoundedRect];
- }
- return _inputTextField;
-}
-
-- (UIImage *)backgroundImage
+- (NSMutableArray *)textFields
{
- if (_backgroundImage == nil) {
- [self setBackgroundImage:
- [[UIImage imageNamed: @"TSAlertViewBackground.png"]
- stretchableImageWithLeftCapWidth:15 topCapHeight:30]];
- }
- return _backgroundImage;
+ if (_textFields == nil)
+ [self inputTextField];
+ return _textFields;
}
-- (void)setTitle:(NSString *)title
+- (void)TSAlertView_commonInit
{
- [[self titleLabel] setText:title];
-}
-
-- (NSString*)title
+ [self setBackgroundColor:[UIColor clearColor]];
+ [self setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin |
+ UIViewAutoresizingFlexibleRightMargin |
+ UIViewAutoresizingFlexibleTopMargin |
+ UIViewAutoresizingFlexibleBottomMargin];
+ // defaults:
+ _style = TSAlertViewStyleNormal;
+ [self setWidth:.0]; // set to default
+ [self setMaxHeight:.0]; // set to default
+ _buttonLayout = TSAlertViewButtonLayoutNormal;
+ _cancelButtonIndex = -1;
+ _firstOtherButtonIndex = -1;
+}
+
+- (void)releaseWindow:(int)buttonIndex
+{
+ if ([[self delegate] respondsToSelector:
+ @selector(alertView:didDismissWithButtonIndex:)])
+ [[self delegate] alertView:self didDismissWithButtonIndex:buttonIndex];
+ // the one place we release the window we allocated in "show"
+ // this will propogate releases to us (TSAlertView), and our
+ // TSAlertViewController
+ [[self window] release];
+}
+
+// pulse animation thanks to:
+// http://delackner.com/blog/2009/12/mimicking-uialertviews-animated-transition
+- (void)pulse
+{
+ [self setTransform:CGAffineTransformMakeScale(.6, .6)];
+ [UIView beginAnimations:nil context:NULL];
+ [UIView setAnimationDuration:.2];
+ [UIView setAnimationDelegate:self];
+ [UIView setAnimationDidStopSelector:
+ @selector(pulseDidStop1:finished:context:)];
+ [self setTransform:CGAffineTransformMakeScale(1.1, 1.1)];
+ [UIView commitAnimations];
+}
+
+- (void)pulseDidStop1:(NSString *)animationID
+ finished:(NSNumber *)finished
+ context:(void *)context
+{
+ [UIView beginAnimations:nil context:NULL];
+ [UIView setAnimationDuration:1. / 15.];
+ [UIView setAnimationDelegate:self];
+ [UIView setAnimationDidStopSelector:
+ @selector(pulseDidStop2:finished:context:)];
+ [self setTransform:CGAffineTransformMakeScale(.9, .9)];
+ [UIView commitAnimations];
+}
+
+- (void)pulseDidStop2:(NSString *)animationID
+ finished:(NSNumber *)finished
+ context:(void *)context
+{
+ [UIView beginAnimations:nil context:NULL];
+ [UIView setAnimationDuration:1. / 7.5];
+ [self setTransform:CGAffineTransformIdentity];
+ [UIView commitAnimations];
+}
+
+- (CGSize)titleLabelSize
+{
+ CGFloat maxWidth = [self width] - (kTSAlertView_LeftMargin * 2.);
+ CGSize size =
+ [[[self titleLabel] text] sizeWithFont:[[self titleLabel] font]
+ constrainedToSize:CGSizeMake(maxWidth, 1000.)
+ lineBreakMode:[[self titleLabel] lineBreakMode]];
+
+ if (size.width < maxWidth)
+ size.width = maxWidth;
+ return size;
+}
+
+- (CGSize)messageLabelSize
+{
+ CGFloat maxWidth = self.width - (kTSAlertView_LeftMargin * 2.);
+ CGSize size =
+ [[[self messageLabel] text] sizeWithFont:[[self messageLabel] font]
+ constrainedToSize:CGSizeMake(maxWidth, 1000.)
+ lineBreakMode:[[self messageLabel] lineBreakMode]];
+
+ if (size.width < maxWidth)
+ size.width = maxWidth;
+ return size;
+}
+
+- (CGSize)inputTextFieldSize
+{
+ if ([self style] == TSAlertViewStyleNormal)
+ return CGSizeZero;
+
+ CGFloat maxWidth = [self width] - (kTSAlertView_LeftMargin * 2.);
+ CGFloat totalHeight = .0;
+
+ for (UITextField *textField in [self textFields])
+ totalHeight += [[self inputTextField] sizeThatFits:CGSizeZero].height +
+ kTSAlertView_RowMargin;
+ return CGSizeMake(maxWidth, totalHeight);
+}
+
+- (CGSize)buttonsAreaSize_Stacked
+{
+ CGFloat maxWidth = [self width] - (kTSAlertView_LeftMargin * 2.);
+ int buttonCount = [[self buttons] count];
+ CGSize bs = [[self.buttons objectAtIndex:0] sizeThatFits:CGSizeZero];
+
+ bs.width = maxWidth;
+ bs.height = (bs.height * buttonCount) +
+ kTSAlertView_RowMargin * (buttonCount - 1.);
+ return bs;
+}
+
+- (CGSize)buttonsAreaSize_SideBySide
+{
+ CGFloat maxWidth = self.width - (kTSAlertView_LeftMargin * 2.);
+ CGSize bs = [[self.buttons objectAtIndex:0] sizeThatFits:CGSizeZero];
+
+ bs.width = maxWidth;
+ return bs;
+}
+
+- (CGSize)recalcSizeAndLayout:(BOOL)layout
+{
+ BOOL stacked = !([self buttonLayout] == TSAlertViewButtonLayoutNormal &&
+ [[self buttons] count] == 2);
+ CGFloat maxWidth = [self width] - (kTSAlertView_LeftMargin * 2.);
+ CGSize titleLabelSize = [self titleLabelSize];
+ CGSize messageViewSize = [self messageLabelSize];
+ CGSize inputTextFieldSize = [self inputTextFieldSize];
+ CGSize buttonsAreaSize = stacked ? [self buttonsAreaSize_Stacked] :
+ [self buttonsAreaSize_SideBySide];
+ CGFloat inputRowHeight = [self style] == TSAlertViewStyleInput ?
+ inputTextFieldSize.height + kTSAlertView_RowMargin : .0;
+ CGFloat totalHeight = kTSAlertView_TopMargin + titleLabelSize.height +
+ kTSAlertView_RowMargin + messageViewSize.height + inputRowHeight +
+ kTSAlertView_RowMargin + buttonsAreaSize.height +
+ kTSAlertView_BottomMargin;
+
+ if (totalHeight > self.maxHeight) {
+ // too tall - we'll condense by using a textView (with scrolling) for
+ // the message
+ totalHeight -= messageViewSize.height;
+ //$$what if it's still too tall?
+ messageViewSize.height = [self maxHeight] - totalHeight;
+ totalHeight = [self maxHeight];
+ [self setUsesMessageTextView:YES];
+ }
+ if (layout) {
+ // title
+ CGFloat y = kTSAlertView_TopMargin;
+
+ if ([self title] != nil) {
+ [[self titleLabel] setFrame:CGRectMake(kTSAlertView_LeftMargin, y,
+ titleLabelSize.width, titleLabelSize.height)];
+ [self addSubview:[self titleLabel]];
+ y += titleLabelSize.height + kTSAlertView_RowMargin;
+ }
+ // message
+ if ([self message] != nil) {
+ if ([self usesMessageTextView]) {
+ [[self messageTextView] setFrame:
+ CGRectMake(kTSAlertView_LeftMargin, y,
+ messageViewSize.width, messageViewSize.height)];
+ [self addSubview:[self messageTextView]];
+ y += messageViewSize.height + kTSAlertView_RowMargin;
+
+ UIImageView *maskImageView = [self messageTextViewMaskView];
+
+ [maskImageView setFrame:[[self messageTextView] frame]];
+ [self addSubview:maskImageView];
+ } else {
+ [[self messageLabel] setFrame:
+ CGRectMake(kTSAlertView_LeftMargin, y,
+ messageViewSize.width, messageViewSize.height)];
+ [self addSubview:[self messageLabel]];
+ y += messageViewSize.height + kTSAlertView_RowMargin;
+ }
+ }
+ // input
+ if ([self style] == TSAlertViewStyleInput) {
+ for (UITextField *textField in [self textFields]) {
+ CGSize textFieldSize = [textField sizeForAlertView:self];
+
+ [textField setFrame:CGRectMake(kTSAlertView_LeftMargin, y,
+ textFieldSize.width,
+ textFieldSize.height)];
+ [self addSubview:textField];
+ y += textFieldSize.height + kTSAlertView_RowMargin;
+ }
+ }
+
+ // buttons
+ CGFloat buttonHeight =
+ [[[self buttons] objectAtIndex:0]
+ sizeThatFits:CGSizeZero].height;
+
+ if (stacked) {
+ CGFloat buttonWidth = maxWidth;
+
+ for (UIButton *b in [self buttons]) {
+ [b setFrame:CGRectMake(kTSAlertView_LeftMargin, y, buttonWidth,
+ buttonHeight)];
+ [self addSubview:b];
+ y += buttonHeight + kTSAlertView_RowMargin;
+ }
+ } else {
+ CGFloat buttonWidth = (maxWidth - kTSAlertView_ColumnMargin) / 2.;
+ CGFloat x = kTSAlertView_LeftMargin;
+
+ for (UIButton *b in [self buttons]) {
+ [b setFrame:CGRectMake(x, y, buttonWidth, buttonHeight)];
+ [self addSubview:b];
+ x += buttonWidth + kTSAlertView_ColumnMargin;
+ }
+ }
+ }
+ return CGSizeMake([self width], totalHeight);
+}
+
+- (void)onKeyboardWillShow:(NSNotification *)note
+{
+ NSValue *boundsValue =
+ [[note userInfo] objectForKey:UIKeyboardBoundsUserInfoKey];
+ NSValue *centerValue =
+ [[note userInfo] objectForKey:UIKeyboardCenterEndUserInfoKey];
+ CGPoint kbCenter = [[self superview] convertPoint:[centerValue CGPointValue]
+ fromView:nil];
+ CGRect kbBounds = [boundsValue CGRectValue];
+ CGRect kbFrame = CGRectOffset(kbBounds,
+ kbCenter.x - kbBounds.size.width / 2.,
+ kbCenter.y - kbBounds.size.height / 2.);
+
+ if (CGRectIntersectsRect([self frame], kbFrame)) {
+ CGPoint c = [self center];
+
+ if ([self frame].size.height > kbFrame.origin.y - 20.) {
+ [self setMaxHeight:kbFrame.origin.y - 20.];
+ [self sizeToFit];
+ [self layoutSubviews];
+ }
+ c.y = kbFrame.origin.y / 2.;
+ [UIView beginAnimations:nil context:NULL];
+ [UIView setAnimationDuration:.2];
+ [self setCenter:c];
+ [self setFrame:CGRectIntegral(self.frame)];
+ [UIView commitAnimations];
+ }
+}
+
+- (void)onKeyboardWillHide:(NSNotification *)note
+{
+ [UIView beginAnimations:nil context:NULL];
+ [UIView setAnimationDuration:.2];
+ CGRect bounds = [[self superview] bounds];
+
+ [self setCenter:CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds))];
+ [self setFrame:CGRectIntegral([self frame])];
+ [UIView commitAnimations];
+}
+
+- (void)onButtonPress:(id)sender
+{
+ int buttonIndex = [_buttons indexOfObjectIdenticalTo:sender];
+
+ if ([[self delegate] respondsToSelector:
+ @selector(alertView:clickedButtonAtIndex:)])
+ [[self delegate] alertView:self clickedButtonAtIndex:buttonIndex];
+ if (buttonIndex == [self cancelButtonIndex] &&
+ [[self delegate] respondsToSelector:@selector(alertViewCancel:)])
+ [[self delegate] alertViewCancel:self];
+ [self dismissWithClickedButtonIndex:buttonIndex animated:YES];
+}
+
+#pragma mark TSAlertView (Public)
+
+- (id)initWithTitle:(NSString *)title
+ message:(NSString *)message
+ delegate:(id)delegate
+ cancelButtonTitle:(NSString *)cancelButtonTitle
+ otherButtonTitles:(NSString *)otherButtonTitles, ...
+{
+ // Will call into initWithFrame, thus TSAlertView_commonInit is called
+ if ((self = [super init]) != nil) {
+ [self setTitle:title];
+ [self setMessage:message];
+ [self setDelegate:delegate];
+ if (nil != cancelButtonTitle) {
+ [self addButtonWithTitle:cancelButtonTitle];
+ [self setCancelButtonIndex:.0];
+ }
+
+ if (nil != otherButtonTitles) {
+ _firstOtherButtonIndex = [self.buttons count];
+ [self addButtonWithTitle: otherButtonTitles];
+
+ va_list args;
+ va_start(args, otherButtonTitles);
+ id arg;
+
+ while (nil != (arg = va_arg(args, id))) {
+ if (![arg isKindOfClass:[NSString class]])
+ return nil;
+ [self addButtonWithTitle:(NSString*)arg];
+ }
+ }
+ }
+ return self;
+}
+
+- (void)setWidth:(CGFloat)width
+{
+ if (_width <= 0)
+ _width = 284;
+ _width = MAX(width, [[self backgroundImage] size].width);
+}
+
+- (CGFloat)width
+{
+ if (nil == [self superview])
+ return _width;
+
+ CGFloat maxWidth = [[self superview] bounds].size.width - 20;
+
+ return MIN(_width, maxWidth);
+}
+
+- (void)setMaxHeight:(CGFloat)height
+{
+ if (height <= 0)
+ height = 358;
+ _maxHeight = MAX(height, [[self backgroundImage] size].height);
+}
+
+- (CGFloat)maxHeight
+{
+ if (nil == [self superview])
+ return _maxHeight;
+ return MIN(_maxHeight, [[self superview] bounds].size.height - 20);
+}
+
+- (void)setStyle:(TSAlertViewStyle)style
+{
+ if (_style != style) {
+ _style = style;
+ if (style == TSAlertViewStyleInput) {
+ // need to watch for keyboard
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(onKeyboardWillShow:)
+ name:UIKeyboardWillShowNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(onKeyboardWillHide:)
+ name:UIKeyboardWillHideNotification object:nil];
+ }
+ }
+}
+
+- (UITextField *)inputTextField
+{
+ if (_textFields == nil) {
+ UITextField *inputTextField = [[UITextField alloc] init];
+
+ [inputTextField setBorderStyle:UITextBorderStyleRoundedRect];
+ _textFields =
+ [[NSMutableArray alloc] initWithObjects:inputTextField, nil];
+ }
+ return [_textFields objectAtIndex:0];
+}
+
+- (UIImage *)backgroundImage
+{
+ if (_backgroundImage == nil) {
+ [self setBackgroundImage:
+ [[UIImage imageNamed: @"TSAlertViewBackground.png"]
+ stretchableImageWithLeftCapWidth:15 topCapHeight:30]];
+ }
+ return _backgroundImage;
+}
+
+- (void)setTitle:(NSString *)title
+{
+ [[self titleLabel] setText:title];
+}
+
+- (NSString*)title
{
return [[self titleLabel] text];
}
@@ -571,17 +836,6 @@ - (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex
}
}
-- (void)releaseWindow:(int)buttonIndex
-{
- if ([[self delegate] respondsToSelector:
- @selector(alertView:didDismissWithButtonIndex:)])
- [[self delegate] alertView:self didDismissWithButtonIndex:buttonIndex];
- // the one place we release the window we allocated in "show"
- // this will propogate releases to us (TSAlertView), and our
- // TSAlertViewController
- [[self window] release];
-}
-
- (void)show
{
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
@@ -621,206 +875,4 @@ - (void)show
[[self inputTextField] becomeFirstResponder];
}
}
-
-// pulse animation thanks to:
-// http://delackner.com/blog/2009/12/mimicking-uialertviews-animated-transition
-- (void)pulse
-{
- [self setTransform:CGAffineTransformMakeScale(.6, .6)];
- [UIView beginAnimations:nil context:NULL];
- [UIView setAnimationDuration:.2];
- [UIView setAnimationDelegate:self];
- [UIView setAnimationDidStopSelector:
- @selector(pulseDidStop1:finished:context:)];
- [self setTransform:CGAffineTransformMakeScale(1.1, 1.1)];
- [UIView commitAnimations];
-}
-
-- (void)pulseDidStop1:(NSString *)animationID
- finished:(NSNumber *)finished
- context:(void *)context
-{
- [UIView beginAnimations:nil context:NULL];
- [UIView setAnimationDuration:1. / 15.];
- [UIView setAnimationDelegate:self];
- [UIView setAnimationDidStopSelector:
- @selector(pulseDidStop2:finished:context:)];
- [self setTransform:CGAffineTransformMakeScale(.9, .9)];
- [UIView commitAnimations];
-}
-
-- (void)pulseDidStop2:(NSString *)animationID
- finished:(NSNumber *)finished
- context:(void *)context
-{
- [UIView beginAnimations:nil context:NULL];
- [UIView setAnimationDuration:1. / 7.5];
- [self setTransform:CGAffineTransformIdentity];
- [UIView commitAnimations];
-}
-
-- (void)onButtonPress:(id)sender
-{
- int buttonIndex = [_buttons indexOfObjectIdenticalTo: sender];
-
- if ([[self delegate] respondsToSelector:
- @selector(alertView:clickedButtonAtIndex:)])
- [[self delegate] alertView:self clickedButtonAtIndex:buttonIndex];
- if (buttonIndex == [self cancelButtonIndex] &&
- [[self delegate] respondsToSelector:@selector(alertViewCancel:)])
- [[self delegate] alertViewCancel:self];
- [self dismissWithClickedButtonIndex:buttonIndex animated:YES];
-}
-
-- (CGSize)recalcSizeAndLayout:(BOOL)layout
-{
- BOOL stacked = !([self buttonLayout] == TSAlertViewButtonLayoutNormal &&
- [[self buttons] count] == 2);
- CGFloat maxWidth = [self width] - (kTSAlertView_LeftMargin * 2.);
- CGSize titleLabelSize = [self titleLabelSize];
- CGSize messageViewSize = [self messageLabelSize];
- CGSize inputTextFieldSize = [self inputTextFieldSize];
- CGSize buttonsAreaSize = stacked ? [self buttonsAreaSize_Stacked] :
- [self buttonsAreaSize_SideBySide];
- CGFloat inputRowHeight = [self style] == TSAlertViewStyleInput ?
- inputTextFieldSize.height + kTSAlertView_RowMargin : .0;
- CGFloat totalHeight = kTSAlertView_TopMargin + titleLabelSize.height +
- kTSAlertView_RowMargin + messageViewSize.height + inputRowHeight +
- kTSAlertView_RowMargin + buttonsAreaSize.height +
- kTSAlertView_BottomMargin;
-
- if (totalHeight > self.maxHeight) {
- // too tall - we'll condense by using a textView (with scrolling) for
- // the message
- totalHeight -= messageViewSize.height;
- //$$what if it's still too tall?
- messageViewSize.height = [self maxHeight] - totalHeight;
- totalHeight = [self maxHeight];
- [self setUsesMessageTextView:YES];
- }
- if (layout) {
- // title
- CGFloat y = kTSAlertView_TopMargin;
-
- if ([self title] != nil) {
- [[self titleLabel] setFrame:CGRectMake(kTSAlertView_LeftMargin, y,
- titleLabelSize.width, titleLabelSize.height)];
- [self addSubview:[self titleLabel]];
- y += titleLabelSize.height + kTSAlertView_RowMargin;
- }
- // message
- if ([self message] != nil) {
- if ([self usesMessageTextView]) {
- [[self messageTextView] setFrame:
- CGRectMake(kTSAlertView_LeftMargin, y,
- messageViewSize.width, messageViewSize.height)];
- [self addSubview:[self messageTextView]];
- y += messageViewSize.height + kTSAlertView_RowMargin;
-
- UIImageView *maskImageView = [self messageTextViewMaskView];
-
- [maskImageView setFrame:[[self messageTextView] frame]];
- [self addSubview:maskImageView];
- } else {
- [[self messageLabel] setFrame:
- CGRectMake(kTSAlertView_LeftMargin, y,
- messageViewSize.width, messageViewSize.height)];
- [self addSubview:[self messageLabel]];
- y += messageViewSize.height + kTSAlertView_RowMargin;
- }
- }
- // input
- if ([self style] == TSAlertViewStyleInput) {
- [[self inputTextField] setFrame:
- CGRectMake(kTSAlertView_LeftMargin, y,
- inputTextFieldSize.width, inputTextFieldSize.height)];
- [self addSubview: self.inputTextField];
- y += inputTextFieldSize.height + kTSAlertView_RowMargin;
- }
-
- // buttons
- CGFloat buttonHeight =
- [[[self buttons] objectAtIndex:0]
- sizeThatFits:CGSizeZero].height;
-
- if (stacked) {
- CGFloat buttonWidth = maxWidth;
-
- for (UIButton *b in [self buttons]) {
- [b setFrame:CGRectMake(kTSAlertView_LeftMargin, y, buttonWidth,
- buttonHeight)];
- [self addSubview:b];
- y += buttonHeight + kTSAlertView_RowMargin;
- }
- } else {
- CGFloat buttonWidth = (maxWidth - kTSAlertView_ColumnMargin) / 2.;
- CGFloat x = kTSAlertView_LeftMargin;
-
- for (UIButton *b in [self buttons]) {
- [b setFrame:CGRectMake(x, y, buttonWidth, buttonHeight)];
- [self addSubview:b];
- x += buttonWidth + kTSAlertView_ColumnMargin;
- }
- }
- }
- return CGSizeMake([self width], totalHeight);
-}
-
-- (CGSize)titleLabelSize
-{
- CGFloat maxWidth = [self width] - (kTSAlertView_LeftMargin * 2.);
- CGSize size =
- [[[self titleLabel] text] sizeWithFont:[[self titleLabel] font]
- constrainedToSize:CGSizeMake(maxWidth, 1000.)
- lineBreakMode:[[self titleLabel] lineBreakMode]];
-
- if (size.width < maxWidth)
- size.width = maxWidth;
- return size;
-}
-
-- (CGSize)messageLabelSize
-{
- CGFloat maxWidth = self.width - (kTSAlertView_LeftMargin * 2.);
- CGSize size =
- [[[self messageLabel] text] sizeWithFont:[[self messageLabel] font]
- constrainedToSize:CGSizeMake(maxWidth, 1000.)
- lineBreakMode:[[self messageLabel] lineBreakMode]];
-
- if (size.width < maxWidth)
- size.width = maxWidth;
- return size;
-}
-
-- (CGSize)inputTextFieldSize
-{
- if ([self style] == TSAlertViewStyleNormal)
- return CGSizeZero;
-
- CGFloat maxWidth = [self width] - (kTSAlertView_LeftMargin * 2.);
- CGSize size = [[self inputTextField] sizeThatFits:CGSizeZero];
-
- return CGSizeMake(maxWidth, size.height);
-}
-
-- (CGSize)buttonsAreaSize_SideBySide
-{
- CGFloat maxWidth = self.width - (kTSAlertView_LeftMargin * 2.);
- CGSize bs = [[self.buttons objectAtIndex:0] sizeThatFits:CGSizeZero];
-
- bs.width = maxWidth;
- return bs;
-}
-
-- (CGSize)buttonsAreaSize_Stacked
-{
- CGFloat maxWidth = [self width] - (kTSAlertView_LeftMargin * 2.);
- int buttonCount = [[self buttons] count];
- CGSize bs = [[self.buttons objectAtIndex:0] sizeThatFits:CGSizeZero];
-
- bs.width = maxWidth;
- bs.height = (bs.height * buttonCount) +
- kTSAlertView_RowMargin * (buttonCount - 1.);
- return bs;
-}
@end
Please sign in to comment.
Something went wrong with that request. Please try again.