【问题标题】:Flash scroll indicators of UICollectionView after changing data source更改数据源后 UICollectionView 的 Flash 滚动指示器
【发布时间】:2013-06-12 16:52:24
【问题描述】:

我正在通过更改数据源来换出我的集合视图中显示的数据。这是作为选项卡式界面的一部分完成的。当新数据加载时,我想闪烁滚动指示器以告诉用户在视口之外还有更多数据。

立即

立即这样做不起作用,因为集合视图尚未加载数据:

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];

当集合视图接收到新数据并调整内容视图的大小时,我是否可以连接到回调以闪烁滚动指示器?

【问题讨论】:

  • 您是否尝试在设置新数据源之后和发送flashScrollIndicators之前调用[collectionView reloadData]
  • 您或许可以尝试使用块like this 重新加载数据并在完成时调用flashScrollIndicators
  • flashScrollIndicators 之前立即调用reloadData 也不起作用,正如zvjerka24 所述。
  • 您说调用-flashScrollIndicators 在使用performSelector:withObject:afterDelay: 时确实有效,但它有点滞后。您是否尝试过延迟为 0?延迟为 0 仍然会稍微延迟消息。
  • 那也行不通

标签: ios uicollectionview


【解决方案1】:

子类化 UICollectionView 并覆盖 layoutSubviews 可能是一种解决方案。您可以在收藏上致电[self flashScrollIndicators]。问题是layoutSubviews 在多个场景中被调用。

  1. 最初创建集合并分配数据源时。
  2. 滚动时,超出视口的单元格将被重新使用和重新布局。
  3. 显式更改框架/重新加载集合。

解决方法是,保留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;

【讨论】:

    【解决方案2】:

    UICollectionViewLayout 的方法-finalizeCollectionViewUpdates 中调用flashScrollIndicators

    来自 Apple 的文档:

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

    希望这会有所帮助!

    编辑:

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

    每次你将一个新的 UICollectionViewCell 交给你的集合视图时,使用[[self.collectionView indexPathsForVisibleItems] lastObject] 检查它是否是最后一个可见单元格。您还需要一个 BOOL ivar 来决定是否应该闪烁指示器。每次更改数据源时,将标志设置为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;
    }
    

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

    希望对你有帮助!

    【讨论】:

    • 很好的发现,但是在更改数据源时似乎没有调用该方法。
    • 仅仅改变 'dataSource' 属性不会导致 UICollectionView 重新加载数据。要调用该方法,请尝试在更改数据源后调用“reloadData”方法:collectionView.dataSource = dataSource2;[collectionView reloadData];
    • 当我调用 reloadData 时,该方法似乎仍未被调用。
    • 感谢您的回答,但我认为接受的答案更直接一些。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-27
    • 2014-05-13
    • 2021-11-20
    • 1970-01-01
    相关资源
    最近更新 更多