Best approach for a UICollectionView to look like

2020-07-24 05:53发布

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:

enter image description here

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:

enter image description here

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!!

Update:

Shouldn't the actual cell frame represent the start of an hour, 10:00 in this example? (Rather than the custom-made separator)

enter image description here

Update

Why does the hierarchy look like this:

enter image description here

This kind of positioning appears to be "blocking" the touch of the cells and the didSelectItemAtIndexPath method doesn't get called. This applies to the cells that appear further back than the other ones.

enter image description here

3条回答
欢心
2楼-- · 2020-07-24 06:24

As per discussion in comments on the question, using the Custom Collection View Layout library linked in the question is suitable for the mentioned problem which can be easily integrated using CocoaPods.

UICollectionView is highly customizable using custom UICollectionViewLayout. See the official apple documentation for creating custom layouts.

To be frank, Apple's documentation is too overwhelming for most of us. So, you can look up (google) custom UICollectionViewLayout tutorial, go through any one you find the easiest and go on to use the library to your specific needs.

查看更多
啃猪蹄的小仙女
3楼-- · 2020-07-24 06:26

I don't think this is so hard to do.

You just need a different perspective, than what you tried.

Make all the CollectionView cells the same size. They represent 1h time, so they should have equal size.

Then have another view in each cell. This is the one that show that there is an event. This view you will give a color, and place it in the cell according to the time when the event start or finish. So in the cellForRowAtIndexPath, you would check your events and if this cell have any event then you are going to show this event view, color it, and position it. If you make the cells height 60, it gets super easy to position the view. For example if the event start at 1:20, at the cell for hour 1, you will size the event view (0, 20, 320, 40).

查看更多
Anthone
4楼-- · 2020-07-24 06:33

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.

When subclassing UICollectionViewLayout, you need to implement a few methods:

  • collectionViewContentSize should return a height equal to the number of hours (24) multiplied by the height of a supplementary view representing an hour.
  • prepareLayout does 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:

Sample

查看更多
登录 后发表回答