IPad Simple Form with Flexible Space - iphone

Im creating an app for an internal process where our trainers will go out to clients and fill in a survey of the customer after the fact.
I want to create a flexible space with in the view. Example if they click a checkbox that the Customer is not happy than text fields will be shown to enter more information which will need to dynamically push all fields under it down to accomodate the new fields. If the user is happy no fields need to appear and no dynamic shifting is necessary.
Just wondering if anyone has done this before and if there is a clean way to execute it.

I don't think there is a control that will do this.
But it should not be that hard. This code is not tested but something like this
//views needs to be ordered in the subview list by y position
//can be in in uibuilder or on awakefrom nib..
-(void) addTextFieldAfterView:(UIView*) selectedView
{
CGRect f = CGRectMake(selectedView.origin.x,
selectedView.origin.y+5+selectedView.size.height,
selectedView.size.width,
150);
UITextField *tf = [[UITextField alloc] initWithFrame:f];
[self insertSubview:tf belowSubview:selectedView];
int start = [self.subviews indexOfObject:tf];
//move everything down
for(int i =start; i < [self.subviews count];i++)
{
UIView* v = [self.subviews objectAtIndex:i];
v.frame = CGRectMake(v.origin.x,
v.origin.y+150,
v.size.width,
v.size.height);
}
}

I like using UITableView for forms. This is what a lot of the forms in the Settings app uses. It's fairly simple to turn sections on and off -- just respond to the messages with the right number of sections and then fill them in as requested.

Related

how to add multiple labels to a view programmatically without worrying about its Y position?

I have a situation here, I want to add user name with a check button in a view, looks simple :)...
Question is I may have single or multiple user, so I need to add it through code only, I want to add all names like a ladder with its corresponding check button.
What is the best way to do that?
I have tried by adding labels for each user.. While adding I wanted to set its top position one by one to make it aligned properly.. Do I have to calculate top like this? Any easiest way is there.. Like how they are doing in Android (relative Layout).
thanks
You can create array of usernames and use following code.
This is test code for your reference.
NSMutableArray *arr = [[NSMutableArray alloc] init];
[arr addObject:#"1"];
[arr addObject:#"2"];
[arr addObject:#"3"];
[arr addObject:#"4"];
[arr addObject:#"15"];
Now looping:
for (int i = 0; i<[arr count]; i++) {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 10*10*i, 100, 40)];
label.text = [arr objectAtIndex:i]; //usernames from array
[self.view addSubview:label];
}
The Objective-C equivalent of relativelayout is Cocoa Auto Layout
I would use a UItableView with a custom cell. The cell contains your input fields. This way you can have as many inputs as you like and they will always be layed out in order in the same way, and you don't need to write any funky code. You also get scrolling and memory management for free.

Display JSON as List in ViewController (Not in TableView)

I am producing a JSON string that I need to parse out and display onto the page. My JSON string outputs information about the contents of a CD like this:
[{"song_name":"Song 1","artist":"John","price":"$1"},
{"song_name":"Song 2","artist":"Anna","price":"$2"},
{"song_name":"Song 3","artist":"Ryan","price":"$3"}]
I would like to display the contents in my viewController in a list format displaying the song_name, artist, and price. I do not want to use a tableView to display this information, but would rather just have a list displayed. How might I go about doing this? I would assume that I need to use NSJSONSerialization, but have only used that for a tableView in the past. Thank you!
In addition to other answers, you can use only one label, just create NSMutableString (for dynamicly adding tracks info) with #"\n" between tracks info, pass it to label.text and set UILabel's property numberOfLines to 0
Follow these steps:
Parse the JSON and store the key-value pair(NSDictionary of CDs) in an NSArray (say infoArray)
Add a UIScrollview as a subview on your viewController's view.
Allocate UILabels dynamically, depending on infoArray count. Looking at your data I believe you can initialize labels with static frames i.e your y can remain static.
Add the text from the infoArray on this label.
Still, I would suggest use UITableView only. It is much simpler and a better approach
You make an array of dictionaries using NSJSONSerialization indeed, then you parse this array one by one and create a view of every dictionary. You're probably best of using a method for this:
-(UIView *) listView: (NSString *)songName andArtist:(NSString *)artist andPrice:(NSString *)price andIndex:(int)viewIndex {
//create your view here and do anything you want
UIView *subView = [[UIView alloc] init] autoRelease];
subView.frame = CGRectMake(0, viewIndex * 70, self.view.frame.width, 70);
//add labels and other stuff
// return the view
return subView;
}
The you add it to the current view by setting different Y values so they appear underneath each other by using the viewIndex of the former method... So if you have an array it goes something like this:
for (int i = 0; i < [array count]; i++) {
NSDictionary *dict = [array objectAtIndex:i];
NSString *songName = [dict valueForKey:#"song_name"];
NSString *artist = [dict valueForKey:#"artist"];
NSString *price = [dict valueForKey:#"price"];
UIView *tempView = [self listView:songName andArtist:artist andPrice:price andIndex:i];
[self.view addSubView:tempView];
}
You have to add it all to a scrollview otherwise you will run into the problem of to many rows on the page. Google for UIScrollView if you don't know how.
But I would recommend against this approach.. Tableviews are there with a reason. They are made for this stuff. Because the also provide for scrolling, drawing and refreshing. If you can, use them!

XCode - Dynamically created labels, when i change the text it changes it for the last one only

So i have a bunch of dynamically loaded labels..
Each of them has the same name because there is no telling how many there will be..
I have another method (not the one that created the labels) changing the text for one of the labels, but when i run it only the last label that was created will change..
I need it to change the one that has a certain tag or something..
Help is much appreciated, this website is yet to let me down.
self.myLabel cannot be connected to multiple labels, so it will contain the reference of last created label, you will have to create new label every time, and you can't track them by class properties, you have to access label by their tag.
you can set tag for each label, below is sample code,
for(int i=0; i< numberOfLabels; i++)
{
UILabel *label = [[UILabel alloc] init];
label.tag = i; // do not use tag 0 here.. u can use i+1, or i+100.. something like this.
[self.view addSubview:label];
}
to access labels,
UILabel *label = (UILabel*)[self.view viewWithTag: labelTag];
Okay since you dont have any code to show i guess i have to speculate.
What i understood is that you are creating Dynamic UILabels in ur code and you want to access them. Since you have same name for all the UILabels you might me loosing the previous UILabel when every time you create a new UILabel. So in order to keep track of how many UILabel you created you must add them in an Array. Declare an NSMutableArray in your viewController.h file and make sure in the viewDidLoad u allocate it like
arrForLabels = [[NSMutableArray alloc]init];
Since it is an NSMutableArray you can add object to it.
So when u create a UILabel make sure you add the same UILabel in the Array as well
for Instance
[arrForLabels addObject:yourLabel];
you can try to NSLog your Array to see its content.
Now all youu got to do is to Create a weak link like that
UILabel *tempLabel = [arrForLabels objectAtIndex:1];
now tempLabel will be the UILabel to change text
tempLabel.text = #"My New Text";
It will work fine.
Feel free to ask for any issues in it.

How to remove everything fron the superView and not just the last item?

In my app i had to draw certain checkboxes at a same time and i used a single function to add all of them. Now when a user clicks one of them all of those checkboxes should get removed from the superview and currently its just removing the last one. Also i have issue to recognize those checkboxes like which one is clicked. i know it should be done through Tag property but don't know how exactly it should be implemented.
Any suggestions.
Removing all subviews
int numberOfSubviews = [[yourView subviews] count];
for(int i=0;i<numberOfSubviews-1;i++
{
[[youView subviews]objectAtIndex:i]removeFromSuperView];
}
//this will leave check box that you added at last.... for first one to remain loop from 1 to numberOfSubviews....
Using tag property...
when you are creating checkbox objects use
checkBoxObject.tag = i;
//I am considering i as looop count which you are using in a loop
to add checkboxes.
then whenever you need a object of checkbox
[yourViewonwhichYouAddedCheckBox viewWithTag:<your tag >];
Thanks
For identifying a "checkbox" or better said any view within an action-method:
- (void)someActionHandler:(id)sender
{
UIView *actionOriginView = (UIView *)sender;
NSLog(#"this action came from view:%d", actionOriginView.tag);
}
For assigning the tag, you may use the IB or within your code, while instantiating;
UIView *myFunkyView = [[UIView alloc] initWithFrame:CGRectZero];
myFunkyView.tag = 1337;
For removing a bunch of views from your superview - lets assume their tag is set to 10 - 15;
for (int i=10;i <= 15;i++)
{
UIView *childView = [superview viewWithTag:i];
[childView removeFromSuperview];
}

UITextField Validation visual feedback

i have a uiTextField that i am validating input on, when i have invalid input what are some appropriate ways to show that the input is invalid? is there any built in mechanism for showing invalid input states?
It's pretty easy to add an 'warning' image to the left-hand side of a UITextField to indicate that the field needs a value.
Try this:
UITextField* field = .... your text field ...
if ( fails_validation ) {
field.leftViewMode = UITextFieldViewModeAlways;
UIImageView* imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 32, 32)];
imageView.image = [UIImage imageNamed:#"warning.png"];
imageView.contentMode = UIViewContentModeScaleAspectFit;
field.leftView = imageView;
} else {
field.leftViewMode = UITextFieldViewModeNever;
field.leftView = nil;
}
The best two options I've found so far are TextFieldValidator and US2FormValidator. With the caveat that I have only used the former, here's my take on each.
TextFieldValidator
&uparrow; Simple (just one class!)
&uparrow; Offers default UI with additional customization possible
&uparrow; Handles multiple validations on a single field
&downarrow; Doesn't handle text views
&downarrow; Slightly awkward name…ValidatedTextField, for example, would be more accurate :)
US2FormValidator
&uparrow; Handles text fields and text views
&uparrow; Importable as a framework, including CocoaPods support
&uparrow; Handles multiple validations on a single field
&downarrow; No default UI
If you just need something implemented quickly, TextFieldValidator may be all you need. If you must have validated UITextViews, US2FormValidator is the way to go.
Have a look at Managing Overlay Views section in UITextField docs
Put a check mark to the right of the UITextField when correct, Else put an X to the right of it. to make it look smooth: fade it using an animation