我根据客户的设计规范为客户构建自定义UICollectionViewLayout
,以实现他们想要的外观和流程。我遇到的问题涉及我定位的单元格大小。
单元格可能具有不同的尺寸,而我所采用的布局样式需要特定的间距要求,以便单元格不会相互重叠,这意味着在重载{ {1}}在布局中,我希望查看项目大小,以便在计算中正确设置和使用。
我遇到的问题是-layoutAttributesForItemAtIndexPath:
似乎依赖于此方法来设置单元格的大小,因为在我设置属性之前,我使用任何方法从a获取大小单元格将始终生成UICollectionView
。
这是我必须要设计的东西吗?故事板中单元格的大小是不可访问的(至少我目前所知的方法)所以除了使用特定的宽度/高度之外,我还没有能够解决这个问题。 (仅适用于两个可能的单元格之一)来测试和编写布局代码。
最终:如何获取CGSizeZero
中UICollectionViewCell
的大小以用于计算?。
修改
我尝试过以下方法:
UICollectionViewLayout
答案 0 :(得分:6)
我从未找到避免在代码中重复大小计算的方法。这就是我通常做的事情:
布局可以与其集合视图对话以查找大小(以及最小项目间距等内容)。您可以在-prepareLayout
或-layoutAttributesForItemAtIndexPath:
:
if ([self.collectionView.delegate respondsToSelector:@selector(collectionView:layout:sizeForItemAtIndexPath:)]) {
id<UICollectionViewDelegateFlowLayout> delegate = (id<UICollectionViewDelegateFlowLayout>) self.collectionView.delegate;
size = [delegate collectionView:self.collectionView layout:self sizeForItemAtIndexPath:indexPath];
}
else {
size = self.itemSize;
}
现在,您的集合视图委托只需要能够响应collectionView:layout:sizeForItemAtIndexPath:
,即使没有自定义布局类也是如此。
有时提供正确的尺寸有点麻烦。没有神奇的方法来获得单元格的大小而没有实际实例化并放置它,所以我总是自己编写代码。我的大多数集合视图单元都有一个类方法:
+ (CGSize)sizeWithItem:(id<MyDisplayableItem>)item;
当我需要一个单元格所需的大小时,我从我的集合视图委托中调用它:
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
Note* note = self.notes[indexPath.item];
CGSize result = [CSDetailNoteCell sizeWithNote:note];
// or [MyCell sizeWithItem:myItem andMyOtherItem:somethingElse]
return result;
}
不幸的是,+sizeWithItem:
方法并非免费提供,但至少它将大小计算封装在Cell类中。我倾向于在类中存储一个常量,表示永远不会改变的事物的大小(填充,也许是图像)。然后,我将固定大小与需要动态计算的内容相结合,以找到最终大小。动态内容通常包括对NSString的-boundingRectWithSize:options:attributes:context:
等的一些调用。
此示例使用宽度始终为320的单元格,但我认为足以获得该点。这是来自CSDetailNoteCell.m
的代码。
static CGFloat const CSDetailNoteCellWidth = 320.f;
static CGFloat const CSDetailNoteCellHeightConstant =
10 + // top padding
16 + // date label height
0 + // padding from date label to textview
8 + // textview top padding
8 + // textview bottom padding
22 // bottom padding
;
...
+ (CGFloat)textWidth {
return CSDetailNoteCellTextViewWidth - 10; // internal textview padding
}
+ (CGSize)sizeWithNote:(CSNote *)note {
CGFloat textHeight = [self _textHeightWithText:note.text];
CGSize result = CGSizeMake(CSDetailNoteCellWidth, CSDetailNoteCellHeightConstant + textHeight);
return result;
}
+ (CGFloat)_textHeightWithText:(NSString*)text {
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
CGSize maxSize = CGSizeMake(CSDetailNoteCell.textWidth, CGFLOAT_MAX);
NSDictionary* attributes = @{NSFontAttributeName: CSDetailNoteCell.font, NSParagraphStyleAttributeName: paragraphStyle};
CGRect boundingBox = [text boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil];
CGFloat textHeight = ceilf(boundingBox.size.height);
return textHeight;
}