Convert view to scrollview for modal controller - ios

I have some modal controllers that are UIViews and are not scrolling.
Reading on SO, the apple docs and elsewhere, it seems there are three approaches to fixing this:
Multiselect all the elements within the view and then go
editor-embedin-UIScrollview.
change the view to a scrollview in the identity inspector and then
add the following line to viewdidload:
[(UIScrollView *)self.view setContentSize:CGSizeMake(320, 2000)];
Copy elements to clipboard, delete the uiview, add a new scrollview
and copy the elements into the scrollview. Warning - this destroys
the positioning of the elements although it does preserve their
outlet properties.
However, I have tried all of these and the scrollview still does not scroll.
Is there any other step I am missing?
Thanks in advance for any suggestions.
Edit:
Getting scrollviews to work is not easy and there is much conflicting advice on the web.
I finally got this to work by setting the content size in a separate method as opposed to viewdidload.
(void)viewDidLayoutSubviews {
self.MainScroll.contentSize = CGSizeMake(320, 1800);
}
Thanks as well to Evo for advice on setting all the vertical dimensions correctly and using freeform in the VC size inspector as it won't work if you don't carefully set these.

If you have EVER enabled autolayout, even if it's disabled now, you need to:
Select the view controller you plan on scrolling
At the bottom right of the storyboard view, click the third button (far right) and then "Reset to Suggested Constraints"
Make sure that all the elements in the scrollview are embedded in the desired positions.
If you are not using autolayout:
Check that the Size of the view controller is set to (320, 2000), or whatever you want.
In the Simulated Metrics of the view controller, you can set the size type to Freeform.
Then in the tab to the right of Simulated Metrics, you can set the width and height to the desired values.
Please comment any concerns

Related

UIPickerView ignoring contraints

I have a view within my app that has a UIPickerView. The delegation and datasource is set up and the picker loads data correctly, however, it ignores storyboard constraints entirely and shifts to the top of the view regardless of what I've tried.
The screenshots below show the alignment in storyboard (the picker is aligned center vertical/horizontal to the blue view (which has a constraint of 30 on all sides) and the alignment when the app is run on a 6S.
Any idea what I'm doing wrong?
UIPickerView has a fussy implementation of setFrame: -it only allows itself to be rendered in a handful of sizes. The easiest way to control/overcome this is to put it in a container view and apply your constraints to that view. You could override layoutSubviews in that containerView in order to center the picker, perhaps even applying a transform to scale it. Don't try to set the size of the pickerview in this code, just query (get) it and then calculate around that value.
Remove [self.view addSubview:self.mouthpiecePicker]; This is re-adding the picker view, but it was already added with Storyboard. When you re-add it, it removed all constraints.

Xcode 6.1 IOS really long form

I am quite new to xcode.
I am trying to create a contact details form for an iPhone using the storyboard. The problem is that form is longer than the display and I can't work out how to design it using the storyboard.
Any ideas?
Tom
In IB, you can set the controller's size in Simulated Metrics to Freeform, then select the view and make it as tall as you want. Then, add a scroll view to take up the whole view, and add your UIElements, and lay them out how you want. When you run the app, the view controller will still only be as big as the screen (obviously), but the scroll view will be as big as you made the view in IB (you may need to increase its contentSize even more to be able to scroll to the bottom).
Such forms are often made in storyboards using a UITableView and setting the "content" of the table to be "Static Cells." You can set any number of cells and the contents of the cell you want. The table itself is scrollable inside the storyboard/Interface Builder editor and looks much the way it would when presented to a user.
First, select the tableView on the left
Then, you can move it simply scrolling (on mac, two fingers on the trackpad, or using the mouse wheel)
You should have a look at UIScrollView, it is designed to support content larger than screen size (like you see in web browser or settings)
Basic usage is:
//Set a size which will be able to cover all form elements
[yourScrollView setContentSize:CGSizeMake()];
//Your scrollView now extends from CGPoint 0,0 to contentSize.width,contentSize.height.
//Your subviews should be positioned according to scrollview's bounds not the viewcontroller.view or any other container view.
//Add all the form elements
[yourScrollView addSubview:...];
[yourScrollView setDelegate:self]; //If you need actions after user scrolled etc.
Have a look at the developer manual for more info. Most method names are quite self explanatory.
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIScrollView_Class/Reference/UIScrollView.html

UITableView in storyboard not updating content size on rotation

I'm working on project targeted for iOS 6 that leverages storyboards and auto layout. In the storyboard there are many places where a UITableView is added as a subview to a view controllers view. This table view uses prototype cells from the storyboard.
The issue we're running into is that if the view controller is initially loaded in landscape orientation and the device is then rotated to portrait, the table view begins to scroll both vertically and horizontally. The table views cells are drawn with the correct dimensions but there is additional white space to the right.
It appears that while the frame and bounds of the table view are being updated to the correct size on rotation, the table views content size is not. Regardless of any update rotation change the content size remains the same dimensions.
The issue doesn't present itself if programatic table view cells are used.
A few garish work arounds I've found, 1.) calling reloadData or reloadRowsAtIndexPaths:withRowAnimation: 2.) manually setting the property contentSize.
Both of these seem less than ideal.
I've added this
link to a dead simple sample project which demonstrates this issue. The only changes made are to the storyboard and the main view controllers implementation.
Before rotation
After rotation
I'm having the same issue - can't seems to find any documented answer related to this. I ended up manually modifying the UITableView contentSize like you mentioned in:
- (void) viewWillLayoutSubviews
{
self.tableView.contentSize = CGSizeMake(self.tableView.frame.size.height, self.tableView.contentSize.height);
}
I ran into this issue today and filed a bug report with Apple.
Appears that if you are using a custom cell with a UI element AND autoLayout, the UIScrollView content size is having problems.
If you remove all UI elements, OR turn off autoLayout, OR use a factory cell (basic, etc), all works fine.
Same issue I have rectified in my project.
I guess this is a bug in Storyboard.
Then I have solved it by manual coding in willAutorotate method by setting
tableview.contentsize = CGSizeMake(tableview.width, tableview.contentsize.height);
Hope this will work for you as well.
If you find any apple documentation regarding the same then please update me as well. Till then you can use the same solution.
Appears that if you are using a custom cell with a UI element AND autoLayout, the UIScrollView content size is having problems.
I had to turn off AutoLayout for my custom UITableViewCells to be able to scroll to the bottom on updating the data and then [self.tableView reloadData].
With AutoLayout turned on, the tableView.contentSize was being updated, but I still wasn't able to scroll to the bottom unless I rotated the device.
I found the following to work for me:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
dispatch_async(dispatch_get_main_queue(), ^{
self.tableView.contentSize = CGSizeMake(self.tableView.frame.size.width, self.tableView.contentSize.height);
});
}
Notice the async dispatch: if that line would be executed synchronously then the contentSize change would trigger another layout pass before the current one would have completed. This triggers an exception:
Auto Layout still required after sending -viewDidLayoutSubviews to the
view controller.
Usage of Constraints helped me. Since you are using Storyboards, it is really easy to set Constraint values for all edges, so UITableView will always fill the whole ViewController (of course if UITableView fills whole ViewController) regardless of device orientation.
I had the same problem.
I found this link. When I tried to implement this I did not find the Auto-sizing attributes for my view then I clicked on Master View Controller and then clicked on the File Inspector and uncheck Use Autolayout and then go to Attributes inspector auto-resizing should be there then you can change the attributes how you want it.
I am sure you must have managed to figure this out.

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 :-)

iOS: How can I figure out the size of the view in the super view's layout?

When I use self.view.frame.size.height, it gets the height of the child nib, rather than the height of how the view is going to fit into the overall layout. I get the same value using self.view.bounds.size.height and super.view.bounds.size.height.
Any help would be appreciated.
Ask at the right time. Not until the view is ready to appear has iOS figured out what size it will actually be. Move your code that depends upon the view being the right size to viewWillAppear instead of viewDidLoad or an init method.
In Xcode 4 you would select your view controller that contains the UIScrollView and set the 'Simulated Metrics' in the IB Attributes Inspector as follows:
This ensures that your UIScrollView will be set to the correct size to fill the available space at design time. It looks like you are using an older version of Xcode/IB and I can't remember exactly where these settings used to be but they're in there somewhere.
With the layout designed to accommodate the space taken up by the tab bar you should be able to query the size of the UIScrollView at any time and get the correct values.

Resources