How do I create and add multiple UITextField to my controller?
I can create one, like this:
UITextField *tf = [[UITextField alloc] initWithFrame:CGRectMake(5,5,100,25)];
tf.borderStyle = UITextBorderStyleRoundedRect;
[tf setReturnKeyType:UIReturnKeyDefault];
[tf setEnablesReturnKeyAutomatically:YES];
[tf setDelegate:self];
[self.view addSubview:tf]
But do I need to do that for each UITextField?
Whats the best approach to template UI Controls?
Put it in a loop, offset each text field's Y position and tag each text field:
for (int i = ; i < numberOfTextFieldsNeeded; i++) {
UITextField *tf = [[UITextField alloc] initWithFrame:CGRectMake(5, 5 + 35 * i ,100,25)]; // 10 px padding between each view
tf.tag = i + 1; // tag it for future reference (+1 because tag is 0 by default which might create problems)
tf.borderStyle = UITextBorderStyleRoundedRect;
[tf setReturnKeyType:UIReturnKeyDefault];
[tf setEnablesReturnKeyAutomatically:YES];
[tf setDelegate:self];
[self.view addSubview:tf]
// don't forget to do [tf release]; if not using ARC
}
Then in delegate methods perform actions based on tag of the textField that called each delegate method. For example to switch to next text view when user taps return key:
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
[textField resignFirstResponder];
UITextField *nextTextField = [self.view viewWithTag:textField.tag + 1];
[nextTextField becomeFirstResponder];
}
Keep in mind that sending messages to nil in Objective-C will not crash so it will be perfectly fine when user taps return key in last text field as UITextField *nextTextField = [self.view viewWithTag:textField.tag + 1]; will return nil, and calling becomeFirstResponder on nil will do nothing. But you can check if nextTextField is nil and do something else then, whatever you like.
You can use interface builder to create a view (bigger than the size that the screen fits) and programmatically add it to a scrollView.
This is in my opinion the best approach.
Related
I have a UITextField and I want it has a maximum text length of 20. So I let self(the current view controller) agree to <UITextFieldDelegate> and set self as the text field's delegate, and use the following method to set a maximum length:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField == self.nickNameTextField)
{
if (textField.text.length > 20)
return NO;
}
return YES;
}
However when I insert a breakpoint in this function I found that this function wasn't called when I typed in any words, much less when the text's length exceeds 20. Can somebody tell me why?
You probably haven't linked your textfield with the delegate
Right click on textField which you want to have delegated and drag the textField on the viewcontroller and drop to select the delegate.
I show you steps and screenshot for connecting textField and delegate with XIB or Storyboard.
In storyboard
STEP 1: Click the TextField
STEP 2: Drag the TextField to ViewController
STEP 3: Click "control+mouse" on TextField to ViewController.h and line shows
STEP 4:Now Box will appear and give the TextField Name
STEP 5:Right Click the TextField in ViewController
STEP 6:Hook Up the Delegate to ViewController
If you want to programmatically create the textField
UITextField *txtfldMaxLength = [[UITextField alloc] initWithFrame:CGRectMake(30, 100, 250, 50)];
txtfldMaxLength.borderStyle = UITextBorderStyleRoundedRect;
txtfldMaxLength.textColor = [UIColor blackColor];
txtfldMaxLength.backgroundColor = [UIColor clearColor];
txtfldMaxLength.font = [UIFont systemFontOfSize:17];
txtfldMaxLength.placeholder = #"enter something";
txtfldMaxLength.autocorrectionType = UITextAutocorrectionTypeNo;
txtfldMaxLength.keyboardType = UIKeyboardTypeDefault;
txtfldMaxLength.returnKeyType = UIReturnKeyDone;
txtfldMaxLength.clearButtonMode = UITextFieldViewModeWhileEditing;
txtfldMaxLength.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
txtfldMaxLength.delegate = self;
[self.view addSubview:txtfldMaxLength];
Well I've figured out the problem. I use this grammar to instantiate a UITextField:
self.nickNameTextField.delegate = self;
self.nickNameTextField = ({
UITextField *textField = [UITextField new];
textField.placeholder = [BBTCurrentUserManager sharedCurrentUserManager].currentUser.nickName;
textField.textAlignment = NSTextAlignmentLeft;
textField.backgroundColor = [UIColor lightGrayColor];
textField;
});
Originally I set the textField's delegate outside the braces(like the code above). But when I move self.nickNameTextField.delegate = self;inside the braces then it worked. However I have no idea about why this happened, can someone tell me why?
I am using Xcode 6 and doing a small project on iOS 8, and I need to render some text onto the View.
My method is to create a UITextField on a UIView and as long as people type onit, the app redraw the View:
- (void)viewDidLoad {
[super viewDidLoad];
self.renderTextView.textToRender = #"Please type something…";
UITextField* textField = [[UITextField alloc] initWithFrame:self.renderTextView.frame];
textField.opaque = NO;
[self.renderTextView addSubview:textField];
[textField addTarget:self action:#selector(updateLabelAndRefresh:) forControlEvents:UIControlEventEditingChanged];
}
- (void) updateLabelAndRefresh: (id)sender{
self.renderTextView.textToRender = #"Hello World";
// if text's length > 0 …
if (self.textField.text.length > 0) {
self.renderTextView.textToRender = self.textField.text;
}
[self.renderTextView setNeedsDisplay];
}
But the problem is: no matter how I try, I can not get the actual text I type on my phone. and the console showed me that the text is null. I kept googling it but I stil can not work it out.
Do you guys have any solution? Thank you ;)
In below some error is there, give a look.
- (void)viewDidLoad {
[super viewDidLoad];
//Here textField is local variable
UITextField* textField = [[UITextField alloc] initWithFrame:self.renderTextView.frame];
textField.opaque = NO;
}
- (void) updateLabelAndRefresh: (id)sender{
self.renderTextView.textToRender = #"Hello World";
// if text's length > 0 …
if (self.textField.text.length > 0) { //Then how come u getting self.textField here and using it as global one.
//So you won't get access to that locally defined textField in viewDidLoad method.
self.renderTextView.textToRender = self.textField.text;
}
}
Please check your code and update me about it.
I have a weird issue with a UIStepper (and it's accompanying UITextField)
Consider this code snippet:
#interface LTRPageTracker : UIView <UITextFieldDelegate>
{
UIStepper* page_move;
UITextField* page_no_view;
}
-(void) nextOrPrevPage:(id)sender forEvent:(UIControlEvents) event;
#implementation LTRPageTracker
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
CGRect stepperFrame, pageNoframe;
pageNoframe.origin = frame.origin;
pageNoframe.size.height = frame.size.height;
pageNoframe.size.width = frame.size.width/2;
stepperFrame.origin.x = pageNoframe.origin.x + pageNoframe.size.width +1;
stepperFrame.origin.y = frame.origin.y;
stepperFrame.size = pageNoframe.size;
page_move = [[UIStepper alloc] initWithFrame:stepperFrame];
[page_move setMinimumValue:0];
[page_move setValue:7];
page_move.maximumValue =1000;
[page_move addTarget:self action:#selector(nextOrPrevPage:forEvent:) forControlEvents:UIControlEventValueChanged];
page_no_view = [[UITextField alloc] initWithFrame:pageNoframe];
page_no_view.delegate = self;
page_no_view.backgroundColor = [UIColor redColor];
[self addSubview:page_no_view];
[self addSubview:page_move];
[page_move sendActionsForControlEvents:UIControlEventValueChanged];
[page_move setEnabled:YES];
}
return self;
}
-(void) nextOrPrevPage:(id) sender forEvent:(UIControlEvents) event {
//assert(sender == page_move);
NSLog(#"Event is %x", event);
page_no_view.text = [[NSNumber numberWithDouble: page_move.value] stringValue];
}
I have added this View to the navigation bar.
And I can decrement the value of the UIStepper but no increment it (the event will simply not get triggered for increment but will do so decrement).
WHY?
Using iOS 7, running on simulator.
Whenever you have a problem with a UI element not responding, the first thing you should check is whether it (or part of it) is outside the bounds of its superview (the part that's out of the bounds will not respond). An easy way to do this, is to give the superview a background color. In the init method assign a background color to self, and see what that shows you. I'm betting that you'll see that the right side of the stepper is not within its superview, so you'll need to make that view bigger, or change the stepper's position within that view.
If you make the view's frame 150x30, and change these two lines in the view's init method, I think it should work ok for a number as large as 1000:
pageNoframe.size.width = frame.size.width/4; // changed 2 to 4
stepperFrame.origin.x = pageNoframe.origin.x + pageNoframe.size.width+20; // changed 1 to 20
I have two buttons for adding and deleting the textfields. Adding works fine but when I click on delete it deletes only the last added textfield. Here are my two methods:
-(void)addTextField {
keyTextField = [[UITextField alloc] initWithFrame:CGRectMake(10, yAxisDistance, 150, 30)];
keyTextField.borderStyle = UITextBorderStyleRoundedRect;
keyTextField.placeholder = #"Key Value";
keyTextField.delegate = self;
[self.view addSubview:keyTextField];
valueTextField = [[UITextField alloc] initWithFrame:CGRectMake(165, yAxisDistance, 150, 30)];
valueTextField.borderStyle = UITextBorderStyleRoundedRect;
valueTextField.placeholder = #"Value";
valueTextField.delegate = self;
[self.view addSubview:valueTextField];
yAxisDistance = yAxisDistance+35;
}
-(void)deleteTextField {
[keyTextField removeFromSuperview];
[valueTextField removeFromSuperview];
yAxisDistance = yAxisDistance-35;
}
I know it's an small issue but I am very new to this field so kindly help.
Use this code for remove specific textfield from UIView. But First you have to set tag of every UITextField in view when you create or add it in view.
for ( UITextField* textField in view.subviews )
{
if(textField.tag== 1)
{
[textField removeFromSuperview];
}
}
I think the problem lies with the outlet. Can you check the following:
Open the outlets that are connected to the textifeld in the IB. There should be gray dots inside circles on the left side of the editor. Are they seem correct for both text fields?
Setup a breakpoint inside deleteTextField method and check the two textfields. Verify that both properties are not nil.
PS: You don't need to add tags to your view, using properties is perfectly fine and even better in my opinion. The reason for your problem is something else. Also, you do not need to removeFromSuperview, you can also setHidden:YES.
Sorry that time I was not understand your problem...
I done with this:
Declare one
NSMutableArray *allTextfieldArray;
and initialise in
viewdidload
method..
now do:
-(void)addTextField {
keyTextField = [[UITextField alloc] initWithFrame:CGRectMake(10, yAxisDistance, 150, 30)];
keyTextField.borderStyle = UITextBorderStyleRoundedRect;
keyTextField.placeholder = #"Key Value";
keyTextField.delegate = self;
[self.view addSubview:keyTextField];
valueTextField = [[UITextField alloc] initWithFrame:CGRectMake(165, yAxisDistance, 150, 30)];
valueTextField.borderStyle = UITextBorderStyleRoundedRect;
valueTextField.placeholder = #"Value";
valueTextField.delegate = self;
[self.view addSubview:valueTextField];
yAxisDistance = yAxisDistance+35;
[allTextfieldArray addObject:keyTextField];
[allTextfieldArray addObject:valueTextField];
}
if ([allTextfieldArray count]>0) {
UITextField *txtField = [allTextfieldArray lastObject];
[allTextfieldArray removeLastObject];
[txtField removeFromSuperview];
txtField = nil;
UITextField *txtField2 = [allTextfieldArray lastObject];
[allTextfieldArray removeLastObject];
[txtField2 removeFromSuperview];
txtField2 = nil;
yAxisDistance = yAxisDistance-35;
}
you store the last textField in your variables keyTextField and valueTextField. So when you call your deleteTextField the last both will be deleted. you must track which textFileds you want exactly to delete.
for example you could give all your textFields a tag number when you create them:
first create an int as counter:
#implementation YourClass {
int tagcounter;
}
in init method set your counter:
tagcounter = 0;
in your addTextField:
keyTextField.tag = tagcounter++;
valueTextField.tag = tagcounter++;
when the delete button is tapped, you must know the textfield tags and pass them to your deleteTextField method. There you could do something like:
-(void)deleteTextFieldWithTag:(int)tagnumber {
for (UIView *view in [self.view subviews])
{
if ([view isKindOfClass:[UITextField class]])
{
if (view.tag == tagnumber || view.tag == tagnumber+1) {
[view removeFromSuperview];
}
}
}
So I have a view controller that I created completely programmatically, I didn't use storyboard or a nib file. In it, I have a button, addNew that when pressed, it creates two UITextfields, one for a number, the other for a product, and places it where the "Add New"button was, and moves the button down. Instead of explaining it, here's some code :
-(IBAction)addProduct:(id)sender{
self.numOfProducts += 1;
//To keep track of how many times the button was pressed
NSLog(#"New Product Added");
NSLog(#"# of products: %d", self.numOfMaterials);
//The number textfield
self.numOfProduct = [[UITextField alloc]initWithFrame:CGRectMake(self.addNew.frame.origin.x, self.addNew.frame.origin.y, 70.0, 30.0)];
self.numOfProduct.delegate = self;
self.numOfProduct.textAlignment = NSTextAlignmentCenter;
[self.numOfProduct setPlaceholder:#"#"];
self.numOfProduct.borderStyle = UITextBorderStyleBezel;
self.numOfProduct.keyboardType = UIKeyboardTypeNumberPad;
//Added doneToolbar to close keypad
UIToolbar *doneToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];
doneToolbar.barStyle = UIBarStyleBlackTranslucent;
[doneToolbar setItems:[NSArray arrayWithObjects:
[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(doneNumPad)],
nil]];
[doneToolbar sizeToFit];
self.numOfMaterialNeeded.inputAccessoryView = doneToolbar;
//Product text field, places it next to numOfProduct text field
self.product = [[UITextField alloc]initWithFrame:CGRectMake(self.numOfProduct.frame.origin.x + 80, self.numOfProduct.frame.origin.y, 200.0, 30.0)];
self.product.delegate = self;
self.product.textAlignment = NSTextAlignmentCenter;
[self.product setPlaceholder:#"Product"];
self.product.borderStyle = UITextBorderStyleBezel;
self.product.autocapitalizationType = UITextAutocorrectionTypeNo;
self.product.keyboardType = UIKeyboardTypeDefault;
self.product.returnKeyType = UIReturnKeyDone;
self.product.clearButtonMode = UITextFieldViewModeWhileEditing;
//Places addNew below the newly created text fields
[self.addNew setFrame:CGRectMake(self.addNewMaterial.frame.origin.x, self.addNewMaterial.frame.origin.y + (self.addNewMaterial.frame.size.height + 10), self.addNewMaterial.frame.size.width, self.addNewMaterial.frame.size.height)];
// add text fields to the UIScrollView
[self.scrollView addSubview:self.numOfMaterialNeeded];
[self.scrollView addSubview:self.material];
}
//Called when done button is pressed for numOfProduct text field
-(void)doneNumPad{
[self.numOfProduct resignFirstResponder];
[self.product becomeFirstResponder];
//Save num in an array
[self.saveNumOfProduct addObject:self.numOfProduct.text];
for (int i = 0; i < [self.saveNumOfProduct count]; i++) {
NSLog(#"%# of ___", [self.saveNumOfProduct objectAtIndex:i]);
}
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
//Save product in an array
if (textField == self.product) { //
[self.saveNameOfProduct addObject:self.product.text];
}
return YES;
}
The code is working well and fine, BUT, I realized, if I have the self.numOfProduct textField as the first responder, and instead of pressing "Done", I press the self.product textField right away, it won't save the self.numOfProduct.text, same with the self.product.text, it won't save unless I press "Done". How can I do it so that I can efficiently save the text from the textfield property, no matter how many textfields I have on the screen? Is it possible? I appreciate any feedback! And if I haven't been clear enough, lemme know and I'll clear up whatever needs clearing!
I've found the answer! A lot easier than I thought it would be, I completely forgot about the (void)textFieldDidEndEditing:(UITextField *)textField function. All I had to do was save the text in that function, and it saves every time the textfield becomes the responder to another field OR when I press the done button.