更改数据源后,UICollectionView的Flash滚动指示器

时间:2013-06-12 16:52:24

标签: ios uicollectionview

我通过更改数据源来交换我的集合视图中显示的数据。这是作为类似标签的界面的一部分完成的。加载新数据时,我想闪烁滚动指示器,告诉用户视口外还有更多数据。

立即

立即这样做并不起作用,因为集合视图还没有加载数据:

collectionView.dataSource = dataSource2;
[collectionView flashScrollIndicators]; // dataSource2 isn't loaded yet

dispatch_async

稍后调度flashScrollIndicators来电也不起作用:

collectionView.dataSource = dataSource2;
dispatch_async(dispatch_get_main_queue(), ^{
    [collectionView flashScrollIndicators]; // dataSource2 still isn't loaded
});

performSelector:withObject:afterDelay:

在定时延迟后执行flashScrollIndicators确实有效(我在SO上的其他地方看到它),但是在显示滚动指示器时会导致一些延迟。我可以减少延迟,但似乎它只会导致竞争条件:

collectionView.dataSource = dataSource2;
[collectionView performSelector:@selector(flashScrollIndicators) withObject:nil afterDelay:0.5];

在收集视图获取新数据并调整内容视图大小后,是否有可以挂钩的回调来刷新滚动指示符?

2 个答案:

答案 0 :(得分:3)

flashScrollIndicators的方法UICollectionViewLayout内拨打-finalizeCollectionViewUpdates

来自Apple的文档:

“...此方法在用于执行所有插入,删除和移动动画的动画块中调用,因此您可以根据需要使用此方法创建其他动画。否则,您可以使用它执行与管理布局对象的状态信息相关的任何最后一分钟任务。“

希望这有帮助!

编辑:

好的,我明白了。既然你提到finalizeCollectionViewUpdates方法没有被调用,我决定自己尝试一下。而你是对的。问题是(对不起,我之前没有注意到),只有在更新集合视图(插入,删除,移动单元格)后才会调用该方法。所以在这种情况下它不适合你。所以,我有一个新的解决方案;它涉及在UICollectionView方法indexPathsForVisibleItems

中使用UICollectionViewDataSource方法collectionView:cellForItemAtIndexPath:

每次将新的UICollectionViewCell传递到集合视图时,请使用[[self.collectionView indexPathsForVisibleItems] lastObject]检查它是否是最后一个可见单元格。您还需要一个BOOL ivar来决定是否应该闪烁指示器。每次更改dataSource时,都会将标志设置为YES

- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"MyCell" forIndexPath:indexPath];
    cell.backgroundColor = [UIColor whiteColor];

    NSIndexPath *iP = [[self.collectionView indexPathsForVisibleItems] lastObject];
    if (iP.section == indexPath.section && iP.row == indexPath.row && self.flashScrollIndicators) {
        self.flashScrollIndicators = NO;
        [self.collectionView flashScrollIndicators];
    }

    return cell;
}

我试过这种方法,它对我有用。

希望它有所帮助!

答案 1 :(得分:3)

UICollectionView进行子类化并覆盖layoutSubviews可以是一种解决方案。您可以在集合上调用[self flashScrollIndicators]。问题是在多个场景中调用layoutSubviews

  1. 最初创建集合并分配数据源时。
  2. 在滚动时,超出视口的单元格会被重复使用&重新布局。
  3. 明确更改框架/重新加载集合。
  4. 解决此问题的方法是,保留BOOL属性,仅在重新加载数据源时才会生成YES,否则将保留NO。因此,只有在重新加载集合时才会显式地发生滚动条的闪烁。

    就源代码而言,

    MyCollection.h

    #import <UIKit/UIKit.h>
    
    @interface MyCollection : UICollectionView
    
    @property (nonatomic,assign) BOOL reloadFlag;
    
    @end
    

    MyCollection.m

    #import "MyCollection.h"
    
    @implementation MyCollection
    
    - (void) layoutSubviews {
        [super layoutSubviews];
        if(_reloadFlag) {
            [self flashScrollIndicators];
            _reloadFlag=NO;
        }
    }
    

    用法应该是

    self.collection.reloadFlag = YES;
    self.collection.dataSource = self;