Iphone 调用setCollectionViewLayout:animated不会重新加载UICollectionView
我将UICollectionView与两个自定义布局一起使用,它们是从Iphone 调用setCollectionViewLayout:animated不会重新加载UICollectionView,iphone,objective-c,uicollectionview,Iphone,Objective C,Uicollectionview,我将UICollectionView与两个自定义布局一起使用,它们是从UICollectionViewFlowLayout 首次加载视图时,我使用以下命令将其设置为默认视图: [self.collectionView setCollectionViewLayout:self.tableViewLayout]; 这将调用:cellForItemAtIndexPath——因此没有问题。这在视图中将出现方法中 然后我使用UIButton将布局从当前视图更改为下一个布局,如下所示: -(void)ch
UICollectionViewFlowLayout
首次加载视图时,我使用以下命令将其设置为默认视图:
[self.collectionView setCollectionViewLayout:self.tableViewLayout];
这将调用:cellForItemAtIndexPath
——因此没有问题。这在视图中将出现方法中
然后我使用UIButton将布局从当前视图更改为下一个布局,如下所示:
-(void)changeViewLayoutButtonPressed
{
self.changeLayout = !self.changeLayout;
if (self.changeLayout){
[self.tradeFeedCollectionView setCollectionViewLayout:self.grideLayout animated:YES];
}
else {
[self.tradeFeedCollectionView setCollectionViewLayout:self.tableViewLayout animated:YES];
}
}
@property (strong, nonatomic) BBTradeFeedTableViewLayout *tableViewLayout;
@property (strong, nonatomic) BBTradeFeedGridViewLayout *grideLayout;
在此调用之后,将调用
numberOfItemsInSection
。我已在调试器中检查返回帐户是否不为零
在该调用之后,不会调用任何其他内容,my UICollectionView会更改布局,但由于未调用cellForItemAtIndexPath
,因此单元格设置不正确
如果我将[self.collectionView roloadData]
放在numberOfItemsInSection
中,则调用cellForItemAtIndexPath
并设置单元格
我不需要手动调用来重新加载numberOfItemsInSection
中的数据。有人能告诉我发生了什么事吗
编辑
我忘了提到我正在为两个不同的单元格使用两个不同的UINIB,因为它们需要应用稍微不同的布局。这会是一个问题吗?
谢谢
编辑2
对,所以我让它几乎像我想要的那样工作。下面是用于集合视图的所有代码,以及我如何更改其布局
自定义布局
这些是从UICollectionViewFlowLayout
子类化的-我之所以子类化是因为我的UICollectionView
的外观和行为需要非常接近苹果预先制作的布局。不过,细胞大小不同
TableViewLayout
-头文件中没有代码。
-BBTradeFeedTableViewLayout.m
@implementation BBTradeFeedTableViewLayout
-(id)init
{
self = [super init];
if (self){
self.itemSize = CGSizeMake(320, 80);
self.minimumLineSpacing = 0.1f;
}
return self;
}
@end
@implementation BBTradeFeedGridViewLayout
-(id)init
{
self = [super init];
if (self){
self.itemSize = CGSizeMake(159, 200);
self.minimumInteritemSpacing = 0.1f;
self.minimumLineSpacing = 0.1f;
}
return self;
}
@end
网格布局
-头文件中没有代码。
-BBTradeFeedGridViewLayout.m
@implementation BBTradeFeedTableViewLayout
-(id)init
{
self = [super init];
if (self){
self.itemSize = CGSizeMake(320, 80);
self.minimumLineSpacing = 0.1f;
}
return self;
}
@end
@implementation BBTradeFeedGridViewLayout
-(id)init
{
self = [super init];
if (self){
self.itemSize = CGSizeMake(159, 200);
self.minimumInteritemSpacing = 0.1f;
self.minimumLineSpacing = 0.1f;
}
return self;
}
@end
然后在包含我的UICollectionView
的ViewController
中,我声明如下两个自定义布局:
-(void)changeViewLayoutButtonPressed
{
self.changeLayout = !self.changeLayout;
if (self.changeLayout){
[self.tradeFeedCollectionView setCollectionViewLayout:self.grideLayout animated:YES];
}
else {
[self.tradeFeedCollectionView setCollectionViewLayout:self.tableViewLayout animated:YES];
}
}
@property (strong, nonatomic) BBTradeFeedTableViewLayout *tableViewLayout;
@property (strong, nonatomic) BBTradeFeedGridViewLayout *grideLayout;
然后为collectionView注册两个.xib文件:
[self.tradeFeedCollectionView registerNib:[UINib nibWithNibName:@"BBItemTableViewCell" bundle:nil] forCellWithReuseIdentifier:@"TableItemCell"];
[self.tradeFeedCollectionView registerNib:[UINib nibWithNibName:@"BBItemGridViewCell" bundle:nil] forCellWithReuseIdentifier:@"GridItemCell"];
[self.collectionView removeFromSuperview]; //First remove the Collection View
//Relocate the view with layouts
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
layout.minimumInteritemSpacing = 10;
layout.minimumLineSpacing = 10;
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.width,100) collectionViewLayout:layout];
[self.collectionView setDataSource:self];
[self.collectionView setDelegate:self];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellIdentifier"];
[self.collectionView reloadData];
[self.view addSubview:self.collectionView];
然后,我有一个更改布局的UIButton:
-(void)changeViewLayoutButtonPressed
{
if (!self.gridLayoutActive){
self.gridLayoutActive = YES;
[self.tradeFeedCollectionView setCollectionViewLayout:self.grideLayout animated:YES];
self.lastLayoutUsed = @"GridLayout";
}
else {
self.gridLayoutActive = NO;
[self.tradeFeedCollectionView setCollectionViewLayout:self.tableViewLayout animated:YES];
self.lastLayoutUsed = @"TableLayOut";
}
[self.tradeFeedCollectionView reloadItemsAtIndexPaths:[self.tradeFeedCollectionView indexPathsForVisibleItems]];
}
最后,当web服务调用完成时,它调用[self.tradeFeedCollectionView reloadData]代码>
因此,我的UICollectionView
被重新加载,最后一个方法是:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{ static NSString *tableCellIdentifier = @"TableItemCell";
static NSString *gridCellIdentifier = @"GridItemCell";
if (indexPath.item < [self.tradeSearchArray count]){
if (self.gridLayoutActive == NO){
BBItemTableViewCell *tableItemCell = [collectionView dequeueReusableCellWithReuseIdentifier:tableCellIdentifier forIndexPath:indexPath];
if ([self.tradeSearchArray count] > 0){
self.toolBarButtomItem.title = [NSString stringWithFormat:@"%d Results", self.searchResult.searchResults];
tableItemCell.gridView = NO;
tableItemCell.backgroundColor = [UIColor whiteColor];
tableItemCell.item = self.tradeSearchArray[indexPath.row];
}
return tableItemCell;
}else
{
BBItemTableViewCell *gridItemCell= [collectionView dequeueReusableCellWithReuseIdentifier:gridCellIdentifier forIndexPath:indexPath];
if ([self.tradeSearchArray count] > 0){
self.toolBarButtomItem.title = [NSString stringWithFormat:@"%d Results", self.searchResult.searchResults];
gridItemCell.gridView = YES;
gridItemCell.backgroundColor = [UIColor whiteColor];
gridItemCell.item = self.tradeSearchArray[indexPath.row];
}
return gridItemCell;
}
-(UICollectionViewCell*)collectionView:(UICollectionView*)collectionView cellForItemAtIndexPath:(NSIndexPath*)indexPath
{静态NSString*tableCellIdentifier=@“TableItemCell”;
静态NSString*gridCellIdentifier=@“GridItemCell”;
if(indexath.item<[self.tradeSearchArray count]){
if(self.gridLayoutActive==否){
BBItemTableViewCell*tableItemCell=[collectionView dequeueReusableCellWithReuseIdentifier:tableCellIdentifier for indexPath:indexPath];
如果([self.tradeSearchArray count]>0){
self.toolbarbuttonmitem.title=[NSString stringWithFormat:@“%d个结果”,self.searchResult.searchResults];
tableItemCell.gridView=否;
tableItemCell.backgroundColor=[UIColor whiteColor];
tableItemCell.item=self.tradeSearchArray[indexath.row];
}
返回表项单元格;
}否则
{
BBItemTableViewCell*gridItemCell=[collectionView dequeueReusableCellWithReuseIdentifier:gridCellIdentifier forIndexPath:indexPath];
如果([self.tradeSearchArray count]>0){
self.toolbarbuttonmitem.title=[NSString stringWithFormat:@“%d个结果”,self.searchResult.searchResults];
gridItemCell.gridView=是;
gridItemCell.backgroundColor=[UIColor whiteColor];
gridItemCell.item=self.tradeSearchArray[indexath.row];
}
返回gridItemCell;
}
上述代码的问题
上面的代码确实有效。但是,单元格的动画效果不好,看起来很奇怪,几乎就像发生了刷新。这是由于调用:
[self.tradeFeedCollectionView重载itemsatindexpaths:[self.tradeFeedCollectionView indexPathsForVisibleItems]];
但这是我能让它接近我想要的东西的唯一方法。你应该在之前调用[self.tradeFeedCollectionView invalidateLayout];
if (self.changeLayout){
[self.tradeFeedCollectionView setCollectionViewLayout:self.grideLayout animated:YES];
}
else {
[self.tradeFeedCollectionView setCollectionViewLayout:self.tableViewLayout animated:YES];
}
-setCollectionViewLayout:
或-setCollectionViewLayout:animated:
不会导致您的UICollectionView
重新加载其数据
- 如果要更改单元格样式或更新数据,请调用
[self.collectionView reloadData]
并调用UICollectionViewDataSource
协议方法
- 如果要将
UICollectionView
布局更改为其他布局,请调用-setCollectionViewLayout:
。或者如果要更新UICollectionView
布局,只需调用[self.collectionView.collectionViewLayout invalidateLayout]
单元格布局和数据在UICollectionView
中是两个不同的东西
更新
您应该丢弃所有过时的数据,可能是通过-reloadData
,并为UICollectionViewLayout子类中的每个单元格计算新的帧。重写-(UICollectionViewLayoutAttribute*)LayoutAttribute ForItemAtIndexPath:(NSIndexPath*)indexPath
(NSArray*)LayoutAttribute ForElementsRect:(cRect)rect
您可以决定新的
contentOffset
。例如,您可以保留某个可见单元格的indexPath,并决定在布局更改后滚动到该indexPath
或setContentOffset:
到框架。新单元格的原点在同一indexPath
处
- 我发现我可以给你帮助
- 还可以查看精彩的视频
您应该只需要将其称为m
[self.collectionView reloadData];
[self.collectionView performBatchUpdates:^{
[self.collectionView.collectionViewLayout invalidateLayout];
[self.collectionView setCollectionViewLayout:self.grideLayout animated:YES];
} completion:^(BOOL finished) {
}];
}
[self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
[self.collectionView setCollectionViewLayout:newLayout animated:animated];