ios 更改数据源后UICollectionView的 Flink 滚动指示符

wmomyfyw  于 2023-05-19  发布在  iOS
关注(0)|答案(3)|浏览(130)

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

立即

立即执行此操作不起作用,因为集合视图尚未加载数据:

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

有没有一个回调函数,我可以挂在上面,以便在集合视图接收到新数据并调整了内容视图的大小后,立即 Flink 滚动指示符?

pkln4tw6

pkln4tw61#

子类化UICollectionView并覆盖layoutSubviews可能是一种解决方案。您可以在集合上调用[self flashScrollIndicators]。问题是layoutSubviews在多个场景中被调用。
1.最初创建集合并分配数据源时。
1.在滚动时,超出视口的单元格会被重新使用和重新布局。
1.显式地更改框架/重新加载集合。
解决方法是,保留BOOL属性,只有在重新加载数据源时才将其设置为YES,否则将保持为NO。因此,只有在重新加载集合时才会显式地 Flink 滚动条。
在源代码方面
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;
5jvtdoz2

5jvtdoz22#

将对flashScrollIndicators的调用放在UICollectionViewLayout的方法-finalizeCollectionViewUpdates中。
来自Apple的文档:
“...此方法在用于执行所有插入、删除和移动动画的动画块内调用,因此您可以根据需要使用此方法创建其他动画。否则,您可以使用它来执行与管理布局对象的状态信息相关的任何最后一分钟任务
希望这有帮助!
编辑:
好的我知道了既然你提到了finalizeCollectionViewUpdates方法没有被调用,我决定自己试试。你说得对问题是(抱歉我之前没有注意到这一点),只有在更新集合视图(例如插入、删除、移动单元格)之后才会调用该方法。所以在这种情况下,它不适合你。所以,我有一个新的解决方案;它涉及到在UICollectionViewDataSource的方法collectionView:cellForItemAtIndexPath:中使用UICollectionView的方法indexPathsForVisibleItems
每次将新的UICollectionViewCell提交到集合视图时,使用[[self.collectionView indexPathsForVisibleItems] lastObject]检查它是否是最后一个可见的单元格。您还需要一个BOOL ivar来决定是否应该 Flink 指示器。每次更改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;
}

我尝试过这种方法,它对我很有效。
希望有帮助!

iyfjxgzm

iyfjxgzm3#

像@Amar建议的那样创建自己的集合视图类,并像下面这样覆盖layoutSubviews和reloadData

class FlashScrollBarCollectionView: UICollectionView {

   var flashScrollBar = false
   override func layoutSubviews() {
       super.layoutSubviews()
       if flashScrollBar {
           flashScrollIndicators()
           flashScrollBar = false
       }
   }

   override func reloadData() {
       flashScrollBar = true
       super.reloadData()
   }
}

相关问题