代码之家  ›  专栏  ›  技术社区  ›  Iván Peralta

UITableView和UICollectionView在行中同时在不同行中进行奇怪的滚动

  •  2
  • Iván Peralta  · 技术社区  · 7 年前

    我们有一个 UITableView ,每行作为 UICollectionView 支持 horizontal scroll 没有 paging 已启用。

    我们已经注册了细胞以供再次使用,

        // Setup for VenueFilterTableViewCell
        NSString * cellIdentifier = @"VenueFilterTableViewCell";
        VenueFilterTableViewCell *tbCell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier];
        if (tbCell == nil) {
            tbCell = [[VenueFilterTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                                     reuseIdentifier:cellIdentifier];
            tbCell.selectionStyle = UITableViewCellSelectionStyleNone;
        }
        // Method for inflate the UICollectionView in the row
        [tbCell setVenues:venues
                  loading:NO
               atLocation:self.definedLocation
         forFilter:filter
             withDelegate:self];
        cell = tbCell;
    

    当我水平滚动行时 UICollectionView indexPath.row 中的0 UITableViewCell 这个 indexPath。一行 3(最初退出屏幕)同时滚动。因此,如果在水平滚动之后,快速向下移动滚动,您可以看到第3行和第7行。。。等等,同时滚动。

    我在每个单元格中都有一个进度条,用于向用户提供距离水平滚动结束多远的反馈,但由于这种重用行为,涉及的每一行(0、3和7)都会弄乱另一行的进度。

    有什么建议吗?

    使现代化

    我加入了 UITableView 下一个事件用于控制单元格何时离开屏幕并强制 UICollectionView 内部停止滚动。这稍微提高了性能,但最终问题再次出现。

    中的代码 UITableViewController 用于检测行何时离开屏幕:

    - (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
        if ([tableView.indexPathsForVisibleRows indexOfObject:indexPath] == NSNotFound) {
            // This indeed is an indexPath no longer visible
            // Do something to this non-visible cell...
            if ([cell isKindOfClass:[VenueFilterTableViewCell class]]) {
                VenueFilterTableViewCell *tbCell = (VenueFilterTableViewCell *) cell;
                [tbCell stopScrolling];
            }
        }
    }
    

    中的代码 UITableViewCell 使用 UICollection 视图中,在重新加载内容时,除了恢复contentOffset外,还需要重新启用 self.collectionView.scrollEnabled = YES;

    - (void) stopScrolling {
        self.collectionView.scrollEnabled = NO;
        [self.collectionView setContentOffset:self.collectionView.contentOffset animated:NO];
    }
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   Prashant Tukadiya    7 年前

    我的第一个回答没有帮助。所以我已经修复了这个,很抱歉用swift,你可以很容易地在objc中转换它

    我用以下代码实现了willDisplayCell和endDispayCell

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        guard let cell = cell as? ScreenShotsCell else { return }
        self.configureCell(for: indexPath, to: cell)
        cell.collectionView.setContentOffset(cell.collectionView.contentOffset, animated: true)
        cell.collectionViewOffset = storedOffsets[indexPath.row] ?? 0
    }
    
    //--------------------------------------------------------------------------------
    
    func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        guard let cell = cell as? ScreenShotsCell else { return }
        storedOffsets[indexPath.row] = cell.collectionViewOffset
        cell.collectionView.setContentOffset(cell.collectionView.contentOffset, animated: true)
    }
    

    主要核心逻辑是 cell.collectionView.setContentOffset 因此,当它不可见时,它将停止滚动,因此它将修复其他行由于重用单元格而导致的tableview滚动问题

    希望有帮助

        2
  •  0
  •   Jakub Truhlář    7 年前

    似乎是由 单元重用 .如果你真的有 UICollectionView 作为 单间牢房 ,最好的方法是创建 Dictionary 共存储 偏移量

    快速示例:

    var storedOffsets: [Int: CGFloat] = [:]

    在里面 tableView:didEndDisplaying:forRowAt: 存储 collectionView的 contentOffset

    然后在 tableView:willDisplay:forRowAt: 使用这些存储的偏移设置 内容偏移量 collectionView 在牢房里。