I am new to iOS,
I want to change keyboard after certain characters left in UITextField,
for e.g.: I have String of #"AEBPQ1234M"
for first 5 letters I want alphabet keyboard and then for next 4 letters I need number pad and on last letter I need again alphabet.
here is the code I have tried but it's not working when I hit backspace in the keyboard.
-(void)textFieldDidChange :(UITextField *)theTextField{
if (theTextField.text.length < 5 || theTextField.text.length >= 9) {
[theTextField setKeyboardType:UIKeyboardTypeEmailAddress];
}
if (theTextField.text.length >= 5 && theTextField.text.length < 9 ) {
[theTextField setKeyboardType: UIKeyboardTypeNumberPad];
}
[theTextField reloadInputViews];
}
Where I am making mistake?
Try this-
-(void)textFieldDidChange :(UITextField *)theTextField{
if (panNumber.length <= 5 || panNumber.length > 9) {
[theTextField setKeyboardType:UIKeyboardTypeEmailAddress];
}
else {
[theTextField setKeyboardType: UIKeyboardTypeNumberPad];
}
[theTextField reloadInputViews];
}
use this
where selector textEditingChanged: should listen for UIControlEventEditingChanged event
//add following in viewDidLoad
[self.textField addTarget:self action:#selector(textEditingChanged:) forControlEvents:UIControlEventEditingChanged];
-(void)textEditingChanged:(UITextField*) sender{
if (sender.text.length > 5 && sender.text.length < 9 ) {
[self.textField setKeyboardType: UIKeyboardTypeNumberPad];
}
if (sender.text.length < 5 || sender.text.length == 10) {
[self.textField setKeyboardType:UIKeyboardTypeEmailAddress];
}
[self.textField reloadInputViews];
}
This will be a bad experience for a user who types very fast in phone keyboard.
Try below code.
At first declare UITextFieldDelegate in your .h file. Also set it's delegate with self.
You can set self delegate with two types :-
1. Storyboard
2. Code
When set with code write textField.delegate = self; in viewDidLoad method.
Now use below code in .m file
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (textField.text.length < 4 || textField.text.length > 7) {
[textField setKeyboardType: UIKeyboardTypeEmailAddress];
} else {
[textField setKeyboardType: UIKeyboardTypeNumberPad];
}
[textField reloadInputViews];
return YES;
}
I would recommend using multiple textFields each with their own keyboard type.
Then on your end you can append the inputted strings together to do whatever it is you need to do. This is much better user experience and also much simpler to do.
Please check my answer.It works perfectly.I tried it then only I post the answer here.
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
if(string.length == 0 && range.location == 9)
range.location = range.location - 2;
if(string.length == 0 && range.location == 8)
range.location = range.location - 1;
if(string.length == 0 && range.location > 3)
range.location = range.location - 2;
if(range.location <= 3){
textField.keyboardType = UIKeyboardTypeAlphabet;
[textField reloadInputViews];
return YES;
}
else if(range.location > 3 && range.location <= 7){
textField.keyboardType = UIKeyboardTypeNumberPad;
[textField reloadInputViews];
return YES;
}
else if(range.location > 7){
textField.keyboardType = UIKeyboardTypeAlphabet;
[textField reloadInputViews];
return YES;
}
else{
return NO;
}
return YES;
}
Related
I know this may be perceived as a duplicate but I promise you it is not.
Everybody has given an answer similar to this:
if ([_confirm.text isEqualToString: _password.text] || resultantLength2 < 3) {
textField.textColor = [UIColor redColor];
[_next setEnabled:NO];
}else{
[_next setEnabled:YES];
}
}
So why does this not work?
- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (textField == _confirm || textField == _password) {
int resultantLength2 = textField.text.length + string.length - range.length;
NSLog(#"Length After Additions And Subtractions Will Be: %i letters", resultantLength2);
if ([_confirm.text isEqualToString: _password.text] || resultantLength2 < 3) {
textField.textColor = [UIColor redColor];
[_next setEnabled:NO];
}else{
[_next setEnabled:YES];
}
}
return YES;
}
Where I have a next button that gets dissabled
What we actually want to do is compare the strings in the text fields AFTER the text has changed, but currently, we're using a method that is fired BEFORE the text changes and asks whether or not the change is okay.
We can do some tricks in this method to get it work right, but why not just check the values after they've changed?
In the view controller's viewDidLoad, add these two lines:
[_confirm addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
[_password addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
Now add the textFieldDidChange: method to compare the values in the textfield.
- (void)textFieldDidChange:(UITextField *)textField {
if (![_confirm.text isEqualToString: _password.text]) {
textField.textColor = [UIColor redColor];
[_next setEnabled:NO];
} else {
[_next setEnabled:YES];
}
}
Your problem is that you are in shouldChangeCharactersInRange, which is called before the text field is updated, but you are comparing the current value of _confirm.text
Also, your string comparison logic seems to be the wrong way around - you want NEXT enabled if the password is the same as the confirm I would think
I would try this -
- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (textField == _confirm) {
NSMutableString *newValue=[NSMutableString stringWithString:textField.text];
[newValue replaceCharactersInRange:range withString:string];
int resultantLength2 = newValue.length;
NSLog(#"Length After Additions And Subtractions Will Be: %i letters", resultantLength2);
if (([newValue isEqualToString: _password.text] == NO) || resultantLength2 < 3) {
textField.textColor = [UIColor redColor];
[_next setEnabled:NO];
}else{
textField.textColor = SOMETHING; // should reset text colour
[_next setEnabled:YES];
}
}
return YES;
}
In my app I have a view with 3 textfields. Until they are ALL filled out, I want my button to be disabled. In the storyboard I left it enabled, but then in my ViewDidLoad I added this:
if (amtYouOwe.text.length == 0 && personYouOweMoney.text.length == 0 && self.cellNum.text.length == 0)
{
saveButton.enabled = NO;
}
Even if all the fields were filled out my button was disabled..So then I tried to put it in my IBAction save button. This time I got the opposite result. No matter what my button was enabled. Even if all the textfields were blank. I believe my code is correct, I'm just trying to find the perfect place to put it....
All help is appreciated, thanks in advance.
Write a function to enable/disable saveButton as
-(void)enableDisableSave{
if (amtYouOwe.text.length == 0 && personYouOweMoney.text.length == 0 && self.cellNum.text.length == 0){
saveButton.enabled = NO;
} else {
saveButton.enabled = YES;
}
}
Write a delegate method of textField, assign your view controller as delegate to all textfield, write following delegate method and call that method in that and bingo..
- (void)textFieldDidEndEditing:(UITextField *)textField {
[self enableDisableSave];
}
You should add button enable/disable control in UITextField delegate methods. Every time a text field being edited, check all the text fields' length and change button status.
https://developer.apple.com/library/ios/documentation/uikit/reference/UITextFieldDelegate_Protocol/UITextFieldDelegate/UITextFieldDelegate.html
If you want real time checking, use this:
- (void)viewDidLoad {
[super viewDidLoad];
// ..
// your code
// ..
[self addTextChangedEvent];
[self toggleSaveButtonStatus];
}
- (void)addTextChangedEvent {
[amtYouOwe addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
[personYouOweMoney addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
[self.cellNum addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
}
- (void)textFieldDidChange:(UITextField *)textField {
[self toggleSaveButtonStatus];
}
- (void)toggleSaveButtonStatus {
int youOweLength = amtYouOwe.text.length;
int personYouOweLength = personYouOweMoney.text.length;
int cellNumLength = self.cellNum.text.length;
saveButton.enabled = youOweLength > 0 && personYouOweLength > 0 && cellNumLength > 0;
}
Write in .pch file
This macro does not allow white space..
#define allTrim( object ) [object stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet] ]
then write delegate method
- (void)textFieldDidEndEditing:(UITextField *)textField {
[self enableDisableSave];
}
Write a function to enable/disable saveButton as
-(void)enableDisableSave{
if ([allTrim(amtYouOwe.text) length] == 0 && [allTrim(personYouOweMoney.text) length] == 0 && [allTrim(self.cellNum.text) length] == 0){
saveButton.enabled = NO;
} else {
saveButton.enabled = YES;
}
}
Happy Coding!!!
I have in my TableViewCell 2 TextFields.
For the 2nd TextField i need a confirm to enable a button.
I´m using this code to determine if the confirm button should be enabled, but it doesn't work:
-(BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
textField = self.installDeviceCell.passWordTextFieldOutlet;
[textField addTarget:selfaction:#selector(checkTextField:)forControlEvents:UIControlEventEditingChanged];
return YES;
}
-(void)checkTextField:(id)sender
{
UITextField* textField = (UITextField*)sender;
if ([textField.text length] < 7) {
self.installDeviceCell.installDeviceTouchUpInsideButton.enabled = NO;
}else if ([textField.text length] > 7){
self.installDeviceCell.installDeviceTouchUpInsideButton.enabled = YES;
}else{
self.installDeviceCell.installDeviceTouchUpInsideButton.enabled = YES;
}
}
Have you assigned your UITextFieldDelegate for your UITextField when it is being instatiated? If don't assign the it the delegate methods for the UITextField will not be called.
Also make sure that in the header file of the delegate you specify the delegate of the interface e.g.
#interface MyDelegate <UITextFieldDelegate>
// ...
#end
Finally you're doing your text calculations a little oddly. You can do all your computations witin shouldChangeCharactersInRange. You also don't need to add the target or overwrite the textField property. Simply check if the replacementString is greater than 7 characters. Your final code might look something like this:
-(BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if ([string length] < 7) {
self.installDeviceCell.installDeviceTouchUpInsideButton.enabled = NO;
} else {
self.installDeviceCell.installDeviceTouchUpInsideButton.enabled = YES;
}
return YES;
}
See this great answer on delegation for more info: https://stackoverflow.com/a/626946/740474
I have textField i want that when user enter data and presses space then it should add new row in tableView it works fine but i also want that on textFieldDidEndEditing it should also add row but when there is no space press by user right now in my code if any user pressed space code it add rows also and then other row for textFieldDidEndEditing.
-(void)textFieldDidEndEditing:(UITextField *)textField {
if (textField==tagTextField) {
[self showAnimationBack];
}
if (textField.tag==2) {
if (textField.text.length > 0 || ![tagTextField.text isEqualToString:#""]) {
[textField resignFirstResponder];
[tagArray addObject:tagInputField.text];
[tableView reloadData];
tableView.frame = CGRectMake(tableView.frame.origin.x, tableView.frame.origin.y, tableView.frame.size.width, tableView.contentSize.height);
[tableView.layer setCornerRadius:7.0f];
[tableView.layer setMasksToBounds:YES];
tableView.layer.borderWidth = 0.5;
tableView.layer.borderColor = [UIColor grayColor].CGColor;
[self showAnimationBack];
float y = descriptionTextImageView.frame.origin.y;
float yp = publishButton.frame.origin.y;
NSLog(#"Y is %2.f",y);
if (y==405.00) {
[descriptionTextImageView setFrame:CGRectMake(48,y+30,250,90)];
[publishButton setFrame:CGRectMake(40,yp+30,250, 50)];
}
else{
y=y+30;
[descriptionTextImageView setFrame:CGRectMake(48,y,250,90)];
[publishButton setFrame:CGRectMake(40,yp+30,250, 50)];
}
}
}
}
And Other when space is pressed
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (textField.tag==2) {
if ( [string isEqualToString:#" " ]){
if (textField.text.length > 0 || ![tagTextField.text isEqualToString:#""]) {
[textField resignFirstResponder];
[tagArray addObject:tagInputField.text];
[tableView reloadData];
tableView.frame = CGRectMake(tableView.frame.origin.x, tableView.frame.origin.y, tableView.frame.size.width, tableView.contentSize.height);
[tableView.layer setCornerRadius:7.0f];
[tableView.layer setMasksToBounds:YES];
tableView.layer.borderWidth = 0.5;
tableView.layer.borderColor = [UIColor grayColor].CGColor;
float y = descriptionTextImageView.frame.origin.y;
float yp = publishButton.frame.origin.y;
NSLog(#"Y is %2.f",y);
if (y==405.00) {
[descriptionTextImageView setFrame:CGRectMake(48,y+30,250,90)];
[publishButton setFrame:CGRectMake(40,yp+30,250, 50)];
}
else{
y=y+30;
[descriptionTextImageView setFrame:CGRectMake(48,y,250,90)];
[publishButton setFrame:CGRectMake(40,yp+30,250, 50)];
}
[self showAnimationBack];
}
}
else {
return YES;
}
}
}
I could not completely get what are you actually looking for. If you are trying to avoid adding of new if user simply presses space bar without entering any other character then below piece of code can help you out:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *resultingString = [textField.text stringByReplacingCharactersInRange: range withString: string];
NSCharacterSet *whitespaceSet = [NSCharacterSet whitespaceCharacterSet];
if ([resultingString rangeOfCharacterFromSet:whitespaceSet].location == NSNotFound) {
return YES;
} else {
return NO;
}
}
use uitextview it's work's what you want
I tink u should call textFieldShouldReturn
textFieldDidEndEditing is fired when the textfield resigns it's first responder and textFieldShouldReturn is fired when the return button is pressed.
Mayb your textfield is never resigning its firstResponder. You can check it by putting some debug output or by navigating out of the textfield with a touch - eg start typing then just touch outside of the field to force it to resign firstResponder.
i have four textfields. User is allowed to enter only one digit in each text field.Once the user Enters single digit its focus should be on the next textfield. i have done this part and its working fine. Now, What i want is when i remove the text from the text field then its focus should move to previous textfield. i mean if i am deleting the text(digit) from the fourth text field then its focus should move to third text field. In short on removal of text the focus should be on previous textfield.
Now, what my problem is when i remove the text from the textfield then its focus moves to previous textfield but it clears the text of that textfield(the textfield on which i have set the focus).What i want is the text should not be removed on focus.
in .h file
IBOutlet UITextField *txtPinDigit1;
IBOutlet UITextField *txtPinDigit2;
IBOutlet UITextField *txtPinDigit3;
IBOutlet UITextField *txtPinDigit4;
UITextField *currentTextField;
in .m file
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if(textField.tag==0)
{
currentTextField=txtPinDigit1;
}
else if(textField.tag==1)
{
currentTextField=txtPinDigit2;
}
else if(textField.tag==2)
{
currentTextField=txtPinDigit3;
if(isDelete)
{
textField.text=digit3;
}
}
else if(textField.tag==3)
{
currentTextField=txtPinDigit4;
}
return YES;
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if(([textField.text length]==1)&&(![string isEqualToString:#""]))
{
if(currentTextField==txtPinDigit1)
{
[txtPinDigit2 becomeFirstResponder];
}
else if(currentTextField==txtPinDigit2)
{
[txtPinDigit3 becomeFirstResponder];
}
else if(currentTextField==txtPinDigit3)
{
[txtPinDigit4 becomeFirstResponder];
}
else if(currentTextField==txtPinDigit4)
{
textField.text = [textField.text substringToIndex:MAXLENGTH-1];
//[txtPinDigit4 resignFirstResponder];
//[txtPinDigit1 becomeFirstResponder];
}
}
else if([string isEqualToString:#""])
{
isDelete=YES;
NSLog(#"replacementString:%#",string);
// textField.text=string;
if(currentTextField==txtPinDigit4)
{
textField.text=string;
digit3=nil;
[digit3 release];
digit3=[[NSString alloc] initWithFormat:#"%i",[txtPinDigit3.text intValue]];
[txtPinDigit3 becomeFirstResponder];
}
else if(currentTextField==txtPinDigit3)
{
textField.text=string;
[txtPinDigit2 becomeFirstResponder];
}
else if(currentTextField==txtPinDigit2)
{
textField.text=string;
[txtPinDigit1 becomeFirstResponder];
}
else if(currentTextField==txtPinDigit1)
{
textField.text=string;
// [txtPinDigit1 resignFirstResponder];
//[txtPinDigit1 becomeFirstResponder];
}
}
return YES;
}
in the above code MAXLENGTH=1 defined.
any help will be appreciated.
thanks in advance.
Try This code, Change shouldChangeCharactersInRange: Delegate Method
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
if ([newString length] < 1)
{
if (textField.tag==2)
{
[txtPinDigit1 performSelector:#selector(becomeFirstResponder) withObject:nil afterDelay:0.0];
// txt2.text=#"";
}
else if (textField.tag==3)
{
[txtPinDigit2 performSelector:#selector(becomeFirstResponder) withObject:nil afterDelay:0.0];
}
else if (textField.tag==4)
{
[txtPinDigit3 performSelector:#selector(becomeFirstResponder) withObject:nil afterDelay:0.0];
}
return YES;
} else
{
// Otherwise we cut the length of newString to 1 (if needed) and set it to the textField.
textField.text = [newString length] > 1 ? [newString substringToIndex:1] : newString;
if (textField.tag==1)
{
[textField resignFirstResponder];
[txtPinDigit2 becomeFirstResponder];
}
else if (textField.tag==2)
{
[textField resignFirstResponder];
[txtPinDigit3 becomeFirstResponder];
}
else if (textField.tag==3)
{
[textField resignFirstResponder];
[txtPinDigit4 becomeFirstResponder];
}
return NO;
}
}
Check to check length via this way and put a break point at beginning of shouldChangeCharactersInRange
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
int length = textField.text.length - range.length + string.length;
return YES;
}
I hope it will help you.
Before calling up to become first responder on filling up the 1st digit,bind the entered text inputs & the responder into dictionary...
On each previous/next condition,retrieve the information from the dictionary...The below example code is for the general previous/next custom actions(not auto though)..You just need to change the logic a bit based on the condition you prefer...
- (NSArray *) responders
{
if (_responders)
return _responders;
NSArray *textInputs = EditableTextInputsInView([[UIApplication sharedApplication] keyWindow]);
return [textInputs sortedArrayUsingComparator:^NSComparisonResult(UIView *textInput1, UIView *textInput2) {
UIView *commonAncestorView = textInput1.superview;
while (commonAncestorView && ![textInput2 isDescendantOfView:commonAncestorView])
commonAncestorView = commonAncestorView.superview;
CGRect frame1 = [textInput1 convertRect:textInput1.bounds toView:commonAncestorView];
CGRect frame2 = [textInput2 convertRect:textInput2.bounds toView:commonAncestorView];
return [#(CGRectGetMinY(frame1)) compare:#(CGRectGetMinY(frame2))];
}];
}
The below function should get called before doing previous/next auto tab.
- (Void) selectAdjacentResponder: (UISegmentedControl *) sender
{
NSArray *firstResponders = [self.responders filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(UIResponder *responder, NSDictionary *bindings) {
return [responder isFirstResponder];
}]];
NSLog(#"%#",firstResponders);
UIResponder *firstResponder = [firstResponders lastObject];
NSInteger offset = sender.selectedSegmentIndex == 0 ? -1 : +1;
NSInteger firstResponderIndex = [self.responders indexOfObject:firstResponder];
NSInteger adjacentResponderIndex = firstResponderIndex != NSNotFound ? firstResponderIndex + offset : NSNotFound;
UIResponder *adjacentResponder = nil;
if (adjacentResponderIndex >= 0 && adjacentResponderIndex < (NSInteger)[self.responders count])
adjacentResponder = [self.responders objectAtIndex:adjacentResponderIndex];
[adjacentResponder becomeFirstResponder];
}
Bit lengthier,but this is all i know a BIT :)..Happy coding...