调用setCollectionViewLayout:animated不会重新加载UICollectionView [英] Calling setCollectionViewLayout:animated does not reload UICollectionView

查看:773
本文介绍了调用setCollectionViewLayout:animated不会重新加载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] UICollectionViewDataSource 协议方法。

  • 如果要将 UICollectionView 布局更改为另一个,请调用 -setCollectionViewLayout:。或者,如果要更新 UICollectionView 布局,只需调用 [self.collectionView.collectionViewLayout invalidateLayout]

  • If you want to change your cell style or update the data, call [self.collectionView reload] and UICollectionViewDataSource protocol methods will be called.
  • If you want to change your UICollectionView layout to another, call -setCollectionViewLayout:. Or if you want to update your UICollectionView 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.

  • 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆