Add a bunch of controls dynamically to screen in iOS - ios

I am working on a screen where user selects an option from drop-down. Based on this selection he adds a bunch of controls to screen. My drop-down is at the bottom-right corner of the screen. It takes up 20-25% of screen space at the bottom. In the remaining 75% screen at the bottom i need to add 9 labels,6 UItext fields ,2 drop-downs and 2 buttons. I am attaching a markup here.
My question is: in ASP.NET, I have a repeater which has all the above controls. In one of the buttons named "Add More". If I click that button, it adds the same repeater at the bottom of the current one. Do we have anything like that in iOS? Like a repeater which has a bunch of controls and click add and that exact repeater is added at the bottom and so-on and so forth. If any ideas/new ideas based on my explanation pop-up then please let me know. Thanks.
The link
http://dl.dropbox.com/u/40597849/mockup2.png
So, the big rectangle to the right containing 8 labels, textboxes, drop-downs and the 2 buttons below it(one is named as "Add More") should be added again when user clicks on Add More. Please ask me if you need more information.
ITMCustomView *cView = [[ITMCustomView alloc] initWithFrame:frame];
cView.delegate =self;
CGPoint scrollPoint = CGPointMake(0.0, (frame.origin.y/400)*400);
[self.scrollView setContentOffset:scrollPoint animated:YES];
[self.scrollView addSubview:cView];
Initially the very first custom view i add, i add it with this frame size (187, 585, 350, 21); . Next whenever i hit add more i call this delegate
[self.delegate addNewSize:CGRectMake(187,self.y+ 400 , 400, 400)];
This calls the above 5 lines of code and makes a new custom view and adds it to scroll view. I store the self.y as the y value of whatever frame currently being built. So how do i make my scroll view move up and down freely. The screen shows the custom view as they are added but doesnt allow me to go up anymore. I wanted to suppose add the custom view 5 times and i added 4 i just want to scroll up , see i added 4 scroll down and just add 1 more custom view and do other processing with it. But my scroll view is non-functional and its stuck at the just added custom view disabling me to scroll up. If you need more information, please ask me. Thanks.

Use a custom view that contains all your views.
1.) Make a custom class myView which subclasses UIView.
2.) Add all the controls you need in that view class.
3.) include myView in your main view.
4.) initiate as many myView as you like and add them to your main view.
I hope that is clear enough to get you going.
Update: As to elaborate more on the comment bgoers made.
When you create a new class myView sub-classing UIView you get an empty sheet. This sheet will have the frame that you specify either in the class or when you initiate (up to you). Within that frame (myView.h and myView.m in initWithFrame), you can add subViews like buttons or labels. Those subviews will placed relative to the sheet myView.
For example, your draw up is a custom view with all the controls. I can have another one looking exactly like it by simply initiating another custom view without adding more subviews. All I need to do is move the second custom view to where I would like, all the subviews will follow.
I encourage you to read up on how to subclass and how that works in iOS. It is very simple once you get the hang of it.

Related

How to bring subview to front in interface builder without changing its position

I want to ask a simple question how can I temporary bring a subview to front to view its element without changing its position by dragging and dropping. The problem i face all the time is i forgot to put the views back to there position and that causes lot of trouble specially if you are working on the view that have large number of subviews.
Question : Is there any shortcut or any functionality that can show the view temporary without dragging, changing its frame or making any changes in its hierarchy.
For a view controller like this :-
FYI, for those who are wondering, the view closest to the bottom of the list (on the left) will show in the front. So in the case below, view 'a' will be in front of 'b' and 'b' will be in front of 'c'
XIB:
If you need your views to be readily accessible for viewing/editing without having to rearrange them, I would actually recommend breaking them out into their own view and then stitching them together in the correct order in your code. This will ensure that all elements will be put in the proper order and will always be easily editable. Something like this:
And then in your code, in somewhere like viewDidLoad:
[self.view addSubview:view2];
[self.view addSubview:view3];

How do I make the elements in my UIView responsive?

My goal is to create an alert that has three text fields, one taller than the others, and an image that, when tapped, allows the user to choose a picture to replace a set default one.
After unsuccessfully searching for a library for this, I decided to create my own alert by placing a UIView off the screen and, when prompted by a button, would zoom onto the screen; it consists of all the elements I require.
When I run the application, the view pops up correctly, but none of the elements on the view are responding to touch. I've checked that isUserInteractionEnabled for everything is turned on.
What's also odd is that when I keep the view on the screen (instead of placing it some distance away on Storyboard), all the elements work fine.
I'm assuming it had something to do with the animation. I tested it with a fade in instead of a displacement, and the result was the same - the elements were unresponsive.
In order for your elements to be responsive you have to link the action of you clicking them to your view's code. You can do this in a non-programmatic manner by ctrl-clicking your element on story-views and then dragging to the view controller. Then choose action instead of outlet, and choose when the action you want will be triggered (bottom part). Then insert your code in the viewController.
So I figured it out. I used the debug view hierarchy and saw that the alert was behind the elements behind it, even though it was still being shown (for some reason). I changed the zIndex of the UIView and it worked!

How can I bring a view in front of another view, in Swift?

Below are how my views are organized in IB, top->bottom when the app is started.
The user can do something to make "Category Table View Header" temporarily expand over "Name View" - however once doing so, the .TouchDown action assigned to "Category Table View Header" no longer works wherever it overlaps with "Name View" (i.e., the user can tap the header anywhere it doesn't overlap with name view and it still works).
I know that may be confusing, so I drew out some boxes. On the left is the original, right is after user action - problem is on the right the action on the red box only works if the user taps the bottom half, not the top half.
My guess is its because the header is lower in the view hierarchy than the name view, but it would be hard for me to change that without messing around with a bunch of constraints.
I also tried setting nameView.hidden = true, but that doesn't work.
If you want to bring a subview to the front, you can use:
SWIFT 4 + UPDATE
self.view.bringSubviewToFront(yourView)
SWIFT 3 UPDATE
self.view.bringSubview(toFront: yourView)
Send view to back:-
SWIFT 4+ UPDATE
self.view.sendSubviewToBack(yourView)
SWIFT 3 UPDATE
self.view.sendSubview(toBack: yourView)
SWIFT 4+ UPDATE - INSERT VIEW ON SPECIFIC LOCATION IN THE STACK
parentView.insertSubview(yourView, belowSubview: requiredViewOnStack)
parentView.insertSubview(yourView, aboveSubview: requiredViewOnStack)
Swift 5.1+
UIKit draws views back to front, which means that views higher up the stack are drawn on top of those lower down. If you want to bring a subview to the front, there's a method just for you: bringSubviewToFront(). Here's an example:
parentView.bringSubviewToFront(childView)
This method can also be used to bring any subview to the front, even if you're not sure where it is:
childView.superview?.bringSubviewToFront(childView)
In Swift 5
To bring a subview to front
self.view.bringSubviewToFront(yourView)
To send a subview to back
self.view.sendSubviewToBack(yourView)
You can take a control over the order of subviews using methods: bringSubviewToFront and sendSubviewToBack from the superview.
You can access all the subviews contained by superview using self.view.subview array.
The method has been updated since swift 3
What has worked for me and hopefully for you is using :
YourView.bringSubview(toFront: yourelementA)
YourView.bringSubview(toFront: yourelementB)
Alternatively you could use the following to send the object that is in the front:
YourView.sendSubview(toBack: yourelementC)
I hope this helps
Swift 5.4
views in UIKit are drawn from the back towards the front (like adding icing onto a cake). This means that the new views will be placed on top/over the previously placed views. (e.g. Icing is the new view and the base of the cake being the old view.
You can use the following to manipulate the views Z-position using,
Forward
parent.bringSubviewToFront(child)
Backward
parent.sendSubviewToBack(child)
bringSubViewToFront did not work in my case, Take a look
As I wanted this notification count comes before image, bringSubViewToFront did not work, So I just drag this label below to stack view of my imgae and bottom label, it worked for me.
I hope this will work for all

Single Tapping not being detected on dynamically created uibuttons

It was necessary to create a subclass of UIButton, lets call it subButton. These subButtons are instantiated one by one and dynamically added to an UIScrollView object.
Unfortunately the subButtons aren't reacting as expected. After scrolling away from the first dynamic generated subButtons and then returning back to them. They loose their reactivity to single tapping. I can not explain this behaviour. Can somebody explain why its behaving this way?
Many thanks.
Source code
self.subButton = [[SubButton alloc]initWithFrame:CGRectMake(69.5, y, 201, 114)];
[self.subButton setBackgroundColor:[UIColor blueColor]];
self.subButton.imageData = imageData;
self.subButton.videoPath = videoPath;
self.subButton.vidIndex = _indexVideo +1;
[self.subButton drawVidPreview];
[self.subButton setTag:(_indexVideo +1)];
[self.subButton addTarget:self action:#selector(handleSingleTap:) forControlEvents:UIControlEventTouchUpInside];
[self.videoScroll addSubview:self.subButton];
[_videoPreviews addObject:self.subButton];
The subButton method drawVidPreview adds some subviews to itself.
Do the buttons not respond at all, or just not to single-tap? That might help us help you.
If they don't respond at all, I would check your view hierarchy to make sure no other view (perhaps invisible) are sitting above your buttons. Or, perhaps are the buttons not being added to the parent view you think?
Please make sure you are not adding the same UIGestureRecognizer instance to all of the UIButtons, instead for each UIButton you need to add a separate instance, however all gesture instance can point to the same target.
At last, i could solve the problem. The reason why the first subButtons did not respond to single tapping with UIControlEventTouchDown is because the uiScrollview content offset was set to a negative y value. This first of all was not necessary and was done out of pure laziness. I corrected it by giving it a positive value.
So my conclusion is, if you do not set the content offset or content size of the scrollView correctly, some dynamically added buttons to the scrollView might not respond to tapping appropriately. This is even the case if all Buttons are placed completely on a uiScrollview object.
This I could confirm by playing around with the content size of the uiScrollview instance too. I changed size of the y value of uiScrollviews instance just by few points and then some of the last buttons did not respond to tapping anymore.
Just by increasing the content size of the y value again, made the buttons responsive again.

how to redraw custom view from the controller in ios objective-c

I have a custom view with 3 buttons taking full width.
I import the class to my controller where I want to hide on button (menuBtn) and make one of the one of the other buttons (searchbarBtn) be bigger to fill the empty space by doing:
`self.topMenuView.searchbarBtn.frame = CGRectMake(self.topMenuView.searchbarBtn.frame.origin.x, self.topMenuView.searchbarBtn.frame.origin.x, self.topMenuView.searchbarBtn.frame.size.width + self.topMenuView.menuBtn.frame.size.width , self.topMenuView.searchbarBtn.frame.size.height);`
I do this in viewWillLayoutSubviews (have also tried in viewWillAppear) and I call the
[self.topMenuView.searchbarBtn setNeedsDisplay];
but nothings happens.
I
The button's layout properties override your frame settings, since by definition viewWillLayoutSubvies is called before the layout pass. You should just set
self.topMenuView.menuBtn.hidden = YES;
and use autolayout constraints (in the interface builder or in the code) between menuBtn, searchbarBtn and topMenuView to make sure your buttons grow as needed.
As a general rule, we should strive to create interface so that views will correctly position themselves provided their inner state is correctly set and correct constraints are formed, without explicit corrections on our part.

Resources