我想创建一个带有自定义布局的集合视图,它允许单元格跨越多行,如下所示:
http://stripysock.com.au/blog/2013/2/21/creating-a-custom-collection-view-layout
作者还为我们提供了定位单元格和计算内容大小的方法 我找到了另一个啧啧http://damir.me/implementing-uicollectionview-layout 使用源代码,它几乎是我需要的。问题是在这个项目中,单元格只跨越列,因此单元格的高度是固定的,因此逻辑更简单,每行有独立的列。我没有看到任何方式如何改变第二个tut以满足我的需求并决定合成它们。我借用了第二个tut和第二个自定义布局的单元格,集合视图控制器和app委托的实现。
问题:它没有用,集合视图在那里但是单元格没有。我在我的代码和第二个tut中放了一堆NSLog,并发现我的代码不会调用集合视图单元格的initWithFrame方法,尽管它非常相似。
问题:我在这个问题上挣扎了一个星期,无法理解我所缺少的东西。可以有人提出建议吗?
AppDelegate.m
#import "AppDelegate.h"
#import "CollectionViewController.h"
#import "CollectionViewLayout.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//именно здесь мы создаем наш collection view
CollectionViewLayout *collectionViewLayout = [[CollectionViewLayout alloc] init];
NSLog(@"a layout initialized");
CollectionViewController *collectionViewController = [[CollectionViewController alloc] initWithCollectionViewLayout:collectionViewLayout];
NSLog(@"a controller is ready");
[self setWindow:[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]];
[_window setRootViewController:collectionViewController];
[_window makeKeyAndVisible];
NSLog(@"end of app delegate");
return YES;
}
@end
CollectionViewCell.h
#import <UIKit/UIKit.h>
@interface CollectionViewCell : UICollectionViewCell
@property (strong,nonatomic) UILabel *titleLabel;
@end
和CollectionViewCell.m
#import "CollectionViewCell.h"
@implementation CollectionViewCell
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];NSLog(@"super was initialized");
if (self)
{
_titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0,self.bounds.size.height-50, self.bounds.size.width, 40.0)];
self.titleLabel.textColor = [UIColor whiteColor];
self.titleLabel.textAlignment = NSTextAlignmentCenter;
[self.layer setBorderWidth:2];
[self.layer setBorderColor:[UIColor blackColor].CGColor];
[self.contentView addSubview:_titleLabel];
NSLog(@"initializing a cell");
}
return self;
}
@end
CollectionViewLayout.h
#import <UIKit/UIKit.h>
@interface CollectionViewLayout : UICollectionViewLayout
@property (strong, nonatomic) NSMutableArray *itemAttributes;
@end
和CollectionViewLayout.m
#import "CollectionViewLayout.h"
@implementation CollectionViewLayout
- (CGSize)collectionViewContentSize
{
int kNumberOfItemsPerPage = 12;
int numberOfItems = 24;
int numberOfPages = ceil((float)numberOfItems / (float)kNumberOfItemsPerPage);
// Set the size
float pageWidth = self.collectionView.frame.size.width;
float pageHeight = self.collectionView.frame.size.height;
float totalWidth = numberOfPages*pageWidth;
CGSize contentSize = CGSizeMake(totalWidth, pageHeight);
NSLog(@"figuring out content's size");
return contentSize;
}
-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSLog(@"i am there rect attributes ");
return [_itemAttributes filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(UICollectionViewLayoutAttributes *evaluatedObject, NSDictionary *bindings) {
return CGRectIntersectsRect(rect, [evaluatedObject frame]);
}]];
}
- (void)prepareLayout
{
//constants
int kNumberOfItemsPerPage = 12;
float kColumnWidth = 200;
float kPadding = 10;
float kRowHeight = 100;
float kLargeCellWidth = 410;
float kLargeCellHeight = 210;
float kMediumCellHeight = 210;
NSUInteger numberOfItems = [self.collectionView numberOfItemsInSection:0];
for (int item=0;item<numberOfItems;item++)
{
NSLog(@"preparing layout");
NSIndexPath *path = [NSIndexPath indexPathForItem:item inSection:0];
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:path];
// Figure out what page this item is on
int pageNumber = floor((float)item / (float)kNumberOfItemsPerPage);
// Set the horizontal offset for the start of the page
float pageWidth = self.collectionView.frame.size.width;
float horizontalOffset = pageNumber * pageWidth;
// Now, determine which position this cell occupies on the page.
int indexOnPage = item % kNumberOfItemsPerPage;
int column = 0;
switch (indexOnPage) {
case 0:
case 3:
case 5:
column = 0;
NSLog(@"!");
break;
case 1:
case 4:
case 6:
case 9:
column = 1;
NSLog(@"@");
break;
case 2:
case 7:
case 10:
column = 2;
NSLog(@"#");
break;
case 8:
case 11:
column = 3;
NSLog(@"$");
break;
default:
column = 0;NSLog(@"j");
break;
}
NSLog(@"preparing layout stage 2");
int row = 0;
switch (indexOnPage) {
case 0:
case 1:
case 2:
row = 0;
break;
case 3:
case 4:
row = 1;
break;
case 5:
case 6:
case 7:
case 8:
row = 2;
break;
case 9:
case 10:
case 11:
row = 3;
break;
default:
row = 0;
break;
}
horizontalOffset = horizontalOffset + ((kColumnWidth + kPadding) * column);
float verticalOffset = (kRowHeight + kPadding) * row;
NSLog(@"preparing layout stage 3");
// finally, determine the size of the cell.
float width = 10.0;
float height = 10.0;
switch (indexOnPage) {
case 2:
width = kLargeCellWidth;
height = kLargeCellHeight;
NSLog(@"1");
break;
case 5:
width = kColumnWidth;
height = kMediumCellHeight;
NSLog(@"3");
break;
default:
width = kColumnWidth;
height = kRowHeight;
NSLog(@"2");
break;
}
CGRect frame = CGRectIntegral(CGRectMake(horizontalOffset, verticalOffset, width, height));
attributes.frame =frame;
[_itemAttributes addObject:attributes];
NSLog(@"preparing layout complete");
}
}
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return NO;
}
@end
最后,控制器的代码在 CollectionViewController.m
#import "CollectionViewController.h"
#import "CollectionViewCell.h"
@interface CollectionViewController ()
@end
@implementation CollectionViewController
- (id)initWithCollectionViewLayout:(UICollectionViewLayout *)layout
{
self = [super initWithCollectionViewLayout:layout];
if (self) {
[self.collectionView registerClass:[CollectionViewCell class] forCellWithReuseIdentifier:@"cellID"];
self.collectionView.backgroundColor=[UIColor redColor]; }
NSLog(@"initializing controller with a given layout");
return self;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
NSLog(@"returning number of items in section");
return 24;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CollectionViewCell *cell = (CollectionViewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];
cell.titleLabel.text = [NSString stringWithFormat:@"%i", indexPath.row];
NSLog(@"filling the cell with the text");
return cell;
}
@end
P.S我确实知道RFQuiltLayout,GooglePlusLikeLayout和其他类似的东西,但我想自己编写并理解它。任何帮助都将不胜感激!
答案 0 :(得分:0)
我发现重用标识符不匹配。
您正在注册:
[self.collectionView registerClass:[CollectionViewCell class] forCellWithReuseIdentifier:@"cellID"];
然后试图将此列出:
CollectionViewCell *cell = (CollectionViewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];
cellID
必须与cellIdentifier
相同。