I'm trying to implement custom AlertView.
The idea is to have alertview with textfield and cancel button.
What i can't do is to check textfield live for entered characters. I know i can do it using – alertViewShouldEnableFirstOtherButton: but i don't want another button. I wish to do the same just without button.
In android you can add listeners to textfields onchange.
Tried to do it using this uitextfield function, but it doesn't get called live or maybe i'm using it in a wrong way.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
textField = [alert textFieldAtIndex:0];
if ([textField.text length] == 0)
{
NSLog(#"Hello");
return NO;
}
return NO;
}
So how to do this properly?
try this
UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"New List Item", #"new_list_dialog")
message:#"this gets covered" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil];
UITextField *myTextField = [[UITextField alloc] initWithFrame:CGRectMake(12.0, 45.0, 260.0, 25.0)];
myTextField.delegate = self;
[myTextField setBackgroundColor:[UIColor whiteColor]];
[myAlertView addSubview:myTextField];
[myAlertView show];
[myAlertView release];
and textfield method
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
NSLog(#" %#", [textField.text stringByReplacingCharactersInRange:range withString:string]);
return YES;
}
You can add observer for the UITextFieldTextDidChangeNotification which will be posted whenever the text changes in textfield.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(controlTextDidChange:)
name:UITextFieldTextDidChangeNotification object:[alert textField]];
selector is below:
- (void)controlTextDidChange:(NSNotification *)notification {
{
if ([notification object] == [alert textField])
{
// [alert textField] has changed
}
}
EDIT : remove Observer when finish doing
[[NSNotificationCenter defaultCenter] removeObserver:UITextFieldTextDidChangeNotification];
Related
want to get input from pickerView in textField when alert show Objective C
NOTE: Opening actionsheet from alertview first dismiss your alertview then open actionsheet.My code may help you regarding opening actionsheet from alertview
#import "ViewController.h"
#interface ViewController ()<UITextFieldDelegate,UIActionSheetDelegate>
{
NSString *alertSelectValue;
UITextField * alertTextField;
}
#end
#implementation ViewController
- (void)viewDidLoad {
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:#"Hello!" message:#"Please enter your name:" delegate:self cancelButtonTitle:#"Continue" otherButtonTitles:nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
UITextField * alertTextField = [alert textFieldAtIndex:0];
alertTextField.tag=101;
alertTextField.delegate=self;
alertTextField.keyboardType = UIKeyboardTypeNumberPad; alertTextField.placeholder = #"Enter your name";
[alert show];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
if (textField.tag==101)
{
[textField setUserInteractionEnabled:YES];
[textField resignFirstResponder];
NSString*String = [NSString stringWithFormat:#"%#",textField.text];
[self openSheet:String];
}
}
-(void)openSheet:(NSString*)text
{
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Select" delegate:self cancelButtonTitle:#"OK" destructiveButtonTitle:nil otherButtonTitles:text,#"Test" ,nil];
actionSheet.actionSheetStyle = UIActionSheetStyleDefault;
UIViewController *topvc=[self topMostController];
[actionSheet showInView:topvc.view];
}
//-------- Get top Most view to -----
- (UIViewController*) topMostController
{
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
return topController;
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSLog(#"Index = %d - Title = %#", buttonIndex, [actionSheet buttonTitleAtIndex:buttonIndex]);
if(buttonIndex == 0)
{
alertTextField.text= [actionSheet buttonTitleAtIndex:buttonIndex];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I have a UITableView set up programatically, and it is populated with all the names of the states. When you click on one of the cells, for ex. ALABAMA, a UIAlertView will appear With the title being that of the state you just clicked on (ALABAMA) and a number that correlates to that state, which is in another NSMutable Array. Every state has a different number to correlate with it.
This number is actually a placeholder text in the UIAlert, and the purpose of the alert is so that you can input a number in the text field, and when you hit the CHANGE button, the number that was in the placeholder text (from the Array) will be changed with the number that the user imputed; permanently. All is good until I hit change, and then I get a SIGABRT error, and in output it reads:
2013-02-21 20:57:33.750 final[10046:11303] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM replaceObjectAtIndex:withObject:]: object cannot be nil'
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:[NSString stringWithFormat:#"%#", [states objectAtIndex:indexPath.row]]
message:[NSString stringWithFormat:#"%#", [tax objectAtIndex:53]]
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Change", nil];
UITextField *myTextField =[[UITextField alloc] initWithFrame:CGRectMake(42, 50, 200, 25)];
CGAffineTransform myTransform =CGAffineTransformMakeTranslation(0, 0);
[alertView setTransform:myTransform];
[myTextField setBackgroundColor:[UIColor clearColor]];
[alertView addSubview:myTextField];
myTextField.placeholder = [NSString stringWithFormat:#"%#", [tax objectAtIndex:indexPath.row]];
myTextField.borderStyle = UITextBorderStyleNone;
myTextField.returnKeyType = UIReturnKeyDone;
myTextField.textColor = [UIColor grayColor];
myTextField.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
myTextField.textAlignment = UITextAlignmentCenter;
myTextField.delegate = self;
[alertView show];
[alertView release];
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) {
NSString *theTaxer = [myTextField text];
[tax replaceObjectAtIndex:1 withObject:theTaxer];
}
}
At the point when alertView:clickedBUttonAtIndex is called myTextField is no longer defined since myTextField isn't defined as a class ivar you can only reference it in the function you created it in. If you want to reference myTextField elsewhere in your class (in the alertView callback for instance) make it a class iVar.
Try this,
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:[NSString stringWithFormat:#"%#", [states objectAtIndex:indexPath.row]]
message:[NSString stringWithFormat:#"%#", [tax objectAtIndex:53]]
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Change", nil];
alertView.tag =indexPath.row;
UITextField *myTextField =[[UITextField alloc] initWithFrame:CGRectMake(42, 50, 200, 25)];
[myTextField setTag:99];
CGAffineTransform myTransform =CGAffineTransformMakeTranslation(0, 0);
[alertView setTransform:myTransform];
[myTextField setBackgroundColor:[UIColor clearColor]];
[alertView addSubview:myTextField];
myTextField.placeholder = [NSString stringWithFormat:#"%#", [tax objectAtIndex:indexPath.row]];
myTextField.borderStyle = UITextBorderStyleNone;
myTextField.returnKeyType = UIReturnKeyDone;
myTextField.textColor = [UIColor grayColor];
myTextField.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
myTextField.textAlignment = UITextAlignmentCenter;
myTextField.delegate = self;
[alertView show];
[alertView release];
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) {
UITextField * myTextField = (UITextField *)[alertView viewWithTag:99];
NSString *theTaxer = [myTextField text];
[tax replaceObjectAtIndex:1 withObject:theTaxer];
}
}
Shizam is right, I think if you want get the reference of the textview, just give a tag to the textview when you create the alertview like this: myTextField.tag = 111;
and then in the alertView delegate method:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) {
UITextField *textField = [alertView viewWithTag:111];
NSString *theTaxer = [textField text];
[tax replaceObjectAtIndex:1 withObject:theTaxer];
}
}
I have multiple textFields. In one of them, i want to display a UIPickerView.
I did it this way:
-(void)showPicker{
[subject becomeFirstResponder];
actionSheet = [[UIActionSheet alloc] initWithTitle:nil
delegate:nil
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
[actionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
CGRect pickerFrame = CGRectMake(0, 40, 0, 0);
picker = [[UIPickerView alloc] initWithFrame:pickerFrame];
picker.showsSelectionIndicator = YES;
picker.dataSource = self;
picker.delegate = self;
[actionSheet addSubview:picker];
[picker release];
UISegmentedControl *closeButton = [[UISegmentedControl alloc] initWithItems: [NSArray arrayWithObject:#"Close"]];
closeButton.momentary = YES;
closeButton.frame = CGRectMake(260, 7.0f, 50.0f, 30.0f);
closeButton.segmentedControlStyle = UISegmentedControlStyleBar;
closeButton.tintColor = [UIColor blackColor];
[closeButton addTarget:self action:#selector(dismissActionSheet) forControlEvents:UIControlEventValueChanged];
[actionSheet addSubview:closeButton];
[closeButton release];
[actionSheet showInView:[[UIApplication sharedApplication] keyWindow]];
[actionSheet setBounds:CGRectMake(0, 0, 320, 485)];
}
-(void)dismissActionSheet{
[actionSheet dismissWithClickedButtonIndex:0 animated:YES];
}
When i close it, the sheet is being dismissed, but the keyboard on the subject textField appears.
Now:
How can i do to not to show the keyboard on that subject textField?
Here is where i resign the keyboard:
- (void) resignKeyboard:(id)sender{
if ([name isFirstResponder])
[name resignFirstResponder];
else if ([email isFirstResponder])
[email resignFirstResponder];
else if ([message isFirstResponder])
[message resignFirstResponder];
else if ([subject isFirstResponder]) {
[subject resignFirstResponder];
}
}
Use UItextField delegates: For that u need add #interface YourViewController :UIViewController
If UItextField taken from xib by right clicking add its delegate to fileowner
Now use this method in code:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if(textField == subject)
{
return NO;
}
return YES;
}
It is possible to prevent the keyboard from popping up.
Firstly set your class as the delegate of UITexfield
textField.delegate = self
In your Interface Declaration add:
<UITextFieldDelegate>
Now implement textFieldShouldBeginEditing::
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
// Show UIPickerView
return NO;
}
Solved by using a transparent button which handles the action to show the picker. The "subject" textField was disabled.
I have a UIAlertView with a textField on it and two buttons: Save & Cancel. When the Save button is tapped I am checking if the text field isn't empty and after if it is I simply want to change the textFields placeholder to: #"enter a name please" and KEEP the alert view on screen. However it is automatically dismissed.
How do I override that?
Add a target to the textfield in a subclassed alertView. You can subclass the alertView and not dismiss as described in this post
[[alertView textFieldAtIndex:0] addTarget:self action:#selector(textFieldDidChange) forControlEvents:UIControlEventEditingChanged];
Then write a function called textFieldDidChange that checks the current textfield of your alertView and set a boolean value so you know whether or not to dismiss the alert.
- (void) textFieldDidChange
{
NSString *alertViewText = [[alertView textFieldAtIndex:0] text];
if ([alertViewText isEqualToString:#""]) {
[alertView setMessage:#"Enter a name please."];
} else {
[alertView setMessage:#"Default Message"];
}
}
* Alternatively, I would suggest disabling "Save" when it is empty and not have to subclass. *
- (void) textFieldDidChange
{
NSString *alertViewText = [[alertView textFieldAtIndex:0] text];
if ([alertViewText isEqualToString:#""]) {
[alertView setMessage:#"Enter a name please."];
for (UIViewController *view in alertView.subview) {
if ([view isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)view;
if ([[[button titleLabel] text] isEqualToString:#"Save"])
[button setEnabled:NO];
}
}
} else {
[alertView setMessage:#"Default Message"];
for (UIViewController *view in alertView.subview) {
if ([view isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)view;
if ([[[button titleLabel] text] isEqualToString:#"Save"])
[button setEnabled:YES];
}
}
}
}
The below code shows that when a user does a long press gesture on a Table View Cell, then a UIActionSheet launches with a UITextField inside of it. When tapping the UITextField, the keyboard launches, and textFieldShouldBeginEditing and textFieldDidBeginEditing get called, but the text field won't accept the key taps.
Hitting the return key won't trigger the delegate methods, but tapping one of the UIActionSheet buttons will trigger textFieldShouldEndEditing and then textFieldDidEndEditing.
I'm setting the textField to become the first responder, so I'm not sure why it's not accepting input from the keyboard. Any suggestions?
- (void)longPress:(UILongPressGestureRecognizer *)gesture
{
// only when gesture was recognized, not when ended
if (gesture.state == UIGestureRecognizerStateBegan)
{
// get affected cell
SinTableViewCell *cell = (SinTableViewCell *)[gesture view];
// get indexPath of cell
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
// do something with this action
NSLog(#"Long-pressed cell at row %d", indexPath);
AppDelegate_Shared *appDelegate = (AppDelegate_Shared*)[UIApplication sharedApplication].delegate;
//setup UITextField for the UIActionSheet
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 170, 320, 200)];
textField.borderStyle = UITextBorderStyleBezel;
textField.backgroundColor = UIColorFromRGB(0XFFFFFF);
textField.text = #"";
textField.delegate = self;
[textField setKeyboardType:UIKeyboardTypeAlphabet];
[textField setKeyboardAppearance:UIKeyboardAppearanceAlert];
//setup UIActionSheet
UIActionSheet *asheet = [[UIActionSheet alloc] initWithTitle:#"Add Notes"
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil
otherButtonTitles: #"Save", nil];
[asheet showFromTabBar:appDelegate.tabBarController.tabBar];
[asheet setFrame:CGRectMake(0, 100, 320,380)];
[asheet insertSubview:textField atIndex:0];
//[textField becomeFirstResponder];
//memory management
[textField release];
[asheet release];
}
}
#pragma mark -
#pragma mark UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex {
}
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
}
#pragma mark -
#pragma mark UITextFieldDelegate
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
NSLog(#"textFieldShouldBeginEditing");
return YES;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField {
NSLog(#"textFieldDidBeginEditing");
[textField becomeFirstResponder];
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
NSLog(#"textFieldShouldEndEditing");
return YES;
}
//should save the notes value here, I think
- (void)textFieldDidEndEditing:(UITextField *)textField {
NSLog(#"textFieldDidEndEditing");
[textField resignFirstResponder];
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
return YES;
}
- (BOOL)textFieldShouldClear:(UITextField *)textField {
NSLog(#"textFieldShouldClearEditing");
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
NSLog(#"in textFieldShouldReturn");
return YES;
}
Your question is a little bit old but not marked as answered, so if it is helpful for you or other viewers I post my solution from my own SO question. I started up with the same problem as you had and ended up in the fact that UIActionSheet really eats up some important events which are necessary to get the keyboard working properly.
My linked posted code unfortunately works only in portrait orientation, anyway it does it.
Is UITextFieldDelegate and UIActionSheetDelegate in your header?
If not, there could be problems while setting the textfield.delegate to self