我正在摆弄新的UICollectionView和UICollectionViewLayout类。我创建了一个自定义布局,子类化UICollectionViewFlowLayout。
我的单元格大小正在动态变化,我使用下面的委托方法设置项目大小
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"SETTING SIZE FOR ITEM AT INDEX %d", indexPath.row);
return CGSizeMake(80, 80);
}
现在,在我的自定义UICollectionViewFlowLayout类的prepareLayout方法下,我需要访问这些大小变量,以便我可以计算如何放置它们并为layoutAttributesForItemAtIndexPath缓存它们。
但是,我似乎无法在UICollectionView或UICollectionViewFlowLayout下找到任何属性来达到我在委托方法中设置的自定义项目大小。
答案 0 :(得分:13)
自己找到它。
在不遗漏UICollectionViewDelegateFlowLayout
@interface SECollectionViewCustomLayout : UICollectionViewFlowLayout
<UICollectionViewDelegateFlowLayout>
然后你可以打电话
CGSize size = [self collectionView:self.collectionView
layout:self
sizeForItemAtIndexPath:indexPath];
答案 1 :(得分:8)
查看各种UICollectionView...
头文件,并观看WWDC 2012 Session 219 - Advanced Collection Views and Building Custom Layouts视频(从大约6:50开始),似乎可扩展委托模式利用动态类型来确保布局正确访问其扩展的委托方法。
UI(Collection)ViewController
)应声明自己支持此自定义协议。
UICollectionViewFlowLayout
或其子类,这只是表示声明与UICollectionViewDelegateFlowLayout
的一致性。 .m
布局标题放入代理人的界面,请随意在#import
文件的类扩展中执行此操作。 collectionView
属性,将委托转换为符合所需协议的对象以说服编译器。 respondsToSelector:
。实际上,如果您愿意,对所有方法执行此操作都没有坏处,因为类型转换意味着没有运行时保证委托甚至可以实现所需的方法。
因此,如果您实现了一个自定义布局,需要委托来处理某些信息,那么您的标题可能如下所示:
@protocol CollectionViewDelegateCustomLayout <UICollectionViewDelegate>
- (BOOL)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)layout
shouldDoSomethingMindblowingAtIndexPath:(NSIndexPath *)indexPath;
@end
@interface CustomLayout : UICollectionViewLayout
// ...
@end
你的代表声明了一致性(我在这里的实现文件中已经这样做了):
#import "CustomLayout.h"
@interface MyCollectionViewController () <CollectionViewDelegateCustomLayout>
@end
@implementation
// ...
- (BOOL)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)layout
shouldDoSomethingMindblowingAtIndexPath:(NSIndexPath *)indexPath
{
return [self canDoSomethingMindblowing];
}
// ...
@end
在布局的实现中,您可以访问以下方法:
BOOL blowMind;
if ([self.collectionView.delegate respondsToSelector:@selecor(collectionView:layout:shouldDoSomethingMindblowingAtIndexPath:)]) {
blowMind = [(id<CollectionViewDelegateCustomLayout>)self.collectionView.delegate collectionView:self.collectionView
layout:self
shouldDoSomethingMindblowingAtIndexPath:indexPath];
} else {
// Perhaps the layout also has a property for this, if the delegate
// doesn't support dynamic layout properties...?
// blowMind = self.blowMind;
}
请注意,在这里进行类型转换是安全的,因为我们正在检查委托事先是否事先响应了该方法。
这只是猜测,但我怀疑Apple是如何管理UICollectionViewDelegateFlowLayout
协议的。
delegate
属性,因此调用必须通过集合视图的委托进行。UICollectionViewController
不公开符合扩展流布局委托(我怀疑它是在另一个私有标头中这样做的。)UICollectionView
的{{1}}属性仅声明符合'base'delegate
协议。同样,我怀疑流布局正在使用UICollectionViewDelegate
的私有子类/类别,以防止需要进行类型转换。为了进一步增加这一点,Apple不鼓励在文档(Collection View Programming Guide for iOS: Creating Custom Layouts)中对UICollectionView
进行子类化:避免继承UICollectionView。集合视图很少或没有自己的外观。相反,它从数据源对象中提取其所有视图,并从布局对象中提取所有与布局相关的信息。
所以我们走了。并不复杂,但值得知道如何做到范式友好的方式。
答案 2 :(得分:4)
在GitHub上查看UICollectionView-FlowLayout。同样的想法,这只是使得访问flowLayout的扩展委托方法更加清晰。
答案 3 :(得分:0)
对于后来的读者,IOS 7具有定义它的UICollectionViewFlowLayout。
答案 4 :(得分:0)
在我的例子中,关于布局,单元格布局等的所有内容都在UIViewController的nib中定义,并为UICollectionViewCell分别定义nib。 MyCollectionViewCell
包含UIImageView
,其自动布局为带有填充/边距但为方形的单元格。
我需要圆形图标而不是平方但不想照顾我用于iPhone或iPad的笔尖(我有单独的笔尖用于设备和方向)。
我不想将@selector(collectionView:layout:sizeForItemAtIndexPath:)
实施到我的视图控制器中。
所以,在collectionView:cellForItemAtIndexPath:
内
我可以使用
CGSize size = cell.imageView.bounds.size;
cell.imageView.layer.masksToBounds = YES;
cell.imageView.layer.cornerRadius = size.height/2.0;
因为collectionView:layout:sizeForItemAtIndexPath:
在collectionView:cellForItemAtIndexPath:
之前调用并且布局已完成。
您可以查看底部的圆形头像