UICollectionViewCell 使用原型尺寸
Posted
技术标签:
【中文标题】UICollectionViewCell 使用原型尺寸【英文标题】:UICollectionViewCell using prototype sizes 【发布时间】:2014-03-17 23:00:08 【问题描述】:我有一个 UICollectionView,其中包含三个不同的原型单元格,每个单元格都通过 Storyboard 设置不同的高度。在运行时,Collection View 使用自己的单元格大小,忽略我的 Storyboard 的。
我目前正在使用 collectionView:layout:sizeForItemAtIndexPath: 和几个条件来直接设置每个 CGSize。
有没有更好的方法来设置单元格大小?我似乎无法检索每个单元格的 Storyboard 大小,而且 CGSizeMake 似乎太硬编码并且不是很灵活。
【问题讨论】:
【参考方案1】:目前似乎没有简单的方法:
从 Storyboard 中获取 UICollectionViewCell 原型单元大小运行时。 只需在一处管理原型单元的大小(而不必在故事板单元原型中输入它们并实施sizeForItemAtIndexPath
)。
建议的方法here(用于UITableViews)不起作用,因为在sizeForItemAtIndexPath
中使用dequeueReusableCellWithReuseIdentifier
会导致无限循环。
但是,我设法通过以下方式做到了这一点:
在所有 Storyboard 中的每个 UICollectionView
原型单元格中添加一个唯一的(在每个故事板中的所有 UICollectionViewCell
s 中)重用标识符。
使用从所有 Storyboard 中提取 UICollectionViewCell
帧大小的脚本,将 Run script
构建阶段添加到您的项目中。
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
这将创建一个名为 StoryboardPrototypeCellSizes.h
的头文件,其中包含以下示例内容:
@@"TodayCell" : [NSValue valueWithCGSize:CGSizeMake(320, 80)],
@"SpecialDayCell" : [NSValue valueWithCGSize:CGSizeMake(320, 42)],
@"NameDayCell" : [NSValue valueWithCGSize:CGSizeMake(320, 30)];
添加一个辅助方法以在控制您的 UICollectionView
的视图控制器中返回 UICollectionViewCell
重用标识符:
- (NSString *)cellReuseIdentifierAtIndexPath:(NSIndexPath *)indexPath
switch (indexPath.item)
case 0: return @"TodayCell";
case 1: return @"SpecialDayCell";
case 2: return @"NameDayCell";
return nil;
确保在cellForItemAtIndexPath
中使用相同的重用标识符:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
UICollectionViewCell *cell =
[collectionView dequeueReusableCellWithReuseIdentifier:
[self cellReuseIdentifierAtIndexPath:indexPath]
forIndexPath:indexPath];
...
终于实现sizeForItemAtIndexPath
:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
NSDictionary *storyboardPrototypeCellSizes =
#import "StoryboardPrototypeCellSizes.h"
return [(NSValue *)storyboardPrototypeCellSizes[
[self cellReuseIdentifierAtIndexPath:indexPath]
] CGSizeValue];
此解决方案允许您在 Storyboard(s) 中仅定义一次 UICollectionViewCell
原型单元大小,并且在运行时也不会执行任何不符合 App Store 的操作。
****Edit:**** 您还可以通过添加另一个具有相同内容的脚本并将“collectionViewCell”替换为“collectionReusableView”并将头文件重命名为例如 StoryboardReusableViewSizes.h 来获取 UICollectionReusableView 大小
【讨论】:
海拉作弊,但是...很棒。 对于那些在 ios 8 发布后来到这里的人,解决这个问题的方法是使用自调整大小的单元格。通过自动布局单元格,使其宽度/高度根据内容大小而变化,可以让 CollectionView 调整单元格的大小以适应其内容。 '这里提出的方法(用于 UITableViews)不起作用,因为在 sizeForItemAtIndexPath 中使用 dequeueReusableCellWithReuseIdentifier 会导致无限循环。这个真的帮了我很大的忙,因为我不知道为什么我的应用程序总是崩溃。【参考方案2】:没有更好的方法来设置单元格大小。单元格大小在 UICollectionView 中的多个位置使用 - 用于定位,用于滚动指示器。例如,如果用户滚动收集具有数千个小单元格的集合,尽快接收它们是非常重要的。因此,创建单元格并询问其大小不是一种选择。您必须实现 collectionView:layout:sizeForItemAtIndexPath: 并且它应该可以快速运行。
【讨论】:
【参考方案3】:您是否在UICollectionView
中使用流式布局?如果是,您可以使用UICollectionViewDelegateFlowLayout
协议的sizeForItemAtIndexPath
方法来提供单元格的大小。如果您在应用程序中使用 OSS 组件没有问题,可以使用RFQuiltLayout 来实现此目的。
【讨论】:
就像我在问题本身中提到的那样,我目前正在使用 sizeForItemAtIndexPath。另外,我可能错了,但 RFQuiltLayout 不会将集合分成小块吗?我认为它不适合与几个不成比例的可变高度单元格一起使用(例如,一个是 90 点,另一个是 131 点,最后一个是 78 点高)。 您提到UICollectionView
中有三个不同的原型单元格,您是否探索过使用 Autolayout 布置它们的子视图? Obc.io 在UICollectionView
布局上有一个nice article。在 UICollectionView 中使用 Autolayout 的示例是 here。根据我的经验,最好使用UICollectionView
的布局对象来控制每个单元格的大小和位置,同时使用Autolayout来布局子视图?
我们越来越接近我想要的结果了!这是一篇很棒的文章。我正在尝试完全按照这些思路进行操作,但我正在寻找一种方法来使用我在 Storyboard Collection View 中实例化的 Storyboard 单元,而不是在外部创建一个 XIB 并以编程方式注册它们。有什么想法吗?编辑:我尝试通过标签号实例化它们,但这似乎不起作用。另外,我不能在 sizeForItem 中出列。以上是关于UICollectionViewCell 使用原型尺寸的主要内容,如果未能解决你的问题,请参考以下文章
如何正确设置 UICollectionViewCell 边距?
根据标签文本自定义 UICollectionViewCell 自身大小
UICollectionViewCell 中的 UILabel 布局怪异
Xamarin iOS:从情节提要中的 UICollectionViewCell 获取信息