【问题标题】:Reload and Scroll to a specific Collection View cell重新加载并滚动到特定的集合视图单元格
【发布时间】:2013-11-05 12:16:13
【问题描述】:

我正在编写一个应用程序,它使用 UICollectionView 在 CollectionView 单元格中显示一些内容。使用捏合手势,需要重新加载集合视图。我能够根据捏合手势处理内容的变化。现在,在捏合手势开始时,集合视图需要重新加载并滚动到特定索引。为此,我调用了这样的函数:

[tempCollectionView reloadData];

[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(scrollToItem)  userInfo:nil repeats:YES];

[OR]
[self performSelector:@selector(scrollToItem) withObject:nil afterDelay:0.0];

- (void) scrollToItem 
{
    if (m_selectedCellIndex == -1) 
    {
        NSLog(@"cell return");
        return;
    }

    NSIndexPath *iPath = [NSIndexPath indexPathForItem:m_selectedCellIndex inSection:0];
    [tempLocalFilesCollectionView scrollToItemAtIndexPath:iPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:NO];

    LocalFilesCollectionViewCell *cell = (LocalFilesCollectionViewCell *) [m_tempLocalFilesCollectionView cellForItemAtIndexPath: iPath];
    if (cell) 
    {
        CGPoint p = [tempCollectionView convertPoint: cell.center fromView: tempCollectionView];
        NSLog(@"center: %f, %f,  %f, %f", cell.center.x, cell.center.y, p.x, p.y);
    }
    else 
    {
        NSLog(@"Not found");
    }
}

但是滚动不起作用。它因错误“尝试滚动到无效的索引路径”而崩溃。很明显 tempCollectionView 没有准备好滚动的任何单元格。

重新加载完成后如何滚动到索引路径?任何帮助都会很棒!

【问题讨论】:

  • 您应该可以在刷新集合视图后立即调用滚动方法。这是您的索引路径的问题。你打印出iPath 的行了吗?它比您的浏览量大还是小?
  • iPath 的行看起来是正确的,在单元格计数的范围内。不仅仅是滚动,我的目的是通过这个来获得单元格的位置。在上述方法中,单元格以 nil 形式返回。我在这里错过了什么吗?
  • 您正在调用 scrollToItem 两次。一次延迟,一次没有延迟。有可能 reloadData 没有立即完成调用,以便有任何索引路径可以使用。
  • 我忘记在此处放置 OR,我正在尝试使用其中编写的两个语句之一进行调用。谢谢!

标签: ios objective-c uicollectionview


【解决方案1】:

试试这个

BOOL _viewDidLayoutSubviewsForTheFirstTime = YES;

- (void)viewDidLoad
{
  [super viewDidLoad];
  _viewDidLayoutSubviewsForTheFirstTime = YES;
}

- (void)viewDidLayoutSubviews
{
  [super viewDidLayoutSubviews];
  // Only scroll when the view is rendered for the first time
  if (_viewDidLayoutSubviewsForTheFirstTime) {
    _viewDidLayoutSubviewsForTheFirstTime = NO;
    // Calling collectionViewContentSize forces the UICollectionViewLayout to actually render the layout
    [self.collectionView.collectionViewLayout collectionViewContentSize];
    // Now you can scroll to your desired indexPath or contentOffset
    [self.collectionView scrollToItemAtIndexPath:yourDesiredIndexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:NO];
  }
}

希望对大家有帮助

【讨论】:

    【解决方案2】:

    到目前为止我发现的最佳解决方案是像这样使用CATransaction

    CATransaction.begin()
    CATransaction.setCompletionBlock {
        collectionView.scrollToItem(...)
    }
    
    collectionView.reloadData()
    
    CATransaction.commit()
    

    【讨论】:

      【解决方案3】:

      如果你想垂直滚动,你可以试试这个异步代码

      dispatch_async(dispatch_get_main_queue(), ^{
          [_yourCollectionView reloadData];
          [_yourCollectionView reloadInputViews];
          [_yourCollectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:5 inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:YES];
      });
      

      并替换为

      [_yourCollectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:5 inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
      

      如果你想让你的滚动视图水平滚动

      indexPathForRowinSection 的数量替换为您要滚动到的行号,并记住 NSIndexPath 用于 UITableView 和 UICollectionView 通常带有 inSection 引用 Convert NSInteger to NSIndexpath

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-01-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-08
        相关资源
        最近更新 更多