UICollectionView看起来像iOS日历应用程序的最佳方法 [英] Best approach for a UICollectionView to look like the iOS calendar app

查看:33
本文介绍了UICollectionView看起来像iOS日历应用程序的最佳方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个应用程序,在这里我确实需要显示一个列表,例如iOS日历应用程序中显示的列表.我需要创建一个collectionView,在其中可以使单元格扩展到足以覆盖其各自的小时数,例如:

我尝试过各种方法,包括Github上的

这种定位似乎是在阻塞"单元格的触摸,并且不会调用 didSelectItemAtIndexPath 方法.这适用于比其他单元格更靠后的单元格.

解决方案

您确实应该使用 UICollectionView 以及自定义布局.只需提供补充视图来构建基本的日程安排(每小时一个视图),然后使用 cells 布置事件即可.

子类化 UICollectionViewLayout 时,您需要实现一些方法:

  • collectionViewContentSize 的高度应等于小时数(24)乘以表示一个小时的补充视图的高度.
  • prepareLayout 几乎可以执行所有操作.在该方法中,您将计算需要使用的每个 layoutAttributes .通过获取事件的时间及其持续时间,您可以计算每个事件的帧.补充视图框架(每个单个的小时"块)也非常简单,因为它们的高度是固定的(origin.y =固定高度乘以小时).
  • layoutAttributesForElementsInRect:简单地循环访问先前准备的 layoutAttributes ,并返回所有与提供的帧相交的帧.
  • layoutAttributesForItemAtIndexPath:查找并返回与提供的indexPath相匹配的单元格的 layoutAttributes .

  • layoutAttributesForSupplementaryViewOfKind:atIndexPath 查找并返回补充视图的 layoutAttributes ,该数学视图提供的indexPath.

接下来,您将该布局的一个实例提供给集合视图:

  self.collectionView = [[UICollectionView分配] initWithFrame:CGRectZero collectionViewLayout:myCustomLayout] 

然后,您只需通过UICollectionView的委托&数据源.如果需要UIViewController来提供标准委托/数据源提供的更多信息,请随时在自定义布局中创建自定义委托!

注意:由于指示一个小时开始的行在单元格的顶部边框下方几像素,因此您需要在每次事件时将相同数量的像素移动.假设您在每行上方有6个像素,并且每个小时块的高度为60像素,那么如果从2AM开始偶数开始,则将其 origin.y = 2 * 60 + 6 (2小时*每小时60像素+填充6像素).您还需要将最后一个像元块调整为高6像素,因为它下面没有另一个像元.

我建议您阅读官方文档关于创建自定义布局.

为您提供帮助:我创建了一个快速示例项目,制作自己的布局有时会很麻烦.去检查 CalendarViewLayout 类,我添加了一些注释来解释如何处理填充.看起来是这样的:

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

Update:

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

Update

Why does the hierarchy look like this:

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.

解决方案

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:

这篇关于UICollectionView看起来像iOS日历应用程序的最佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆