UIcollectionview decoration view VS supplementary view - ios

I'm starting my development of an ios app using ios 6 and UICollectionView.
I've noticed there's support for both supplementary views and decoration views.
Can someone please explain in bullet points the difference between the two? They sound very similar.
If I want to add a loader to my collection view (that will appear at the bottom of each section, while the section is loading) should it be a supplementary view or a decoration view?
Thanks

Decoration views are just what the name says: decoration, chrome. Only the collection view layout decides what they are and where to put them (for instance, if you want to draw lines on the screen every 5 items).
Supplementary views are more related to your data. The collection view layout still decides where to put them, but they are provided by the collection view data source, just like regular cells. For instance, if you wanted to put titles for sections, you would use supplementary views because the title would be different for each section and you need to call the data source for each.
If your loader is generic, it could be a decoration view, however decorations views are not really accessible (the layout object says where to put them, and that is it, they are created by the collection view and you never get a reference to them), so if you want to start/stop animating it, a decoration view is not the best choice. If you use a supplementary view, then you have access to it at creation time (in your data source collectionView:viewForSupplementaryElementOfKind:atIndexPath: method). However, you can only query the collection view for regular data cells once they are laid out on screen.
Also, you will have to write your own UICollectionViewLayout class if you want to use custom decoration or supplementary views. The base UICollectionViewFlowLayout only provides for a footer and a header supplementary view.

from UITableView perspective :
Supplementary = sections.
Decoration = tableFooterView tableHeaderView

Related

How do you extend the height of a collection view and not have scrolling, but have scrolling on the outside view?

Right now, I have a collection view with scrolling inside a view.
I'd like the collection view's height to expand downward depending on how much content it has and not have any scrolling.
A user would then scroll from the outside view.
The collection view is the last section in the screenshot:
I tried using a table view with one cell having a collection view and that did not work.
"I am fairly new to Swift..."
You may want to first spend some time researching different ways to layout UI elements.
Depending on how many "repeating" elements you'll potentially have, you might want to take this approach:
If you'll potentially have many, many "repeating" views (cells), you might be better off using a collection view - with its built-in memory management - using one of these approaches:
Or, possibly a collection view with a Compositional Layout.
In any case, trying to "expand the collection view to show all the cells and then scroll the whole thing" defeats the purpose of using a collection view, and is rarely the appropriate way to go.

How to achieve a (almost) full view uitableview that can scroll past the last cell and show further elements in iOS

I have attached the below image because it describes my problem better than words:
So basically, I need the Title/Subtitles part at the top to always be static, after that a dynamic UITableView which will have a lot of cells (mostly will fill the rest of the screen), and then after that a few additional elements such as a Map View and etc.
I'm using storyboards/xibs for this so it was also an issue of how to constraint everything in the designer properly. Would a stack or scroll view be appropriate for this?
I think you can take two paths to achieve this.
The first is to create a custom cell containing the map and another containing the "Paragraph of text" thing.
Then you only need to push the cells at the end of the original data source.
Keep in mind that you need to add this cells to the RowsInSection function.
The other way is add a custom footer view to the tableView.
You can create a custom UIView containing the map an other info and then tell the table to take the custom view as footer:
tableView.tableFooterView = customView

iOS - `UIViews` behind `UICollectionViewCell`disappear

I have a gallery using UICollectionView that prepared using main.storyboard. I have a few UIViews and UIButton placed between UICollectionView and UICollectionViewCell. When I test the app, some of the UIViews and UIButtons disappear.
But I have another catalog scene which prepared using the same way and everything is there. What seems to be the issue?
I wouldn't mess with the UICollectionView's view hierarchy this way. Since it handles its own list of subviews, yours may be obstructed. I would suggest one of those two methods:
Set your UICollectionView background as [UIColor clearColor], and put your own views behind that UICollectionView, in a hierarchy similar to this:
UIView
Your Custom Views
UICollectionView
Use the UICollectionView's decoration views. You can read more about them here, in the "Including Decoration Views in Your Custom Layouts" section.
Decoration views are visual adornments that enhance the appearance of
your collection view layouts. Unlike cells and supplementary views,
decoration views provide visual content only and are thus independent
of the data source. You can use them to provide custom backgrounds,
fill in the spaces around cells, or even obscure cells if you want.
Decoration views are defined and managed solely by the layout object
and do not interact with the collection view’s data source object.

How should I approach structuring this view?

I'm having a hard time finding the best way to structure this design.
The top view has a minimum height and becomes sticky when it reaches this height. The bottom view hosts a paging controller with three views within. Each of these views hosts either a collection view or table view with vertical scrolling.
I'm really at a loss on how to approach this. Is the entire view scrollable and I should prevent scrolling on the second view until the top view has reached it's sticky height? Or are each of these views separate uitableviews and the pagingcontroller is just one cell? Should I even be using a pagingcontroller or should I use a scrollview with paging enabled? (the latter was a little rough interaction-wise)
Thank you!
Take a look at the Advanced User Interfaces using Collection View from WWDC this year. This view is very very very similar to the iTunes Connect app interface. The entire session video explains how they created that interface.
I used a similar method to this to create the keyboard in the Emojicate app.
I think what I'd do is actually fake the sticky header. So something like this...
Use only one collection view.
Create a "segmented data source" that contains three data sources. (See the video from WWDC about this)
When the segmented control is changed then update the collection view by changing its layout and (if you want) dataSource.
Make the entire top section a header on the collection view.
When the collection view scrolls past a certain point (when you want to sticky the header) then have a second view that is the compressed header and make it visible at the top of the screen. This is not attached to the collection view at all.
When the segmented control changes you can update the collection view by changing the "selected datasource". The datasource can also contain a UICollectionViewLayout that will update it.
Essentially, the tableview you are talking about is just a collection view where the cell width is equal to the screen width. i.e. fake a table view.
The sticky header isn't sticky at all. Just when it starts to go off screen you can put a fake header there instead.
It will require a duplicate (ish) view and some thinking about how to structure the data but I think this will be easier and less resource hungry than having multiple collection views and page controller and stuff.
If you want me to go through it in more detail let me know but it's a complex subject. Watch the video first.
I would make this part a navigation bar. Should be relatively easy. Just have to customize the back button with a barButtonItem and do a couple of labels in the titleView.
I would make the next part a Table View.
The tableView has 2 sections. The first section doesn't have a section header and the second section doesn't have any cells but just a section header.
First and only cell in this section:
And the rest would be the second section header's view:
This gives you the stickiness that you want because the section header will remain there even if you scroll past it and since the collection has only 2 sections the controls will always remain on top.
I think the collection/table paging part is the hardest part and I don't know clearly how it can be done. But I was thinking it could perhaps be a ContainerView. Each view of the container view would be either a tableview or a collectionview. You would have to add some code to handle the movement of the containerview relative to the second section header (possibly an autolayout constraint that attaches the containerview to the buttom of the first tableview that you implemented above).
I don't think having your tables/collections in a scrollview would be a good implementation. I think I have even read in documentation that developers should stay away from that (but I might be remembering it incorrectly).
I would have:
A "header view" with three subviews:
Fixed height top and bottom views (they stay visible at any size).
A middle view that appears/disappears as the superview grows/shrinks.
A scroll view (table or collection view are subclasses) on that partially covers the header view with a top inset set enough to reveal the underlying header view (the same way pull to refresh views are revealed).
The paging buttons could be set as table/collection view section header views.
Finally track the scroll view's scroll position to keep manually adjusting the header view height.
Another way to see this solution.
Two completely separated parts, a header view and a table view.
A simple header view (blue) that adjusts its subviews as its height changes. More precisely hides its middle subview (light blue) when it shrinks.
A table view that a) partially covers the header view in Interface builder but b) has a top inset as to avoid hiding the header view in the actual device (tableView.contentInset = UIEdgeInsetsMake(60.0f, 0.0f, 0.0f, 0.0f);).
The two parts are only "connected" by resizing the header view height as the table view scrolls up/down.

How can I set the entire header view to UICollectionView?

I want to set the header to collection view, just like UITableViewController's setTableHeader does.
I found the way to set the each section's header on collection view, but I couldn't find how to set the header view of the entire header.
Apple's reference of UICollectionViewLayout says "Supplementary views present data but are different than cells. Unlike cells, supplementary views cannot be selected by the user. Instead, you use supplementary views to implement things like header and footer views for a given section or for the entire collection view. Supplementary views are optional and their use and placement is defined by the layout object.", but I don't know how to implement header view for the entire collection view.
I tried to implement this by making a section header view rectangle only to the first section, but it was different with tableHeader's that.
In table view, if I set the content offset to below header, the content size automatically expands so that the header is hidden although there exist a few elements.
But in collection view, modifying content offset only works fine when there exist many elements enough to make a scroll.
I tried to dynamically expand content size when there exist a few elements, but it seems that it doesn't work fine...
I implemented this using a custom layout and repositioning the header on every scroll event. Start with subclassing UICollectionViewLayout, there are tons of tutorial on the web, this is a good one: http://markpospesel.wordpress.com/2012/10/25/fixing-circlelayout/
Then the trick is to always return YES to shouldInvalidateLayoutForBoundsChange:, and in prepareLayout reposition (ie. change the layoutAttributes' frame) the header based on the collection view xOffset and yOffset.
Use a supplementary view with NSIndexPath 0-0.
layoutAttributesForElementsInRect: will be called on every frame, so if you have a lot of items in your collection view, you will need to cache the result so it does not impact performance. All attributes should be untouched except for that one header.
Source: I spent 1 month working on this particular topic.

Resources