After seeing the wonderful Advances in Collection View Layout Session, I wondered if is possible to use the capabilities implemented in the new Collection View Compositional Layouts framework to create a layout based on previously unknown cell sizes.
My problem:
Imagine a horizontal image gallery with two levels, the photos can be "vertical" or "horizontal", and the app is fetching them when are needed for display, and they are provided randomly ("horizontally" or "vertically"). So we have to populate the gallery with a "random pattern" (Pinterest style, here is how to do it with UICollectionViewFlowLayout).
I cannot see a "group" pattern to populate the cells, because the layout has infinite possibilities, vertical divisions can appear to create groups, but also can not.
Is it possible to archive with Collection View Compositional Layouts?
Thank you.
When you're setting your item layout size, you can use an estimated layout dimension to make the size dependent on its contents. So an image view can set the cell size from the inside out using constraints. You size the image when you populate the cell, depending on whether it is horizontal or vertical, and the image view adopts the size of the image and the cell adopts the size of the image view.
(If you needed even more control you could construct your group as a NSCollectionLayoutGroup.custom, which allows you set every item's frame manually. But there's no need for such extremes in this simple situation, and besides, that assumes you know the frame at layout declaration time, which you probably don't.)
Related
Is there any existing flow layout which can support a collection view which the user can scroll a collection of images in a horizontal direction but have the images have variable width and same height? I have one sort of working but it sometimes randomly spaces the images. Thanks.
I have a screen in interface builder that consists of a UI Collection View containing reusable cells. I've used Interface builder to add Auto Layout constraints to the UI Collection view and its scaling and moving about on each device like it should. How can I use the same method (control dragging) to auto layout the cells width and height? I can get constraint options via control dragging for the child objects in the cell to the cell but not from the cell to say the UI Collection View.
Any help greatly appreciated!
Thanks.
You don't. Collection views manage the placement of the cells within the view themselves, using their own rules. You can certainly use AutoLayout to determine the size and placement of the entire collection view, and you can use it for the internal layout of individual cells, but you can't use AutoLayout to size or position the cells within the collection view.
I am new to iOS development and I am developing a buy/sell application. I am trying to make a collection view where I don't hard set the size of the collection view cell. Instead it would depend on the user who post up something they are selling. I realized that by hard coding the size of the boxes, everything looks "boxy". Any suggestions would be greatly appreciated.
Assuming you're using the default flow layout, there are two options:
You can have self-sizing cells if you:
define unambiguous constraints between your cell and its subviews;
do not define fixed width/height constraints for the image view;
set the estimatedItemSize of your UICollectionViewFlowLayout:
let layout = collectionView?.collectionViewLayout as! UICollectionViewFlowLayout
layout.estimatedItemSize = CGSize(width: 100, height: 100)
Auto layout will then resize the image view to fit the image, and the cell will then resize itself to fit that, accordingly. So, for example, with some random image sizes, the standard flow layout will resize the cells automatically for us:
Now this is a simple cell with a randomly-sized, solid color image in an image view and constraints of H:|[imageView]| and V:|[imageView]|, but the same idea works with complicated cells, too. You just need to make sure that the top/bottom and leading/trailing constraints of the cells are unambiguous.
Note, if you rely upon the implicit size of the image view, this assumes of course that the images are already sized consistently for the device. If not, you might want to create constraints for the image view height/width, include #IBOutlet references for that, and then set the constant for those constraints in your cellForRowAtIndexPath method. But, to manage memory efficiently, you generally want to downsize the images to an appropriate size anyway, so this is generally not necessary.
Alternatively, you can specify a delegate (a UICollectionViewDelegateFlowLayout) of the flow layout and then implement sizeForItemAt:.
Can I setup constrains on storyboard view controller views so that I will have three views one next to other when there is enough horizontal space. In other case it will "float" one of views to next line?
Like on this example:
Enough space
Texts causing third view to "float"
Maybe stack views can help here?
There is no reason to expect the auto layout system to be able to accomplish this, nor can it.
What you want to use here is a collection view (UICollectionView) and have each of your views be a cell in the collection view. In fact, if you look at your views, they look quite the reusable views, where each one has an icon, a title and a detail text. A collection view can be set up to put cells one next to the other until there is no more space, after which cells are added below, and so on.
You can then setup your scene to layout around your collection view using auto layout, where other views would reposition correctly below the collection view content when the collection view grows in height.
See this layout as an example of what you need.
No. There is no way to setup views and constraints in a storyboard that automatically float into a new row if they don't fit into the same row.
(In my opinion that's a big weakness of the Autolayout system.)
The reason for that lies in the concept of constraints: Mathematically they represent linear equations that are normally independent for the x and y dimension. The only exception are aspect ratio constraints that connect the width of a view with the height of that (or another) view. But I cannot think of a way how you could use an aspect ratio constraint to break views into a new line if needed.
When the system resolves your constraints at run-time and computes the actual frames of your views it simply solves the system of linear equations for each dimension (or for both dimensions if an aspect ratio constraint is present). Adding the option of floating views to the Autolayout system would make the whole layout process a hell of a lot more complicated because you cannot describe that behavior as a simple linear equation.
(Stack views won't help as they only work for one dimension as well: either x or y.)
Recently, I needed the very same floating behavior you described and created a FloatingContainerView subclass of UIView. I generalized it so you can use it for any kind of view and translated it into Swift.
You can now find it on GitHub:
https://github.com/mischa-hildebrand/FloatingContainerView
I am programmatically adding a dynamic number of UIButton which are labeled as hashtags to a compact view using Adaptive Layout. Is there a way for adaptive layout to automatically calculate when the width of the view is met and a new line is needed, or do I need to calculate that myself, then manually anchor the next row of buttons under the previous and so on?
My current source gives me the following image, where a second row is needed. Appreciate any direction on this.
Auto layout cannot do this, so if you want to use individual buttons, you'll have to calculate it yourself. Another alternative would be to use a collection view which will automatically layout the buttons (cells).