我目前正在开发一个Objective-C iOS应用程序,该应用程序具有全屏幕集合视图的场景,单元格几乎与整个屏幕的大小垂直向下滚动场景。
我希望能够以编程方式更改位于可见屏幕中心的此Collection视图中的单元格,以及我当前实现此功能的方式是等待滚动停止在Collection View上,以及然后编辑位于屏幕正中心的任何单元格,如下面的方法所示:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
NSIndexPath *centerCellIndexPath =
[self.collectionViewFollwersFeed indexPathForItemAtPoint:
[self.view convertPoint:[self.view center] toView:self.collectionViewFollwersFeed]];
UICollectionViewCell *cell;
NSString *CellIdentifier;
CellIdentifier = @"FollowersFeed";
cell = [_collectionViewFollwersFeed cellForItemAtIndexPath:centerCellIndexPath];
//edit cell here
}
虽然这种实现此功能的方法在某种程度上起作用,但只有当用户停止滚动时才会开始对单元格进行更改。
我希望能够在新单元格覆盖中心位置时开始对中心单元格进行更改,而不必停止滚动。如何编辑此方法,以便当且仅当新单元格覆盖屏幕的中心位置时,应该调用此方法?
答案 0 :(得分:3)
我完全同意受过良好教育的同伴dahn。
话虽如此,您可能希望根据滚动位置实际制作动画,而不是仅仅在碰到中心时“更改”单元格...
要做到这一点,你可以让细胞跟踪自己的位置:
在实例化时将scrollview传递给单元格:
// MyCollectionView's DataSource
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"yourIdentifier" forIndexPath:indexPath];
cell.observedScrollView = theScrollViewYouWantToTrack;
[cell startObservingPosition];
return cell;
}
确保单元格保持observedScrollView
弱,以避免保留周期
然后在你的单元格的.m文件中注册一个KVO观察者:
// MyCollectionViewCell.m
- (void)startObservingPosition {
if (self.observedScrollView) {
[self.observedScrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial context:NULL];
}
}
确保在单元格解除分配之前移除KVO观察者......否则崩溃!你也可以考虑使用我自己发布的漂亮enhanced KVO observer
每次KVO Observer触发(当scrollView滚动时) - 您可以找出位置并做出相应的反应。
此示例显示了如何检测细胞何时位于中心,还说明了如何进行更多操作:
// MyCollectionViewCell.m
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *, id> *)change context:(void *)context {
if ([keyPath isEqualToString:@"contentOffset"]) {
if (self.observedScrollView) {
CGPoint offset = self.observedScrollView.contentOffset;
CGRect contentViewRect = [self.contentView convertRect:self.contentView.bounds toView:self.observedScrollView];
CGFloat contentViewCenterY = contentViewRect.origin.y + contentView.size.height * 0.5 - offset.y;
if (contentViewCenterY == self.observedScrollView.bounds.height * 0.5) {
// the contentView is in the center of the viewable feed. do your animations...
}
}
}
}
答案 1 :(得分:1)
编辑单元格== yuck。改变模型==很好。
因此,将NSInteger添加到数据源indexOverCenter
。将其初始化为无效的内容,例如-1。然后,在委托中,检测条件:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
NSIndexPath *centerCellIndexPath =
[self.collectionViewFollwersFeed indexPathForItemAtPoint:
[self.view convertPoint:[self.view center] toView:self.collectionViewFollwersFeed]];
self.indexOverCenter = centerCellIndexPath.row;
// don't edit the cell here: yuck
// reload it: nice
[self.collectionViewFollwersFeed reloadItemsAtIndexPaths:@[ centerCellIndexPath ]];
}
你的&#34;编辑&#34;在cellForItemAtIndex中工作,将传递的indePath行与indexOverCenter进行比较。如果它们相同,那么在那里进行特殊格式化。
答案 2 :(得分:0)
在我的CollectionView中,我得到了这样的结果:
private func findCenterIndex() -> Int {
let center = self.view.convert(numberCollectionView.center, to: self.numberCollectionView)
let row = numberCollectionView!.indexPathForItem(at: center)?.row
guard let index = row else {
return 0
}
self.rating = index
return index
}
因此,您可以轻松将其转换为您的objective-c代码