[英]uicollectionview select an item immediately after reloaddata?
After calling -[UICollectionView reloadData]
it takes some time for cells to be displayed, so selecting an item immediately after calling reloadData
does not work. 在调用
-[UICollectionView reloadData]
,显示单元格需要一些时间,因此在调用reloadData
之后立即选择一个项目不起作用。 Is there a way to select an item immediately after reloadData
? 有没有办法在
reloadData
之后立即选择一个项目?
Along the lines of this answer I found that calling layoutIfNeeded
after reloadData
seemed to effectively 'flush' the reload before I do other things to the collectionView: 根据这个答案,我发现在我对collectionView执行其他操作之前,在
reloadData
之后调用layoutIfNeeded
似乎有效地“刷新”了重新加载:
[self.collectionView reloadData];
[self.collectionView layoutIfNeeded];
...
On the page I found this solution, some commenters indicated it didn't work for them on iOS 9, but it's been fine for me so your mileage may vary. 在页面上我找到了这个解决方案,一些评论者表示它在iOS 9上没有对他们有效,但它对我来说没问题所以你的里程可能会有所不同。
I'm handling selection of cells in collectionView: cellForItemAtIndexPath:
. 我正在处理
collectionView: cellForItemAtIndexPath:
的单元格选择collectionView: cellForItemAtIndexPath:
. The problem I found was that if the cell didn't exist, simply calling selectItemAtIndexPath: animated: scrollPosition:
wouldn't actually select the item. 我发现的问题是,如果单元格不存在,只需调用
selectItemAtIndexPath: animated: scrollPosition:
实际上不会选择该项目。
Instead you have to do: 相反,你必须这样做:
cell.selected = YES;
[m_collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
Don't use reloadData 不要使用reloadData
Use - (void)performBatchUpdates:(void (^)(void))updates completion:(void (^)(BOOL finished))completion
instead. 使用
- (void)performBatchUpdates:(void (^)(void))updates completion:(void (^)(BOOL finished))completion
。 The completion block is executed after animations for cell insertion/deletion etc. have completed. 在完成单元插入/删除等的动画之后执行完成块。 You can put the call to reloadData in the
(void (^)(void))updates
block 您可以在
(void (^)(void))updates
块中调用reloadData
Apple says: Apple说:
You should not call this method in the middle of animation blocks where items are being inserted or deleted.
不应在插入或删除项目的动画块中间调用此方法。 Insertions and deletions automatically cause the table's data to be updated appropriately.
插入和删除会自动使表的数据得到适当更新。
In fact, you should not call this method in the middle of any animation (including UICollectionView
in the scrolling). 实际上,您不应该在任何动画的中间调用此方法(包括滚动中的
UICollectionView
)。
So, you can use: 所以,你可以使用:
[self.collectionView setContentOffset:CGPointZero animated:NO];
[self.collectionView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
or mark sure not any animation, and then call reloadData
; 或者确定没有任何动画,然后调用
reloadData
; or 要么
[self.collectionView performBatchUpdates:^{
//insert, delete, reload, or move operations
} completion:nil];
Hope this is helpful to you. 希望这对你有所帮助。
The Swift way: Swift方式:
let selected = collectionView.indexPathsForSelectedItems()
collectionView.performBatchUpdates({ [weak self] in
self?.collectionView.reloadSections(NSIndexSet(index: 0))
}) { completed -> Void in
selected?.forEach { [weak self] indexPath in
self?.collectionView.selectItemAtIndexPath(indexPath, animated: false, scrollPosition: [])
}
}
Make sure you're calling reloadData
on the main thread. 确保在主线程上调用
reloadData
。 That could be the cause for the delay in your cell updates. 这可能是导致细胞更新延迟的原因。
I handled it on the willDisplayCell colelctionView delegate. 我在willDisplayCell colelctionView委托上处理它。 The idea: A temp variable is needed to specify the initial scrolling has performed already or not (scrollIsRequired).
想法:需要一个临时变量来指定已经执行或不执行的初始滚动(scrollIsRequired)。 When the last visible cell will display, than we can scroll to the required cell and set this variable to avoid scrolling again.
当显示最后一个可见单元格时,我们可以滚动到所需单元格并设置此变量以避免再次滚动。
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{
//Perform any configuration
if (CGRectGetMaxX(collectionView.frame) <= CGRectGetMaxX(cell.frame)) {
// Last visible cell
if (self.scrollIsRequired) {
[self.collectionView selectItemAtIndexPath:[NSIndexPath indexPathForItem:self.initiallySelectedRepresentativeVerse inSection:0] animated:YES scrollPosition:UICollectionViewScrollPositionLeft];
self.scrollIsRequired = NO;
}
}
}
It has worked for me like a charm. 它对我来说就像一个魅力。
This is what worked for me: 这对我有用:
I kept a reference of the selected index path and overide the reloadData function: 我保留了所选索引路径的引用并覆盖了reloadData函数:
override func reloadData() {
super.reloadData()
self.selectItem(at: self.selectedIndexPath, animated: false, scrollPosition: UICollectionViewScrollPosition())
}
I tried doing it using indexPathForSelectedItems, but it was creating an infinite loop on collection view load. 我尝试使用indexPathForSelectedItems,但它在集合视图加载时创建了一个无限循环。
创建一个执行选择的方法,并在调用reload后使用performSelector调用它;
[self performSelector:@selector(selectIt) withObject:self afterDelay:0.1];
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.