如何开发自定义的UICollectionViewLayout,其中包含具有自定义单元格的交错列? [英] how to develop a custom UICollectionViewLayout that has staggered columns with self-sizing cells?

查看:61
本文介绍了如何开发自定义的UICollectionViewLayout,其中包含具有自定义单元格的交错列?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用我已经在Android上开发的应用程序的iOS版本.此应用具有以下2列自定义大小(固定宽度但高度可变)单元格的网格:

在Android版本中实现此操作很容易,因为Google为 RecyclerView 提供了 StaggeredGridLayoutManager .您指定列数和滚动方向即可.

默认的 UICollectionView 布局 UICollectionViewFlowLayout 不允许我要的交错布局,因此必须实现自定义布局.我已经观看了2个有关该主题的WWDC视频(

第2步.然后,使用自动布局创建单元并调整其大小.

第3步.然后,控制器通知单元格的大小,以便更新布局.

尝试对这些步骤进行编码时,我会感到疑惑.我找到了教程,它解释了如何使用交错的列,但它不使用自动布局来获取单元格的大小.这给我留下了以下问题:

在步骤2中,如何以及何时获得像元大小?

在第3步中,我如何以及何时可以将更改通知布局?

解决方案

我想指出,正如您所提到的,What's New in Table and Collection Views and Advanced User Interfaces with Collection Views) and I more or less have an idea of how it should be implemented.

Step 1. First an approximation of the layout is computed.

Step 2. Then the cells are created and sized with autolayout.

Step 3. Then the controller notifies the of the cell sizes so the layout is updated.

My doubts come when trying to code these steps. I found a tutorial that explains the creation of a custom layout with staggered columns, but it doesn't use autolayout to obtain the size of the cells. Which leaves me with the following questions:

In step 2, how and when can I obtain the cell size?

In step 3, how and when can I notify the layout of the changes?

解决方案

I want to point out that, as you have mentioned, RayWenderlich PinInterest Layout is exactly the tutorial that'll help you achieve this layout.

To answer your questions - with regards to the tutorial:

In step 2, how and when can I obtain the cell size?

To get the cell height, a delegate method was implemented that was called in the prepareLayout method of the custom UICollectionViewLayout. This method is called once (or twice, I just attempted to run it with a print statement, and I got two calls). The point of prepareLayout is to initialize the cell's frame property, in other words, provide the exact size of each cell. We know that the width is constant, and only the height is changing, so in this line of prepareLayout:

let cellHeight = delegate.collectionView(collectionView!,
      heightForItemAtIndexPath: indexPath, withWidth: width)

We obtain the height of the cell from the delegate method that was implemented in the UICollectionViewController. This happens for all the cells we want to show in the collectionView. After obtaining and modifying the height for each cell, we cache the result so we can inspect it later.

Afterwards, for the collectionView to obtain the size of each cell on screen, all it needs to do is query the cache for the information. This is done in layoutAttributesForElementsInRect method of your custom UICollectionViewLayout class.

This method is called automatically by the UICollectionViewController. When the UICollectionViewController needs layout information for cells that are coming onto the screen (as a result of scrolling, for instance, or upon first load), you return the attributes from the cache that you've populated in prepareLayout.

In conclusion to your question: In step 2, how and when can I obtain the cell size?

Answer: Each cell size is obtained within the prepareLayout method of your custom UICollectionViewFlowLayout, and is calculated early in the life cycle of your UICollectionView.

In step 3, how and when can I notify the layout of the changes?

Note that the tutorial does not account for new cells to be added at runtime:

Note: As prepareLayout() is called whenever the collection view’s layout is invalidated, there are many situations in a typical implementation where you might need to recalculate attributes here. For example, the bounds of the UICollectionView might change – such as when the orientation changes – or items may be added or removed from the collection. These cases are out of scope for this tutorial, but it’s important to be aware of them in a non-trivial implementation.

Like he wrote, it's a non trivial implementation that you might need. There is, however, a trivial (very inefficient) implementation that you might adopt if your data set is small (or for testing purposes). When you need to invalidate the layout because of screen rotation or adding/removing cells, you can purge the cache in the custom UICollectionViewFlowLayout to force prepareLayout to reinitialize the layout attributes.

For instance, when you have to call reloadData on the collectionView, also make a call to your custom layout class, to delete the cache:

cache.removeAll()

这篇关于如何开发自定义的UICollectionViewLayout,其中包含具有自定义单元格的交错列?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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