【问题标题】:Synchronize scroll between UITableView and UICollectionView : lag when using multiple scrollToRowAtIndexPath在 UITableView 和 UICollectionView 之间同步滚动:使用多个 scrollToRowAtIndexPath 时出现滞后
【发布时间】:2013-06-05 19:57:01
【问题描述】:

我有一个带有collectionView(单条水平线)和下面的tableview 的视图。两个视图在滚动时同步,因为它们以不同的方式显示相同的数据。事实上,如果你有这个应用程序,它就像“神奇”的应用程序。

我设法使用 UIScrollView 委托方法同步两个视图

#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGPoint currentOffset = scrollView.contentOffset;
    NSLog(@"scrollViewDidScroll %@ - %@", NSStringFromCGPoint(scrollView.contentOffset), NSStringFromCGPoint(self.previousScrollOffset));
    switch (self.scrollAnimation) {
        case ScrollAnimationFromCollection:
        {
            if (currentOffset.x > self.previousScrollOffset.x && (self.scrollDirection == ScrollDirectionLeft || self.scrollDirection == ScrollDirectionNone))
            {
                // NSLog(@"Change to Right!");
                self.scrollDirection = ScrollDirectionRight;
                [self.alreadySelectedIndexPaths removeAllObjects];
            }
            else if (currentOffset.x <= self.previousScrollOffset.x && (self.scrollDirection == ScrollDirectionRight || self.scrollDirection == ScrollDirectionNone))
            {
                // NSLog(@"Change to Left!");
                self.scrollDirection = ScrollDirectionLeft;
                [self.alreadySelectedIndexPaths removeAllObjects];
            }
            [self moveTableView];
            break;
        }

        case ScrollAnimationFromTableView:
        {
            if (currentOffset.y - self.previousScrollOffset.y > 0 && self.scrollDirection == ScrollDirectionBottom)
            {
                self.scrollDirection = ScrollDirectionTop;
                [self.alreadySelectedIndexPaths removeAllObjects];
            }
            else if (currentOffset.y - self.previousScrollOffset.y <= 0 && self.scrollDirection == ScrollDirectionTop)
            {
                self.scrollDirection = ScrollDirectionBottom;
                [self.alreadySelectedIndexPaths removeAllObjects];
            }
            [self moveCollectionView];
            break;
        }

        default:
            break;
    }
    self.previousScrollOffset = currentOffset;
}

#pragma mark - Move actions
- (void)moveCollectionView
{
    NSIndexPath* currentIp = [[self.tableView indexPathsForVisibleRows] objectAtIndex:1];
    NSLog(@"currentIp %@", currentIp);
    if (![self.alreadySelectedIndexPaths containsObject:currentIp])
    {
        NSLog(@"Scroll to IndexPath centered!");
        [self.alreadySelectedIndexPaths addObject:currentIp];
        [self.collectionViewController.collectionView scrollToItemAtIndexPath:currentIp atScrollPosition:PSTCollectionViewScrollPositionCenteredHorizontally animated:YES];
    }
}

- (void)moveTableView
{
    NSIndexPath* currentIp = [self.collectionViewController.collectionView indexPathForItemAtPoint:[self.horizontalContainer convertPoint:self.horizontalContainer.center toView:self.collectionViewController.collectionView]];
    NSLog(@"currentIp %@", currentIp);
    if (![self.alreadySelectedIndexPaths containsObject:currentIp])
    {
        NSLog(@"Scroll to IndexPath At Top!");
        [self.alreadySelectedIndexPaths addObject:currentIp];
        self.tableView.decelerationRate = UIScrollViewDecelerationRateFast;
        [self.tableView scrollToRowAtIndexPath:currentIp atScrollPosition:UITableViewScrollPositionTop animated:YES];
    }
}

它工作得非常好,除了一件事:当我滚动 collectionview 时,由于动画 (YES) 参数,tableview 需要一些时间来滚动。如果我使用 scrollToRowAtIndexPath: 没有动画,它就像一个魅力。但是,一旦我使用动画标志,iOS 似乎(非常合乎逻辑地)将 scrollToRowAtIndexPath 排队并一次运行一次,导致动画滞后。

FWI,hassSelectedIndexPaths 包含一个我已经滚动到的 indexPath 列表(我不知道这句话是否很清楚:D :D)

我查看是否有办法取消之前的订单,但除了 cancelPreviousPerformRequestsWithTarget: with 取消最后一次 performSelector 调用,它没有发现任何有用的东西。

你知道我怎样才能在这里获得流畅的动画吗?

感谢您的帮助。

【问题讨论】:

  • 为什么不调用滚动视图代理?使用它们很容易做到这一点。
  • 代理正在被呼叫,但不是连续呼叫。当用户用手指滚动时,似乎只调用了一次 scrollViewDidScroll ,但在那之后就没有了。还有一个 scrollViewWillEndDragging: 可以使用,因为有一个 targetOffset,但是计算每个视图的减速会有点棘手:-/
  • scrollViewDidScroll 在滚动视图的任何移动过程中被重复调用。无论用户是滚动还是减速都会调用它。
  • @Khal 当您说“同步”时,我了解 tableview 和 collectionview 将同时滚动。但是,switch 方法中 updateUIFromTimer: 方法中的代码中的情况表明并非如此。为什么不删除表和集合上的开关并调用更新?此外,UITableViewUICollectionView 都继承自 UIScrollView,因此您可以使用 setContentOffset:animated: 方法(带或不带动画)以编程方式滚动两者。
  • @Fogmeister :我检查了一个带有 tableview 的简单项目,scrollviewdidscroll 确实被连续调用。但它不在我的应用程序中,很奇怪......我去看看......

标签: ios uitableview uiscrollview scroll uicollectionview


【解决方案1】:

每当滚动 tableView 或 collectionView 时重写 scrollviewDidScroll 方法。

在这里,您可以获取正在滚动的视图的偏移量并将其转换为另一个视图的偏移量。

然后你可以在另一个视图上设置这个偏移量。

您不需要对偏移量或任何东西进行动画处理,因为无论如何都会在动画循环中调用委托方法,因此只需设置偏移量就可以让两个视图看起来都在进行动画处理。

希望这会有所帮助。

【讨论】:

  • 别担心,乐于助人:-D
  • 嘿伙计!我们尝试这样做,但似乎我们使用的偏移量(来自 collectionView)在将其应用于滚动视图时未同步,您知道是否需要某种转换?
  • @RoiMulia 你不应该这样做。不同步是什么意思?集合视图是滚动视图。所以内容偏移量将是相同的。你看到了什么不同?也许是用您的代码等添加一个新问题的想法......然后链接它。我去看看:-)
  • 我将尝试与我的团队一起解决这个问题。如果我们不成功,我会发布一个问题!谢谢你:)
【解决方案2】:

我遇到了类似的问题。对我有用的是:

  1. 创建自定义的 UITableView 和 UICollectionView 子类
  2. 这两个子类都应该符合UIGestureRecognizerdelegate
  3. 在这两个类中重写gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) 方法
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
  1. 您的表格视图和集合视图需要具有相同的超级视图。将两个手势识别器添加到您的超级视图中
yourSuperview.addGestureRecognizer(scrollView.panGestureRecognizer)
yourSuperview.addGestureRecognizer(tableView.panGestureRecognizer)

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-22
    • 2015-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-03
    相关资源
    最近更新 更多