调用setCollectionViewLayout:animated不会重新加载UICollectionView [英] Calling setCollectionViewLayout:animated does not reload UICollectionView
问题描述
我正在使用带有两个自定义布局的UICollectionView - 它们是 UICollectionViewFlowLayout
I am using a UICollectionView with two custom layouts - which are subclassed from UICollectionViewFlowLayout
当我的视图第一个时我使用以下命令将其设置为默认视图:
When my view first loads I set it to a default view using:
[self.collectionView setCollectionViewLayout:self.tableViewLayout];
此调用: cellForItemAtIndexPath
- 所以没问题那里。这是在 viewWillAppear
方法。
This calls: cellForItemAtIndexPath
- so no problem there. This is in viewWillAppear
method.
然后我使用UIButton将布局从当前视图更改为下一个布局像这样:
Then I use a UIButton to change the layout from current view to the next layout like so:
-(void)changeViewLayoutButtonPressed
{
self.changeLayout = !self.changeLayout;
if (self.changeLayout){
[self.tradeFeedCollectionView setCollectionViewLayout:self.grideLayout animated:YES];
}
else {
[self.tradeFeedCollectionView setCollectionViewLayout:self.tableViewLayout animated:YES];
}
}
此次通话后 - <$ c调用$ c> numberOfItemsInSection 。我已在调试器中检查了返回帐户不为零。
After this call - numberOfItemsInSection
is called. I have checked in the debugger that the return account is not zero.
在那次调用之后,没有其他任何东西被调用,我的UICollectionView改变了布局,但由于没有调用 cellForItemAtIndexPath
- 单元格设置不正确。
After that call, nothing else is called and my UICollectionView changes the layout but since cellForItemAtIndexPath
is not called - the cells are not setup correctly.
如果我在 [self.collectionView roloadData]
> numberOfItemsInSection - 然后调用 cellForItemAtIndexPath
并设置单元格。
if I put [self.collectionView roloadData]
inside of numberOfItemsInSection
- then cellForItemAtIndexPath
is called and cells are setup.
我不需要手动调用来重新加载 numberOfItemsInSection
中的数据。有人可以告诉我发生了什么吗?
I shouldn't need to do a manual call to reload the data in numberOfItemsInSection
. Can someone tell me whats going on?
编辑
我忘了提及我正在为两个不同的单元格使用两个不同的UINib,因为它们需要稍微不同的布局。这会是一个问题吗?
谢谢!
I forgot to mention I am using two different UINibs for the two different cells as they need slightly different layouts applied to them. Would this be an issue? Thanks!
编辑2
是的,所以我有让它像我想要的那样工作。以下是用于集合视图的所有代码以及如何更改其布局。
Right, so I have gotten it to work almost like I want it to. Here is all the code used for the collection view and how I change its layouts.
自定义布局
这些是的子类别UICollectionViewFlowLayout
- 我子类化的原因仅仅是因为我的 UICollectionView
需要看起来和表现非常接近Apple的预制布局。但是,只是不同的细胞大小。
These are subclassed from UICollectionViewFlowLayout
- The reason I subclassed is simply due to the face my UICollectionView
needs to look and behave very close to Apple's pre-made layout. Just different cell sizes, though.
TableViewLayout
- 头文件中没有代码。
- BBTradeFeedTableViewLayout.m
@implementation BBTradeFeedTableViewLayout
-(id)init
{
self = [super init];
if (self){
self.itemSize = CGSizeMake(320, 80);
self.minimumLineSpacing = 0.1f;
}
return self;
}
@end
Gride Layout
- 头文件中没有代码。
- BBTradeFeedGridViewLayout.m
@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
然后在 ViewController中
有我的 UICollectionView
- 我声明了两个自定义布局,如下所示:
Then in the ViewController
that has my UICollectionView
- I declare the two custom layouts like so:
@property (strong, nonatomic) BBTradeFeedTableViewLayout *tableViewLayout;
@property (strong, nonatomic) BBTradeFeedGridViewLayout *grideLayout;
然后我为collectionView注册两个.xib文件:
I then register the two .xib files for the collectionView:
[self.tradeFeedCollectionView registerNib:[UINib nibWithNibName:@"BBItemTableViewCell" bundle:nil] forCellWithReuseIdentifier:@"TableItemCell"];
[self.tradeFeedCollectionView registerNib:[UINib nibWithNibName:@"BBItemGridViewCell" bundle:nil] forCellWithReuseIdentifier:@"GridItemCell"];
然后,我有一个更改布局的UIButton:
Then, I have a UIButton that changes the layout:
-(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]];
}
最后 - 当网络服务调用完成时 - 它调用 [self.tradeFeedCollectionView reloadData];
Finally - when a web service call is done - it calls [self.tradeFeedCollectionView reloadData];
所以我的 UICollectionView
重新加载和最后一个方法:
So there my UICollectionView
gets reloaded and the last method:
-(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;
}
以上代码的问题
以上代码确实有效。然而,细胞不能很好地制作动画并且看起来很奇怪,几乎就像刷新了一样。这是由于调用:
The above code does work. However, the cells don't animate nicely and it looks odd, almost as if a refreshed happened. Which is due to calling:
[self.tradeFeedCollectionView reloadItemsAtIndexPaths:[self.tradeFeedCollectionView indexPathsForVisibleItems]];
但这是我能让它接近我想要的唯一方法。
But that is the only way I could get it to be close to what I want.
推荐答案
-setCollectionViewLayout:
或 -setCollectionViewLayout :动画:
不会导致您的 UICollectionView
重新加载。
-setCollectionViewLayout:
or -setCollectionViewLayout:animated:
won't cause your UICollectionView
reload.
- 如果您想更改单元格样式或更新数据,请调用
[self.collectionView reload] 将调用code>和
UICollectionViewDataSource
协议方法。 - 如果要将
UICollectionView
布局更改为另一个,请调用-setCollectionViewLayout:
。或者,如果要更新UICollectionView
布局,只需调用[self.collectionView.collectionViewLayout invalidateLayout]
。
- If you want to change your cell style or update the data, call
[self.collectionView reload]
andUICollectionViewDataSource
protocol methods will be called. - If you want to change your
UICollectionView
layout to another, call-setCollectionViewLayout:
. Or if you want to update yourUICollectionView
layout, just call[self.collectionView.collectionViewLayout invalidateLayout]
.
单元布局和数据是 UICollectionView
中的两个不同的东西。
Cell layout and data are two different things in UICollectionView
.
更新
您应丢弃所有陈旧数据,可能是 -reloadData
。并为UICollectionViewLayout子类中的每个单元格计算新帧。覆盖 - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
和 - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
。$
您决定新的 contentOffset
。例如,你可以保留一些可见单元格的indexPath并决定滚动到 indexPath
或 setContentOffset:
到更改布局后,同一 indexPath
中新单元格的 frame.origin
。
Update
you should discard all the stale data, probably by -reloadData
. And calculate the new frames for every cell in your UICollectionViewLayout subclasses. Override - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
and - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
.
You decide the new contentOffset
. For instance, you could keep the indexPath of some visible cell and decide to scroll to that indexPath
or setContentOffset:
to the frame.origin
of the new cell at the same indexPath
after your layout changed.
- 我发现这个答案可能会给你帮助。
- 同时查看精彩视频 WWDC 2012高级馆藏视图和构建自定义布局
- And I find this answer may give you help.
- Also check the awesome video WWDC 2012 Advanced Collection Views and Building Custom Layouts
这篇关于调用setCollectionViewLayout:animated不会重新加载UICollectionView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!