I'm building an app where I really need to display a list like the one seen in the iOS calendar app. I need to create a collectionView where I can have cells that expand enough to cover their respective hours, like so:
I've tried various things, including this project at Github which I didn't understand how to use in another project
As well as this project I quickly made with a UITableViewController while exploring different methods:
But I'm not really getting where I want to. I need to have the design seen in the first picture and was wondering if anyone could point me in the right direction to achieve that?
Thank you so much for help!!
Shouldn't the actual cell frame represent the start of an hour, 10:00 in this example? (Rather than the custom-made separator)
Why does the hierarchy look like this:
This kind of positioning appears to be "blocking" the touch of the cells and the
You should indeed use a
UICollectionView along with a custom layout. Just provide
supplementary views to build the underlying daily schedule (one view per hour), and then use the
cells to lay down your events.
UICollectionViewLayout, you need to implement a few methods:
collectionViewContentSizeshould return a height equal to the number of hours (24) multiplied by the height of a supplementary view representing an hour.
prepareLayoutdoes almost everything. In that method, you calculate every layoutAttributes you will need to use. By getting the time of the event and its duration, you are able to compute the frame of every event. The supplementary view frames (every single "hour" block) are pretty straightforward too, since their height is fixed (origin.y = fixed height multiplied by the hour).
layoutAttributesForElementsInRect:simply iterates through your previously prepared layoutAttributes and returns all whose frame intersect the provided frame.
layoutAttributesForItemAtIndexPath: finds and returns the cell's layoutAttributes that match the provided indexPath.
layoutAttributesForSupplementaryViewOfKind:atIndexPath finds and returns the supplementary view's layoutAttributes that math the provided indexPath.
Next, you give an instance of that layout to a collection view:
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:myCustomLayout]
Then, you only need to provide the required views for the supplementary views (a.k.a the hour blocks) and the cells, via the UICollectionView's delegate & dataSource. Feel free to create a custom delegate in your custom layout if you need the UIViewController to provide more info that you have with the standard delegate/dataSource!
Note: Since the line that indicate the start of an hour is a few pixels below the cell's top border, you need to shift every time of event by the same number of pixels. Say you have 6 pixels above every line and every hour block has a height of 60 pixels, then if an even start at 2AM, you will set its
origin.y = 2 * 60 + 6 (2 hours * 60 pixels per hour + 6 pixels padding). You will also need to adjust you last cell block to be 6 pixels taller since it won't have another cell below.
I recommend you to read the official documentation about creating custom layouts.
To help you: I made a quick sample project since making your own layout can sometime be troublesome. Go check the
CalendarViewLayout class, I added a few comments to explain how I dealt with the padding. Here is was it looks like: