Why is AutoLayout not taking care of my UICollectionView - ios

I have built a very simple sample of an app (Source code on github) using a UICollectionView.
Everything is working fine, as long as the app is in portrait mode. When it is changed to landscape mode however, the content cell is not resized appropriately, and thus, nothing is displayed.
I thought that all the necessary AutoLayout constraints are in place. I am aware that I can implement collectionView:layout:sizeForItemAtIndexPath:, but my goal is to use AutoLayout as much as possible (simply to understand AutoLayout better).
What am I missing here?

You can use autolayout to set the position and size of the collection view. And you can use autolayout to set the position and size of the subviews inside each cell. But you cannot use autolayout to control the position and size of the cells. You must use the collection view's layout object to set the position and size of each collection view cell. If you want the cells to change size when the interface orientation changes, you must update your layout object to report the new size and invalidate the layout.

Related

Setting UICollectionViewCellSize at runtime

I have a stack view that contains three UICollectionViews, set up to give each of them equal vertical space. That stack view is set to be the height of half of the display, so that it uses more space on larger devices. This has been set up in Interface Builder.
So, I need to set the cell size of the UICollectionView at runtime, since until we are running, I don't know what the actual size of the cells will be. I want them to be square, so I just want to take into account the height of the UICollectionView, subtract out the top and bottom section insets, and set the itemSize to the resulting size.
I attempt to do this in viewDidLayoutSubviews, since by then I figure that the initial heights of the collection views have been set. However, they appear to be set to 1000x1000 (even though they are a much more reasonable size in the storyboard), and so I compute a cell size based on a collection view height of 1000. This is too large, but I figure that I'll get called again and get another chance to recompute it. And I do, but not before UICollectionView complains loudly that the itemSize is incorrect (ie. too large to fit in the collectionView, which now has the "correct" size.)
What is the best way to get the behavior I'm looking for without the warnings from UICollectionView? Setting the collection view item size at runtime based on the eventual size of the UICollectionView is something I've struggled with in the past, and there never seems to be the "right" time to set the itemSize. I don't want to dynamically return it, if only because it's not something that changes during the life of the program. There just seems to be some inconsistencies that occur when laying out the views initially.
It seems odd to me that the collection view comes in with an initial size of 1000.0 by 1000.0, but I'm not sure how or why to fix that - perhaps it has something to do with being embedded in a stack view?
Edited to add: It is almost certainly the UIStackView that is causing the layout issues. I created a dummy project to test the size of a UICollectionView when it is the top level view vs embedded in a UIStackView. If it is not embedded, when viewDidLayoutSubviews is called, it has been properly sized to fit the bounds of its superview. However, if it is inside of a UIStackView, it stays at the default size of 1000x1000.
For now, I am working around this problem by adding the following code in viewDidLayoutSubviews:
if collectionView.bounds.size.width > view.bounds.size.width {
view.layoutIfNeeded()
}
Where collectionView is inside a UIStackView and view is the main view of the UIViewController. This allows all subsequent calculations based on the size of the view to be correct, and hopefully will not get called if the UIStackView behavior ever gets fixed.
Similar discussions here and here. Interesting point that in XCode8, the new default is to not save sizes of views in the XIB file, but instead bring everything in with an initial size of 1000x1000, to be resolved during the first layout pass. Except for UIStackViews, I guess.
Are you having sizeForItemAtIndexPath() return itemSize? I have found that implementing that function is the only reliable way to size a UICollectionViewCell dynamically at runtime.

UITableViewCell size

I have a table view with cells in my IOS app. The thing is that when the cell loads I need to layout some stuff on it that is relative to the size of other elements. The problem is that I can't get the size because there is no viewWillAppear or viewDidLoad methods, which have actual bounds(with autolayout and constraints applied). What is the best way to work with cell's geometry and sizes in IOS, can somebody tell me ?
Auto Layout and self-sizing cells (in iOS 8).
The layout system will determine the size of the "stuff" in the cells, and proper constraints will then determine the cell's height.

Constraints in ios

I am learning constraints and spent whole day applying them to the following screen.It is not getting displayed properly in landscape mode.Basically i am not getting how to fix vertical space between ,say, label-Welcome to BBBB and textfield-username so that textfield always appears below the label yet the spacing between them is adjusted according to the screens of different size. If i go for Pin\Vertical space, it automatically fixes the constant value.
Remove the label (or just move it out of the way).
Fill the space that you want to resize with a view.
Constrain this view to the objects above and below and to the sides of the parent view.
Put your label into this view and constrain it to the top of this view and centred to it.
You may need to change the constraints on the objects above and below it to stop them from changing height in an unwanted manner.
This new view should now resize as the device changes orientation but the label should remain at the top of it.
Repeat on other areas of your layout (i.e put things that are not moving around as you want them into sub views and constrain these views to resize accordingly). Experiment with using variable heights, fixed heigh constraints and 'equal heights with' constraints on the views that you add to get them to resize as you need.
Edit: but you have a lot of vertically stacked items in that view - you may never get them all to fit into a horizontal orientation. You may need to remove a few, or add a scroll view or force that view only to layout in portrait mode or... Don't forget to check that it works on all devices you are targeting.
#Ali Beadle was right. Since i had a lot of vertically stacked items, lining them up in landscape mode was not possible. So, i went for scrollview.
I have taken a ScrollView first and then a UIView named ContentView on that ScrollView. I have made the width of ContentView equal to the width of parent UIView and kept its height fixed to 568. In my code i set
_contentViewHeight.constant = self.view.frame.size.height;
Now it scrolls in landscape mode while in potrait mode, it does'nt scroll.
I run into Autolayout problems all the time. But I finally figured out a way to overcome a lot of issues that arise from it.
I simply will use a container-View like ScrollView or even a plain old UIView, place all my controls in it. thats it. this makes things a lot easier for autolayout to figure out the constraints. in your case you could just use a UIView.
-start off by removing all the constraints you have I would start by selecting each control in the XIB and see if it has width/height constraint, select it then press the delete key then at the bottom of the project explorer you'll see all the constraints that auto layout has select each one then delete. that should get rid of any complaints that auto-layout might have.
-Place a UIView object inside your main View then
-move all the controls inside it. Then
-add the necessary constraints for the container view so it'll resize in different orientations and don't worry about any constraints inside the container view (auto layout will figure them out automatically).
that does the trick for me usually.

View dimensions doesn't alter with iPhone dimension

I have created one view, which I want to use for all iPhone dimensions. So I've set constraints in the view's subviews and its working fine. But when I tried to launch the app in a phone with dimensions less than that of the xib I created, the view projects outside the superview when adding as subview. So now each time when I am adding as subview I have to set the view's frame according to the device's screen dimensions.
I want to know whether there is any other way to resize the view's dimensions in accordance with the device's dimensions, other than setting the view's frame manually.
if you are using the the auto layout in your xib then go to
editor menu-->Resolve auto layout issues-->ALL views in view-->update constraints. if there is no constraints applied then you can go for add missing constraints and see the difference.

Content of scrollview changes size when scrolling

I'm using iOS 6 and Xcode 4.6 and with the Interface Builder I added to my controller a UIScrollView that uses all the available space. In this UIScrollView I added some views (a UIImageView, a UITextView and a UITableView (I disabled the scrolling for the UITextView and the UITableView)).
In the :
- (void) viewDidLayoutSubviews;
method I resized all my views by increasing their height (to fit with their respective content).
Then, I set the contentSize of my UIScrollView so that it fits with its content (my 3 views).
The resizing works and I can see them in my application when I run it.
Also, the scrolling is good (the contentSize is correct as I can scroll).
However, I have one big issue : as soon as I scroll, my 3 views are resized to their initial size (instead of keeping the size I assigned them via the frame property).
All my views are added with Interface Builder to my storyboard.
Do you know what I did wrong? Why my UIScrollView's content is reseting its size when I scroll?
Thank you for your help
You have auto layout enabled in your storyboard. When you scroll the scroll view, auto layout runs and resets your subview frames based on the constraints in the storyboard.
There are a few ways to fix this. One way is to turn off auto layout in your storyboard. Another way is to connect outlets to the constraints in your storyboard, and update the constraints (instead of setting the frames) to make auto layout put the views where you want them.

Resources