Add TextField or other control to UIActionSheet or UIAlertView

Anyone know how to derived UIActionSheet or UIAlertView and add additional UIControl (e.g. TextField ...) to the dialog. It is nice to have example how to do it. I try but still not show the TextField in modal dialog.

Please help.

Thanks

iPhone, Other OS, iphone development

Posted on Aug 21, 2008 8:09 AM

Reply
24 replies

Oct 4, 2008 10:50 AM in response to SexyAndOhSoWitty

I'm experiencing the same issue when trying to add a UIPickerView to a UIActionSheet : the layout is very strange... 😟
I didn't have the same problem when adding a UIActivityIndicatorView to a UIActionSheet so I'm wondering if this is related to the UIPickerView itself...
Actually I'm trying to get the kind of UI you can see in Twinkle when you want to set the search radius : a UIActionSheet appears with a label (the title of the action sheet), a UIPickerView and an "OK" button.
I'm wondering : did they reimplement it from scratch from UIView + the transition or is there a correct way to use the UIPickerView + UIActionSheet to achieve this ?
Thx.

Oct 4, 2008 12:45 PM in response to mazzilli

A solution is described here for the AlertView. I suppose the same could be applied to the ActionSheet but this sounds more like a workaround (put a message to get some space in the AlertView that will be covered later on by the text field.....) than an academic and recommanded way to get it achieved....
http://www.iphonedevsdk.com/forum/iphone-sdk-development/1704-uitextfield-inside -uialertview.html

Oct 4, 2008 12:47 PM in response to interman

Another tip: you can loop through the subviews array and do some interesting stuff.

UIActionSheet *actionSheet;
// allocate, init, etc.
// loop through each subview
for (id subview in actionSheet.subviews) {
// write to the log what the subview is
NSLog(@"Subview is a %@", [subview description]);
// hide all buttons
if ([subview isKindOfClass:[UIButton class]])
subview.hidden = YES;
}

Disclaimer: haven't tested this code

Oct 4, 2008 1:24 PM in response to msv123

I got it 😀
I was trying the same approach as you ("generate some space and then hide it") but differently : with some carriage return in the title :
UIActionSheet* settings = [[UIActionSheet alloc] initWithTitle:@"myTitle:\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
delegate:nil cancelButtonTitle:@"ok" destructiveButtonTitle:nil
otherButtonTitles:nil];
I do it with Interface builder so I cannot really put the whole code but here's the approach :
In IB : create a View (let's call it theView), add your components in it (in my case a UIPickerView).
Set the background of theView to transparent (opacity=0)
Then, after instantiating your UIActionSheet, add this subview to it, but as the first child of the subviews by doing :
[settings insertSubview:theView atIndex:0];
I get the following result :
http://u1.ipernity.com/9/94/93/3119493.64a61467.l.jpg

Nov 12, 2008 6:10 AM in response to interman

Hi,
I subclassed UIAlertView and added a UITextField. Please find the files according class interface and implementation below.
To use and call the TextAlertView use the following code:


TextAlertView *alert = [[TextAlertView alloc] initWithTitle:@"Some Title"
message:@"Some Message - also multiline or nil"
delegate:self cancelButtonTitle:@"Cancel"
otherButtonTitles:@"OK", nil];
alert.textField.keyboardType = UIKeyboardTypeNumberPad;
// tag the alert in case you have multiple alert sheet calls
alert.tag = 1;
[alert show];
[alert release];


You just need to define the following UIAlertSheet delegate to handle the pressed button and edited text:

/*
* UIAlertView/TextAlertView delegate method(s)
*/
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
TextAlertView *alertView = (TextAlertView*) actionSheet;
if(buttonIndex > 0) {
if(alertView.tag == 1) {
NSString *textValue = alertView.textField.text;
if(textValue==nil)
return;
// do something meaningful with textValue
}
}
}


TextAlertView.h


/*
* Text Alert View
*
* File: TextAlertView.h
* Abstract: UIAlertView extension with UITextField (Interface Declaration).
*
*/
#import <UIKit/UIKit.h>
#define kUITextFieldHeight 30.0
#define kUITextFieldXPadding 12.0
#define kUITextFieldYPadding 10.0
#define kUIAlertOffset 100.0
@interface TextAlertView : UIAlertView {
UITextField *textField;
BOOL layoutDone;
}
@property (nonatomic, retain) UITextField *textField;
- (id)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)delegate
cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ...;
@end


TextAlertView.m


/*
* Text Alert View
*
* File: TextAlertView.m
* Abstract: UIAlertView extension with UITextField (Implementation).
*
*/
#import "TextAlertView.h"
@implementation TextAlertView
@synthesize textField;
/*
* Initialize view with maximum of two buttons
*/
- (id)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)delegate
cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... {
self = [super initWithTitle:title message:message delegate:delegate cancelButtonTitle:cancelButtonTitle
otherButtonTitles:otherButtonTitles, nil];
if (self) {
// Create and add UITextField to UIAlertView
UITextField *myTextField = [[[UITextField alloc] initWithFrame:CGRectZero] retain];
myTextField.autocorrectionType = UITextAutocorrectionTypeNo;
myTextField.alpha = 0.75;
myTextField.borderStyle = UITextBorderStyleRoundedRect;
myTextField.delegate = delegate;
[self setTextField:myTextField];
// insert UITextField before first button
BOOL inserted = NO;
for( UIView *view in self.subviews ){
if(!inserted && ![view isKindOfClass:[UILabel class]])
[self insertSubview:myTextField aboveSubview:view];
}
//[self addSubview:myTextField];
// ensure that layout for views is done once
layoutDone = NO;
// add a transform to move the UIAlertView above the keyboard
CGAffineTransform myTransform = CGAffineTransformMakeTranslation(0.0, kUIAlertOffset);
[self setTransform:myTransform];
}
return self;
}
/*
* Show alert view and make keyboard visible
*/
- (void) show {
[super show];
[[self textField] becomeFirstResponder];
}
/*
* Determine maximum y-coordinate of UILabel objects. This method assumes that only
* following objects are contained in subview list:
* - UILabel
* - UITextField
* - UIThreePartButton (Private Class)
*/
- (CGFloat) maxLabelYCoordinate {
// Determine maximum y-coordinate of labels
CGFloat maxY = 0;
for( UIView *view in self.subviews ){
if([view isKindOfClass:[UILabel class]]) {
CGRect viewFrame = [view frame];
CGFloat lowerY = viewFrame.origin.y + viewFrame.size.height;
if(lowerY > maxY)
maxY = lowerY;
}
}
return maxY;
}
/*
* Override layoutSubviews to correctly handle the UITextField
*/
- (void)layoutSubviews {
[super layoutSubviews];
CGRect frame = [self frame];
CGFloat alertWidth = frame.size.width;
// Perform layout of subviews just once
if(!layoutDone) {
CGFloat labelMaxY = [self maxLabelYCoordinate];
// Insert UITextField below labels and move other fields down accordingly
for(UIView *view in self.subviews){
if([view isKindOfClass:[UITextField class]]){
CGRect viewFrame = CGRectMake(
kUITextFieldXPadding,
labelMaxY + kUITextFieldYPadding,
alertWidth - 2.0*kUITextFieldXPadding,
kUITextFieldHeight);
[view setFrame:viewFrame];
} else if(![view isKindOfClass:[UILabel class]]) {
CGRect viewFrame = [view frame];
viewFrame.origin.y += kUITextFieldHeight;
[view setFrame:viewFrame];
}
}

// size UIAlertView frame by height of UITextField
frame.size.height += kUITextFieldHeight + 2.0;
[self setFrame:frame];
layoutDone = YES;
} else {
// reduce the x placement and width of the UITextField based on UIAlertView width
for(UIView *view in self.subviews){
if([view isKindOfClass:[UITextField class]]){
CGRect viewFrame = [view frame];
viewFrame.origin.x = kUITextFieldXPadding;
viewFrame.size.width = alertWidth - 2.0*kUITextFieldXPadding;
[view setFrame:viewFrame];
}
}
}
}
@end

Dec 10, 2008 3:09 AM in response to interman

Hi,
the easiest way is the following:

Create a file called UIAlertView_Extended.h with following content:

@class UITextField, UILabel;
@interface UIAlertView (Extended)
- (UITextField)addTextFieldWithValue:(NSString)value label:(NSString*)label;
- (UITextField*)textFieldAtIndex:(NSUInteger)index;
- (NSUInteger)textFieldCount;
- (UITextField*)textField;
@end


You just need to include this, create an alert and add a textfield. Through the [UIAlertSheet textField] method you can retrieve the field and customize it or retrieve its value.


UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"My Title"
message:@"My Message"
delegate:self cancelButtonTitle:@"Cancel"
otherButtonTitles:@"OK", nil];
[alert addTextFieldWithValue:@"25" label:nil];
[alert textField].keyboardType = UIKeyboardTypeNumberPad;
alert.tag = kMyAlert;
[alert show];
[alert release];


Your delegate method would look like this:

- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if(buttonIndex > 0) {
if(actionSheet.tag == kMyAlert) {
NSString *textValue = [actionSheet textField].text;
if(textValue==nil)
return;
NSInteger value = [textValue integerValue];
}
}
}

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

Add TextField or other control to UIActionSheet or UIAlertView

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.