I wanna show a picker when I click inside a UITextField. This is my code (which works):
[super viewDidLoad];
// Picker View dei Tipi
pickerTipo= [[UIPickerView alloc] init];
pickerTipo.showsSelectionIndicator = YES;
UIToolbar* keyboardDoneButtonView = [[UIToolbar alloc] init];
[keyboardDoneButtonView sizeToFit];
UIBarButtonItem* doneButton = [[UIBarButtonItem alloc]
initWithTitle:
#"Fine" style:UIBarButtonItemStyleBordered
target:self
action:#selector(pickerDoneClicked:)];
[keyboardDoneButtonView setItems:[NSArray arrayWithObjects:doneButton, nil]];
self.textTipo.inputAccessoryView = keyboardDoneButtonView;
[self.textTipo resignFirstResponder];
self.textTipo.inputView = pickerTipo;
self.textTipo.delegate = self;
The picker and the accessory view show correctly. The problem is that the UITextField is still editable, that is I can still typing inside the UITextField. I would that when the picker is shown, no editing is enabled inside the UITextField.
[SOLVED}
Following the accepted answer, the right code is :
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField == self.textTipo || textField == self.textStato)
return NO;
else
return YES;
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if([textField.restorationIdentifier isEqualToString:#"textFieldIdentifier"])
{
return NO;
}
}
Hope it helps.
Instead of textfied you can use button with a background uiimage view of text field.
try this code:
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField;
{
if(textField==self.textTipo)
{
return NO;
}
else
{
return YES;
}
}
make your textfield a readonly property
Related
I have a button:
#property (weak, nonatomic) IBOutlet UIBarButtonItem *addTaskBtn;
...
// Add new task button action.
- (IBAction)addTaskBtnAction:(id)sender {
}
I want a keyboard with a textfield accessory toolbar to pop up when I press my button. That textfield should also become the firstresponder which causes kind of a paradox...
I find it impossible to show a keyboard without making it a first responder of an existing textfiled, but I am trying to create a textfield as a toolbar of a keyboard.
The best example for this is in this app: https://todoist.com/ - they managed to do exactly what I am trying to achieve.
Any ideas?
Try this code for the hidden textfield:
make txtHidden as hidden and make it first responder on button click
- (IBAction)btnOpenTextfield:(id)sender {
[self.txtHidden becomeFirstResponder];
}
- (void) setupToolbar {
UIToolbar *keyboardToolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 42)];
self.txtToolbar = [[UITextField alloc] initWithFrame:CGRectMake(8, 6, 250, 30)];
UIBarButtonItem *textBtn = [[UIBarButtonItem alloc] initWithCustomView:self.txtToolbar ];
UIBarButtonItem *postBtn = [[UIBarButtonItem alloc]initWithTitle:#"Post" style:UIBarButtonItemStyleBordered target:self action:#selector(postComment)];
[keyboardToolBar setItems: [NSArray arrayWithObjects:textBtn,postBtn,nil]];
self.txtHidden.inputAccessoryView = keyboardToolBar;
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if (textField == self.txtHidden) {
[self setupToolbar];
}
return true;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[self performSelector:#selector(changeResponder) withObject:nil afterDelay:0.1];
[self changeResponder];
}
- (void) changeResponder {
[self.txtToolbar becomeFirstResponder];
}
This is not the best way but you can try this till you get any other better solution
I have searched the entire internet and tried different ways to implement UITextFieldShouldReturn, but when I run it in the simulator it just doesn't work.
What I'm trying to do is move from the first textfield(emailTextField) to the second one( nameTextField ) when user clicks next button on the keyboard. The same for the second textfield's keyboard and dismiss the keyboard when user clicks done button on the last textfield( numberTextField ).
Here is my code, can anyone help me with this?
#import "ViewController.h"
#interface ViewController () <UITextFieldDelegate>
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.emailTextField.placeholder = #"Your Pitt Email(optional)";
self.nameTextField.placeholder = #"Lost ID Name";
self.numberTextField.placeholder = #"Lost ID Series Number(optional)";
[self.emailTextField.delegate self];
[self.nameTextField.delegate self];
[self.numberTextField.delegate self];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//release delegate
-(void)dealloc{
self.emailTextField.delegate = nil;
self.nameTextField.delegate = nil;
self.numberTextField.delegate = nil;
}
//dismiss keyboard when it's called
-(void)dismissKeyboard{
[self.emailTextField resignFirstResponder];
[self.nameTextField resignFirstResponder];
[self.numberTextField resignFirstResponder];
}
//when a textfield begins editing, this will happen
-(void)textFieldDidBeginEditing:(UITextField *)textField{
if(textField == self.emailTextField){
textField.placeholder = #"";
}else if(textField == self.nameTextField){
textField.placeholder = #"";
}else{
textField.placeholder = #"";
}
}
//when a textfield ends editing, this will happen
-(void)textFieldDidEndEditing:(UITextField *)textField{
if(textField == self.emailTextField){
textField.placeholder = #"Your Pitt Email(optional)";
[self textFieldShouldReturn:self.emailTextField];
}else if(textField == self.nameTextField){
textField.placeholder = #"Lost ID Name";
[self textFieldShouldReturn:self.nameTextField];
}else{
textField.placeholder = #"Lost ID Series Number(Optional)";
[self textFieldShouldReturn:self.numberTextField];
}
}
//return button set up
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
//when confirm is pressed
- (IBAction)confirmButton:(id)sender {
[self dismissKeyboard];
}
#end`
Change
[self.emailTextField.delegate self];
to
self.emailTextField.delegate = self;
Also remove those delegates from dealloc. You can put them from viewDidDisappear
Try this code snippet. Here i am taking only two
UITextFields.
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if (textField==_txtEmail)
{
[_txtEmail resignFirstResponder];
[_txtPassword becomeFirstResponder];
}
else if (textField==_txtPassword)
{
[_txtPassword resignFirstResponder];
}
return YES;
}
This function is enough to return keyboard from text fields.
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
Your these 3 lines are not working.
[self.emailTextField.delegate self];
[self.nameTextField.delegate self];
[self.numberTextField.delegate self];
If you are using storyboard, connect delegates of the text fields with the view.
You can use this code.It is working for me..
-(void)tool{
UIToolbar *toolbar = [[UIToolbar alloc] init];
[toolbar setBarStyle:UIBarStyleBlackTranslucent];
[toolbar sizeToFit];
UIBarButtonItem *flexButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
UIBarButtonItem *doneButton =[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(resignKeyboard)];
[doneButton setTintColor:[UIColor whiteColor]];
UIBarButtonItem *Next = [[UIBarButtonItem alloc]initWithTitle:#"Next" style:UIBarButtonItemStylePlain target:self action:#selector(Nextbutton)];
[Next setTintColor:[UIColor whiteColor]];
NSArray *itemsArray = [NSArray arrayWithObjects:Next,flexButton,doneButton,nil];
[toolbar setItems:itemsArray];
[FirstNameTextField setInputAccessoryView:toolbar];
[LastNameTextfield setInputAccessoryView:toolbar];
[EmailAddressTextField setInputAccessoryView:toolbar];
[PasswordTextfield setInputAccessoryView:toolbar];
[ConfirmPasswordTextfield setInputAccessoryView:toolbar];}
-(void)Nextbutton{
if ([FirstNameTextField isFirstResponder])
{
[LastNameTextfield becomeFirstResponder];
}
else if ([LastNameTextfield isFirstResponder])
{
[EmailAddressTextField becomeFirstResponder];
}
else if ([EmailAddressTextField isFirstResponder])
{
[PasswordTextfield becomeFirstResponder];
}
else if ([PasswordTextfield isFirstResponder])
{
[ConfirmPasswordTextfield becomeFirstResponder];
}
else if ([ConfirmPasswordTextfield isFirstResponder])
{
[ConfirmPasswordTextfield resignFirstResponder];
}}
-(void)resignKeyboard{
[FirstNameTextField resignFirstResponder];
[EmailAddressTextField resignFirstResponder];
[LastNameTextfield resignFirstResponder];
[PasswordTextfield resignFirstResponder];
[ConfirmPasswordTextfield resignFirstResponder];}
First of all you need to set the delegate right. Then You need to give your next textfield the becomeNextResponder call which should be ideally done in the shouldReturn delegate method.
In your viewDidLoad method, paste this.
self.emailTextField.tag = 2000;
self.nameTextField.tag = 3000;
self.numberTextField.tag = 4000;
Now edit your textFieldShouldReturn method like this:
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
if(textfield.tag<4000)
{
UITextField *nextTextField = (UITextField *)[self.view viewWithTag:textField.tag+1000];
[nextTextField becomeFirstResponder];
}
return YES;
}
you can always use a library to accomplish what you need to do !!
use this library : tpAvoidKeyboard
Read how to use it and there you go all the next buttons and clicks outside text fields to dismiss the keyboard and the the done button on the last textfield to dismiss the keyboard, all those features are already implemented
I have a UITextField and a UIDatePicker which I want to use to set the Birthday of the user.
I use this code in the viewDidLoad:
UIDatePicker *datePicker = [[UIDatePicker alloc] init];
birtdayTextField.inputView = datePicker;
However I have 2 problems. I've placed a UIDatePicker in my view in the storyboard. But it still opens a new datepicker even though I've connected the *datepicker to the UIDatePicker.
And also it doesn't add the info from the datepicker to the textfield.
Input view doesn't work so. You may create lazy UIDatePicker:
- (UIDatePicker *)bDatePicker {
if (!_bDatePicker) {
_bDatePicker = [UIDatePicker new];
_bDatePicker.datePickerMode = UIDatePickerModeDate;
[_bDatePicker addTarget:self action:#selector(datePickerDidChangeDate:) forControlEvents:UIControlEventValueChanged];
}
return _bDatePicker;
}
Then set it like following:
self.birtdayTextField.inputView = self.bDatePicker;
And this is the callback:
- (void)datePickerDidChangeDate:(UIDatePicker *)sender {
self.birtdayTextField.text = [self.bDateFormatter stringFromDate:sender.date];
}
Possible formatter:
- (NSDateFormatter *)bDateFormatter {
if (!_bDateFormatter) {
_bDateFormatter = [NSDateFormatter new];
_bDateFormatter.dateFormat = #"dd.MM.yyyy";
}
return _bDateFormatter;
}
To prevent pasting wrong data to that text field you may use it's delegate:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
return textField != self.birtdayTextField;
}
In my Project I have two UITextFields, one is used for Postal Code another one is used for Phone Number , so I used the Keyboard in NumberPad, Here I used the UIToolbar for both UITextFields for hide values, but my problem is TextField is does not identify the correct Tags in custom Methods for hide the textfields. How to resolve this issue
and my code is
- (void)viewDidLoad
{
[super viewDidLoad];
numberToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];
numberToolbar.items = [NSArray arrayWithObjects:
[[UIBarButtonItem alloc]initWithTitle:#"Cancel" style:UIBarButtonItemStyleBordered target:self action:#selector(cancelNumberPad:)],
[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
[[UIBarButtonItem alloc]initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(doneWithNumberPad:)],
nil];
}
- (IBAction)cancelNumberPad:(UITextField*)textField {
NSLog(#"The user is typing in text field %d",textField.tag);
if (textField.tag==50) {
[txtPostalCode resignFirstResponder];
txtPostalCode.text=#"";
}
else
{
[txtphoneno resignFirstResponder];
txtphoneno.text = #"";
}
}
- (IBAction)doneWithNumberPad:(UITextField*)textField {
NSLog(#"The user is typing in text field %d",textField.tag);
if (textField==txtPostalCode) {
[txtPostalCode resignFirstResponder];
}
else
{
[txtphoneno resignFirstResponder];
}
}
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
if (textField.tag==50) {
textField.inputAccessoryView = numberToolbar;
}
else if
(textField.tag==5) {
textField.inputAccessoryView = numberToolbar;
}
}
in my console report is
2014-05-03 14:06:23.614 why-Q[2000:60b] The user is typing in text field 0
how to get the correct tag in custom methods
//yourviewcontroller.h
#interface ViewController : UIViewController {
int tag;
}
//yourviewcontroller.m
- (void)viewDidLoad {
[super viewDidLoad];
tag = 0;
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField// return NO to disallow editing.
{
tag = textField.tag;
return YES;
}
- (IBAction)cancelNumberPad:(UITextField*)textField {
NSLog(#"The user is typing in text field %d",tag);
}
- (IBAction)doneWithNumberPad:(UITextField*)textField {
NSLog(#"The user is typing in text field %d",tag);
}
I'm using the following code to move to the next field using the UITextField delegate and also I'm adding a toolbar to the keyboard with the previous, next and ok buttons. The code is working fine.
Like you see the keyboard return button logic is pretty generic, using the UITextField tags, and that's good because I'm gonna use the piece of code all around. Now I will need to write the previous and next buttons logic, and I'm lost. Any ideas?
UPDATE (complete code, with some modifications, thanks to #8vius that spent some time with me in the chat to make it work):
//
// SigninViewController.m
//
#import "SigninViewController.h"
#implementation SigninViewController
#synthesize firstResponder = _firstResponder;
#synthesize toolbar;
#synthesize email;
#synthesize password;
- (void)move:(UIBarButtonItem*)sender {
NSInteger tag = self.firstResponder.tag;
if ([sender.title isEqualToString:#"Anterior"]) {
tag -= 1;
} else if ([sender.title isEqualToString:#"Próximo"]) {
tag += 1;
}
UITextField *nextTextField = (UITextField*)[self.view viewWithTag:tag];
if (nextTextField && tag > 0) {
[nextTextField becomeFirstResponder];
} else {
[self.firstResponder resignFirstResponder];
self.firstResponder = nil;
}
}
- (void)ok:(id)sender {
[self.view endEditing:YES];
self.firstResponder = nil;
}
- (void)textFieldDidBeginEditing:(UITextField*)textField {
self.firstResponder = textField;
}
- (BOOL)textFieldShouldReturn:(UITextField*)textField {
NSInteger tag = textField.tag + 1;
UITextField *nextTextField = (UITextField*)[self.view viewWithTag:tag];
if (nextTextField) {
[nextTextField becomeFirstResponder];
} else {
[textField resignFirstResponder];
self.firstResponder = nil;
}
return NO;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.email.delegate = self;
self.password.delegate = self;
if (self.toolbar == nil)
{
self.toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 44)];
UIBarButtonItem* previous = [[UIBarButtonItem alloc] initWithTitle:#"Anterior" style:UIBarButtonItemStyleBordered target:self action:#selector(move:)];
UIBarButtonItem* next = [[UIBarButtonItem alloc] initWithTitle:#"Próximo" style:UIBarButtonItemStyleBordered target:self action:#selector(move:)];
UIBarButtonItem* space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:(UIBarButtonSystemItemFlexibleSpace) target:nil action:nil];
UIBarButtonItem* ok = [[UIBarButtonItem alloc] initWithTitle:#"Ok" style:UIBarButtonItemStyleBordered target:self action:#selector(ok:)];
[self.toolbar setItems:[[NSArray alloc] initWithObjects:previous, next, space, ok, nil]];
[self.toolbar setTranslucent:YES];
[self.toolbar setTintColor:[UIColor blackColor]];
}
for (UIView* view in self.view.subviews) {
if ([view isKindOfClass:[UITextField class]]) {
[(UITextField*)view setInputAccessoryView:toolbar];
}
}
}
- (void)viewDidUnload {
self.email = nil;
self.password = nil;
[super viewDidUnload];
}
#end
It's quite simple, when you load your view you set the tag property on your text fields depending on the order you want them in, then you have to just traverse the tag element on the fields:
- (void)toggleTextfield:(UIBarButtonItem *)sender {
NSInteger nextTag = self.firstResponder.tag;
if ([sender.title isEqualToString:#"Previous"] && nextTag > 1) {
nextTag -= 1
} else if ([sender.title isEqualToString:#"Next"]) {
nextTag += 1;
}
UITextField *nextTextField = (UITextField *)[self.view viewWithTag:nextTag];
if (nextTextField) {
[nextTextField becomeFirstResponder];
}
}
And keep track of who is the first responder:
-(void)textFieldDidBeginEditing:(UITextField *)textField {
self.firstResponder = textField;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
self.firstResponder = nil;
return YES;
}
And when you load your view, you bind the buttons to the toggle action:
UIBarButtonItem *previousButton = [[UIBarButtonItem alloc] initWithTitle:#"Previous"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(toggleTextfield:)];
UIBarButtonItem *nextButton = [[UIBarButtonItem alloc] initWithTitle:#"Next"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(toggleTextfield:)];
In my case, for instance, I set up my text fields inside a table view, so in my cellForRowAtIndexPath method I set the tag property to be the row of the indexPath.
EDIT: You have to set the firstResponder property for it to work.
In your .h file:
#property UIView *firstResponder
In your .m file:
#synthesize firstResponder = _firstResponder;