【发布时间】:2014-07-14 16:04:48
【问题描述】:
我想创建一个具有自定义布局的集合视图,它允许单元格跨越多行,如下所示:
http://stripysock.com.au/blog/2013/2/21/creating-a-custom-collection-view-layout
还有一位作者为我们提供了定位单元格和计算内容大小的方法。
我找到了另一个啧啧http://damir.me/implementing-uicollectionview-layout
使用源代码,这几乎是我所需要的。问题是在这个项目中,单元格只跨越列,所以单元格的高度是固定的,因此每行都有独立列的更简单的逻辑。我没有看到任何关于如何更改第二个 tut 以满足我的需要的方法,并决定合成它们。我从第二个 tut 和第一个自定义布局借用了单元格、集合视图控制器和应用程序委托的实现。
问题:它不起作用,集合视图存在但单元格不存在。我在我的代码和第二个 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 和其他类似的东西,但我想自己编写并理解它。任何帮助将不胜感激!
【问题讨论】:
-
欢迎来到 SO。您能否缩小您的问题范围。您在这里有很多代码,但您没有确定错误发生的位置(如堆栈跟踪等)。请帮助我们帮助您。 :)
-
@kgdesouz 没有错误。这可行,但不应该这样做。基本上,这段代码很简单,可以工作,但有另一种布局。所有关于单元格的东西都是从 tut 带来的。据我所知,单元格和布局是独立的,彼此一无所知。那么为什么它不初始化单元格呢?这就是问题所在。为了更清楚,您可以从这里下载 tut:damir.me/implementing-uicollectionview-layout
-
你有没有想过解决方案?
标签: ios objective-c xcode uicollectionview uicollectionviewcell