保持 UITableView 和 UICollectionView 滚动位置同步

Keeping UITableView and UICollectionView scroll position in sync

我有一个 UIViewController 可以通过 UICollectionView (cv) 或 UITableView (tv) 显示其内容。

两个视图都通过情节提要添加到视图层次结构中,我只是隐藏了不应显示的视图。 UICollectionViewUITableView 具有相同的数据源。 UICollectionView 在每行网格中显示内容,UITableView 显然在每行网格中显示内容。

所以我想要发生的是,如果用户决定在视图之间切换,新显示的视图应该滚动到在另一个视图中可见的元素。

我用 scrollToRowAtIndexPath:atScrollPosition:animated:scrollToItemAtIndexPath:atScrollPosition:animated: 做了一些试验,但没有成功。

我明白,UICollectionViewUITableView 都能够 return 它们当前可见的项目/行的 indexPaths,但是我如何将这些 indexPath 转换为 indexPath另一个视图并告诉他们滚动到该元素?

我当前对开关按钮的触摸事件处理如下所示:

- (IBAction)switchView:(id)sender {
    
    self.showListView = !self.showListView;
    
    UIView *fromView, *toView;
    NSIndexPath *indexPath;
    
    if (self.showListView)
    {
        fromView = self.ArticleCollection;
        toView = self.ArticleList;
        
        CGRect visibleRect = (CGRect){.origin = self.ArticleCollection.contentOffset, .size = self.ArticleCollection.bounds.size};
        CGPoint visiblePoint = CGPointMake(100, CGRectGetMidY(visibleRect));
        indexPath = [self.ArticleCollection indexPathForItemAtPoint:visiblePoint];
    }
    else
    {
        fromView = self.ArticleList;
        toView = self.ArticleCollection;
        
        CGRect visibleRect = (CGRect){.origin = self.ArticleList.contentOffset, .size = self.ArticleList.bounds.size};
        CGPoint visiblePoint = CGPointMake(100, CGRectGetMidY(visibleRect));
        indexPath = [self.ArticleList indexPathForRowAtPoint:visiblePoint];
    }
    
    NSInteger row = indexPath.row;
    
    if (self.showListView) {
        [self.ArticleList scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:row*2 inSection:0]
                                atScrollPosition:UITableViewScrollPositionTop
                                        animated:NO];
    } else {
        [self.ArticleCollection scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:ceil(row/2)
                                                                            inSection:0
                                                                     atScrollPosition:UICollectionViewScrollPositionCenteredVertically
                                                                             animated:NO]];
    }
    
    // Here a transitionFromView:ToView:duration:options:completion call follows
}

提前感谢您对我的问题的任何贡献。

来自 scrollToItemAtIndexPath:atScrollPosition:animated: 调用中的一个小错字:

[self.ArticleCollection scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:row
                                                                        inSection:0]
                                                                 atScrollPosition:UICollectionViewScrollPositionCenteredVertically
                                                                         animated:NO];

我确实认为 indexPath.row 会包含不同的值,无论它来自 cv 的可见索引路径还是电视的可见索引路径,所以我通过乘法或除法计算了新行通过 2。但事实证明,这两种情况下的行是相同的,所以我只需要为这两种情况使用相同的值:

NSInteger row = indexPath.row;

if (self.showListView) {
    [self.ArticleList scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:row inSection:0]
                            atScrollPosition:UITableViewScrollPositionTop
                                    animated:NO];
} else {
    [self.ArticleCollection scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:row
                                                                        inSection:0]
                                                                 atScrollPosition:UICollectionViewScrollPositionCenteredVertically
                                                                         animated:NO];
}

对于给您带来的不便,我们深表歉意。