Add a ScrollView Manually or Programmatically - ios

I have an existing view with several elements, I was thinking of how to include a scrollview to contain all the existing elements without having to go through redesigning one by one the elements,
My objective is, that when my orientation changes to landscape, the elements behind can be scrollable specially when a keyboard is currently displayed.
Can this be done manually or programmatically, and how? Or is there any best approach for this type of scenario's?
*Edit (for clarity)
My apologies for the lack of clarity with the initial question;
I have a view with 3 Textfield, A button and 2 switch, Initially my app only supported the "Portrait" orientation, however, recently I have decided to add "Landscape" orientation support, I already did this. Now my problem is when I'm on landscape the view elements gets covered by the keyboard (specifically). So I was thinking if I could include a scrollview and put the views existing elements(objects) without having to re-design the nib, what I have done already;
I drag a scrollview into the view then making all the existing elements as children of the scrollview so the hierarchy looks like;
--view
--scrollview
--textfield
--button
The end product I get with this approach is that all the elements stacks on top of the other, so I've lost my original design.
So this is what Im asking, is there anyway, to add a scrollview without having to go through the design phase again.
TIA

If your view is designed in a nib, from IB you can select all the elements of the view and then go to Editor->Embed in->Scroll View from the menu.

Following are the steps-
1.Add the scrollview to the main view as subview.
2.create a new view which contains all your elements for the scrollview.
3.add the new view to the scrollview as subview.
4.set the content size of the scrollview as the size of the new view.
Change the frame of the newView accordingly on orientation and repeat step 4.
Thats all you need to do..

Related

Mass auto layout option for 40 viewcontrollers?

I designed about 40 view controllers using a 5.5 inch storyboard layout. After all of that I tested it on the iPhone 4S...big mistake. everything is jumbled together being for a larger screen size. I was able to fix one view controller up using Size Classes. I am wondering if there is any way I can adjust all 40 at the same time, or at least avoid doing this for every single one. It is really frustrating finding this out now. Thanks!
This is a relatively complicated issue you are attempting to solve, but I have two potential solutions. Both suggestions are based on moving your current interface into containing UIScrollView instances
If you are using storyboards, then for each of your view controller scenes, put a UIScrollView as a descendent of the view controller's view. From there, provided your subviews are contained within other views (like a container view for a set of buttons), you can move those into your scroll view. You will have to setup constraints to define the size of the scroll view's content, but this will allow the size of the device to have a smaller impact on the interface as you will get scrolling as needed.
If you are using nib files (.xib) then it is essentially the same thing, but easier. In this case, move a UIScrollView onto the canvas, but not as a subview of the default view. Once that is out there, move the original view to be a subview of the scroll view and set constraints to be 0 from the subview to the scroll view. Finally, right click drag from the File's Owner icon to the scroll view and set that as the view outlet.
Hopefully one of these will help you.

UITabBarController: Tab bar covers view

I am fairly new to UI elements in iOS (all of my apps were Gl games) but I'm trying it out and I found myself in a bit of a pickle...
The view controller for the bulk of my app is a subclass of UITabBarController and I have a few tabs with (currently empty) child view controllers. For the most part I have these working fine, but my problem is with correctly sizing and placing items inside of a tabbed view controller. If, for instance, I try to place something just above the tab bar, then I can't just set the Y position to the height of the the child view controller's view minus the height of the object I'm placing. I also need to account for the tab bar itself.
I can see that part of my problem is that I'm simply creating the view controller and not telling it what size it's view needs to be. Is there a function provided to me to calculate the height the view needs to be? I could just figure out the height of the bar and subtract that from the overall height, but that just feels to flimsy to me.
Any ideas?
EDIT:
I am doing it all programmatically and I don't intend to use Interface Builder. My main concern with the view size is making sure that things like table views fit snugly.
If you are using Interface Builder and auto layout, you can place UIView items on your UIViewController and if you set a size constraint on the view you're placing you can also set position constraints that are relative to screen edge or adjacent views, in your case UITabBar.

Adding a UIScrollView to an existing view with lots of objects... how to easily make whole view scrollable?

I made an app that has a lot of content on its view (images, buttons, text labels, etc.) and is optimized for the iPhone 5 display. However, the part of the view that is missing when viewed on an iPhone 4 screen is just additional settings, and is perfectly acceptable to be hidden until scrolled to.
So, how do I made my entire view scrollable for iPhone 4 users? I tried just dragging and dropping a UIScrollVIew object over the top of the whole view, but it doesn't add scrolling capability.
I have worked with UIScrollView before, but it was always something I added to the view before anything else, and don't know how to go about adding it to my view now that there are already bunches of objects. Hopefully there is some easy solution that doesn't require manually addig every object as a subView, etc.
Thanks for the suggestions!
I don't know how your views are created, but the easiest thing would be to change the class of the main view from UIView to UIScrollView.
From the InterfaceBuilder you can select all your content views (images, buttons, text labels, etc.) and then select Editor > Embed in > ScrollView.
This will create a UIScrollView containing al the views selected.
WARNING: you will lose all constraints between these subviews and the superview or the layout margin. Relative constraints (from subview to subview) will remain.
This approach is very useful when you wan to make only some content scrollable.

Xcode - Is there a way to drag a component from one view to another without losing its frame?

What I'd like to do is drag a component/view from one superview to another in Xcode's interface-builder without having its frame/position be reset.
Xcode's default behavior when doing this appears to be to center the view being moved vertically and horizontally in its new superview, while preserving its dimensions. This is extremely frustrating, as it means that the view needs to be manually repositioned in its new superview. But I had it positioned correctly before I moved it, so I'd like Xcode to just remember all attributes of its frame instead of just its width/height. Is this possible?
Another solution:
Select the items you want in your subview, then
(in the tool bar) Editor > Embed In > view type to embed in.
I found something that might help you guys!
The task is to regroup "child views" into "parent view" so they become children of parent view hierarchically and retain physical positions on display as before action.
First, adjust the parent view to physically covers area of child views. Second, make sure that all children are bellow it in the view list.
Now select all children with the mouse and move them e.g. one pixel up and one pixel down (just to say IB there is some change). After that release children and they will magically become children of the parent and keep their positions on display.
It works for me on OSX 10.8.2 and Xcode 4.6.
Good luck!
I managed to save a lot of time spent repositioning stuff and did this:
Add the parent view in Interface Builder on the same level as the would-be subviews.
Open the storyboard in a text editor and copy the would-be subviews inside the subviews tags of the parent view. XCode is going to update once you save it.
Not very elegant though, can't see why XCode doesn't support it with Shift or something.
Select all controls you want to move from one UIView to another UiView(nay be child) or ScrollView
Cut/Copy
Now after dragging new UIView/ScrollView to your existing UIView, Don't click once to select it, instead DOUBLE click on the new UIView/ScrollView and paste all controls.
Distance difference will remain same among all controls, but you may have to reposition controls again. So don't click anywhere until you have repositioned those, just reposition all controls by navigation arrows as those are all selected already, or you may ve to select those again.
NOTE: I m on XCode 4.2
I have done something similar to Stepan's solution, without using a storyboard. In the IB while the ViewController's view is open:
Create another view in addition to VC's main view
Move all subviews to the second view by dragging them from one view to another (dragging from the list on the left side resets their position) If you cannot select them from the IB using your mouse then select all from the list on the left side then select one final subview from the IB panel using "cmd" button.
Take them back to the final view on the initial main view.
Remove the added view, all set.
This is the best solution to copy subviews to another view and retaining the positions :
Select the items you want in your subview, then
Editor -> Embed In -> View
Copy this View (Cmd+C)
Undo (Cmd+Z) (Since you just wanted the subviews)
Go to the view you want the subviews in and paste it(Cmd+V)
Select the Embedding View that you copy-pasted and Editor -> Unembed
Step 6 would remove the embedding view and you'll have copied just the subviews.
Xcode Interface Builder messes when a Parent View is dragged and dropped into another View (UIView, ScrollView, StackView)
Q:
Embedding a View (which contains many other subviews within it) into a ScrollView or in another top level view is not straight forward with what I have seen so far. What happens soon after is all the subviews might seems to be misplaced due to it couldn’t find their original frame.
A:
Follow following steps and you will be able to resolve it easier as possible:
Select the items you want in your subview, then
Go to menubar, Editor -> Embed In -> View
Copy this new View (Cmd+C) with the subviews (for me currently all the constraints were preserved so far at this point)
Go to the view (be it a ScrollView or may be StackView) you want the subviews to be in and paste (Cmd+V) the copied view
Select the pasted Embedding View (which you newly created previously) and Go to menubar of Xcode, Editor -> Unembed
No, not finished yet! Sometimes, you may experience that there are few more UI Constraint related issues, you will have to resolve them accordingly.
I detected another approach. It is basically: Move = Cut + Paste
This way you do:
get all your subviews to be children of the new parent view (P')
keep (almost) all of your constraints in Auto-Layout based Storyboard
keep your subview's relative positions (frames) one to another
This way you do not:
edit Storyboard file in a text editor
Base the thing is that each view except one (root) in Storyboard has its parent view. Next, when you copy/move multiple subviews, you lose frames and constraints.
The answer is pretty simple. You make a copy of your subviews (SVs) by copying their parent view (P) into new parent view (P'). This way you may need to recreate only constraints from that parent new view (P') to its new parent view but not for every subview you wanted to move.
After you did make copy of parent view (P) into new one (P'), from that new view (P') you:
remove all the children except ones that you wanted to move
recreate new parent (P') constraints
recreate possible Interface Builder outlets to (SVs')
And from original parent view (P) you:
remove all the children that you wanted to move
Before:
View1
View2
P
SVs-you-want-to-move
SVs-you-do-not-want-to-move
View3
After:
View1
View2
P
SVs-you-do-not-want-to-move
View3
P'
SVs'-you-want-to-move
I should stress that this does not generalise well if you have e.g. UIScrollView as a parent view. Then a copy of it would be again a UIScrollView what may not be desirable.
Another thing is when you do remove some of the subviews (SVs) in original parent view (P), you may need to recreate some constraints if other (non-moveable subviews) reference them. But you should do that anyway.
What helped me to solve this issue was-
Create the desired parent view (scroll view or uiview) in the xib at the root level and resize it accordingly
Copy all the views that you want to be subviews of this parent view and paste them onto the new view you created in step 1
At this point you will have duplicated these views. The newly added views would be a misaligned but still in the same order and at the same distance with respect to each other, align them in the xib to match their bounds with the old copies of the same view (This assumes that the new parent view has same bounds as the old one)
The newly added views will lose some of the constraints, refer to the old views to fix those
Delete the old views from the xib

Designing inside a scrollview in xcode 4.2 with storyboards

I have a vertically scrolling uiscrollview - imagine an 'about this app' page of a tab bar app which goes on a bit and requires a scrollview. It only contains a few images, a video and some text (only the video has been coded in - the rest have been placed in the GUI). In storyboard (Interface Builder?) Xcode 4.2, everything is set up as it should be and works fine, but the view is only as large as what you see on the screen, is it not possible to manually arrange in storyboard the items that are initially offscreen - that you need to scroll up to? The only way I've found so far is to design them on the visible view then navigate them down with the arrow keys..
In the storyboard select the viewController, then in Attributes inspector change 'size' to 'freeform'. Then change the 'height' of the view/scroll view to as big as you need. The default settings of struts and springs should take care of resizing the view back correctly when the app is run, but you should double check.
I feel your pain. The only way I found is to manually pan the scroll view in the size inspector to reveal the portion of the view that you wish to visually edit.
Use a UIView to contain elements so they are positioned relatively to this view. Add the view as a subview to the scrollview at 0,0.
pan: use the Y coordinate say to -200, then edit the contents.
to place more contents in the hidden part, pan again to reveal new real-estate
when finished, restore the values of the ScrollView's height and X,Y position.
Make sure the scroll view frame rectangle is smaller than the contained view.
New: 3/26/2013
I stumbled upon what I think is even simpler way of dealing with UIScrollView directly in storyboard.
No code needed, just storyboard settings. This maybe new in iOS6.1 / Xcode 4.6
No need to disable constraints (i.e. uncheck "Use autolayout" in File Inspector for storyboard file)
No need to add UIScrollView* scrollView; in .h
No need to add self.scrollView.contentSize = ... in overrides of viewWillAppear or viewDidLoad
Here is what I did (important parts highlighted with **): (see code)
Create a new project with storyboard enabled
Drop in a UIScrollView, set class in identity inspector for view controller
In attributes Inspector, change Size under simulated metrics to Freeform**
Select scroll View; In attributes inspector, turn on "scroll enabled" and "background" to "White" (you'll figure out why - if you don't)
Under Size Inspector (with scroll view selected) change the height to 900 for example**
Add buttons, one on top and one at the bottom
Add a default handler for buttonTouchUpInside for both buttons and simply Log sender.
See Code Select the View Controller and scroll view and check inspectors.
Just change the 'Simulated Size' of the view controller to freeform and set a height that is larger than the usual size, you will be able to see all the outlets you need to edit.
On iOS 6.0 you can drag a Container View inside your Scroll View. This will automatically create a new View for your content, outside of the current scene. You can then resize this view as big as needed to fit your content.
I believe you would still have to set the ScrollView content height at runtime, but at least you can design you content view at once without having to scroll up and down on IB.
Just uncheck the "Autoresize subviews" from any view that you're trying to resize and it should keep all your objects from resizing with it.
I've been struggling with this for a while now, and every single thing I've tried has failed.
Specifically, What I am trying to achieve is a freeform sized modal dialog with a scrollable view containing a container for another view. I have had a lot of varied results, including occasionally having it working correctly. Most often I get it looking exactly correct, but with no scrolling.
In finally downloaded Dickey Singh's code, which worked perfectly but had nothing special. (Excellent clean solution BTW). So, I added a container view to it, exactly as I had in my code, and it broke!
After some experimenting, I worked out what is going on. Just bear with me.
1) Using Auto Layout, the size of the scroll view seems to dictate what the scrolling bounds will be. Setting "contentSize" in "USer Defined Runtime Attributes" seems to have no effect on this, and neither does setting "contentSize" or "bounds" in "viewWillDisplay" or "viewDidLoad". Thus if the initial size of the scroll view is 800x800, that will be all the space that can be displayed. For this reason, when I want a scrollable region, I create a container view and then put the scrolling view inside the content.
2) Without Auto Layout, setting "contentSize" in "User Defined Runtime Attributes" works, as does by setting it programmatically in "viewDidLoad". I prefer to use "User Defined Runtime Attributes" because it keeps the size with the layout. This solution allows you to use scrolling view with more flexibility, since it can be any size at design time.
3) Regardless of Auto Layout, if any view within the scrolling region exactly matches EITHER the horizontal or vertical frame bounds, then the scroll view ceases to function as a scroll view. This applies to my own code and to Dickey Singh's code in every possible configuration that I have tried.
I have no idea what is causing (3), but it is clearly a bug.
I hope this helps everybody out there who is struggling to use scroll view. I imagine that some people are using them without any problem, and some (like me) have had noting but problems with them.
Here's my solution to design a ScrollView with a content larger than the screen entirely in Storyboard (well, except for 1 single line of code :-) :
https://stackoverflow.com/a/19476991/1869369
I'm currently developing an app for iOS 7, and I did exactly as #Dickey Singh's answer, but it doesn't work in the beginning.
After checking the storyboard, I found that we also need to add Auto Layout Constraints for the view controller who holds the scrollView.
It seems that such auto layout constraints would be added automatically before Xcode 5, but now we need to do it ourselves.
The way to add constraints: First select the view controller in the storyboard; Enter 'Editor' in the top menu; Select the 'Resolve Auto Layout Issues'; Select the 'Add Missing Constraints In Container'. Done :-)

Resources