UICollectionViewCell使用原型尺寸

我有一个UICollectionView有三个不同的原型单元格,每个原型单元格都通过Storyboard设置不同的高度。 在运行时,集合视图使用自己的单元大小,忽略我的故事板。

我目前正在使用collectionView:layout:sizeForItemAtIndexPath:用一对条件来设置每个CGSize直。

有没有更好的方法来设置单元格大小? 我似乎无法获取每个单元格的Storyboard尺寸,而CGSizeMake似乎太硬编码,并且不够灵活。

看来,目前还没有简单的方法来:

  • 从Storyboard(s)获取UICollectionViewCell原型单元大小运行时。
  • 在一个地方pipe理原型单元格的大小(而不必在Storyboard单元格原型中input它们并实现sizeForItemAtIndexPath )。

这里提出的方法(对于UITableViews)不起作用,因为在sizeForItemAtIndexPath使用dequeueReusableCellWithReuseIdentifier将导致无限循环。

但是,我已经设法做到这一点如下

  1. 在所有Storyboard中的每个UICollectionView原型单元中添加一个唯一的( UICollectionViewCell所有故事板中的所有UICollectionViewCell )重用标识符。

  2. 使用从所有Storyboard中抽取UICollectionViewCell帧大小的脚本,将Run script构build阶段添加到项目中。

     output=${PROJECT_DIR}/StoryboardPrototypeCellSizes.h printf "@{" > $output for storyboard in $(find ${PROJECT_DIR} -name "*.storyboard") do echo "Scanning storyboard $storyboard..." delimiter= for line in $(xpath $storyboard "//collectionViewCell/@reuseIdentifier[string-length()>0] | //collectionViewCell/rect" 2>&-) do case $line in reuseIdentifier*) reuseIdentifier=$(sed 's/[^"]*"\([^"]*\)".*/\1/' <<< $line) ;; width*) if [ -n "$reuseIdentifier" ]; then width=$(sed 's/[^"]*"\([^"]*\)".*/\1/' <<< $line) fi ;; height*) if [ -n "$reuseIdentifier" ]; then height=$(sed 's/[^"]*"\([^"]*\)".*/\1/' <<< $line) fi ;; esac if [ -n "$reuseIdentifier" ] && [ -n "$width" ] && [ -n "$height" ]; then printf "$delimiter@\"$reuseIdentifier\" : [NSValue valueWithCGSize:CGSizeMake($width, $height)]" >> $output unset reuseIdentifier unset width unset height delimiter=,\\n fi done done printf "};\n" >> $output 

    这将创build一个名为StoryboardPrototypeCellSizes.h的头文件,其中包含以下示例内容:

     @{@"TodayCell" : [NSValue valueWithCGSize:CGSizeMake(320, 80)], @"SpecialDayCell" : [NSValue valueWithCGSize:CGSizeMake(320, 42)], @"NameDayCell" : [NSValue valueWithCGSize:CGSizeMake(320, 30)]}; 
  3. 添加一个帮助器方法来在控制你的UICollectionView的视图控制器中返回UICollectionViewCell重用标识符:

     - (NSString *)cellReuseIdentifierAtIndexPath:(NSIndexPath *)indexPath { switch (indexPath.item) { case 0: return @"TodayCell"; case 1: return @"SpecialDayCell"; case 2: return @"NameDayCell"; } return nil; } 
  4. 请确保在cellForItemAtIndexPath使用相同的重用标识符:

     - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier: [self cellReuseIdentifierAtIndexPath:indexPath] forIndexPath:indexPath]; ... 
  5. 最后实现sizeForItemAtIndexPath

     - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { NSDictionary *storyboardPrototypeCellSizes = #import "StoryboardPrototypeCellSizes.h" return [(NSValue *)storyboardPrototypeCellSizes[ [self cellReuseIdentifierAtIndexPath:indexPath] ] CGSizeValue]; } 

该解决scheme允许您在Storyboard中仅定义一次UICollectionViewCell原型单元大小,并且在运行时也不执行任何非App-Store兼容。

****编辑:****您还可以通过添加具有相同内容的另一个脚本并用“collectionReusableView”replace“collectionViewCell”并将头文件重命名为例如StoryboardReusableViewSizes.h来获取UICollectionReusableView大小。

没有更好的方法来设置单元格大小。 单元格大小在UICollectionView的几个地方使用 – 定位,滚动指示器。 例如,如果用户用数千个小小区滚动收集,则尽可能快地接收它们是非常重要的。 所以创build单元格并询问它的大小不是一个选项。 你必须实现collectionView:layout:sizeForItemAtIndexPath:它应该很快。

你在你的UICollectionView使用stream布局吗? 如果是,则可以使用sizeForItemAtIndexPath协议的sizeForItemAtIndexPath方法来提供单元的大小。 如果您在应用程序中使用OSS组件没有问题, 则可以使用RFQuiltLayout来实现此目的。