【问题标题】:UICollectionView automatically scroll to bottom when screen loadsUICollectionView 在屏幕加载时自动滚动到底部
【发布时间】:2013-01-23 12:08:57
【问题描述】:

我试图弄清楚当屏幕首次加载时如何一直滚动到 UICollectionView 的底部。当状态栏被触摸时,我可以滚动到底部,但我希望能够在视图加载时自动执行此操作。如果我想在触摸状态栏时滚动到底部,则以下内容可以正常工作。

- (BOOL)scrollViewShouldScrollToTop:(UITableView *)tableView
{
NSLog(@"Detect status bar is touched.");
[self scrollToBottom];
return NO;
}

-(void)scrollToBottom
{//Scrolls to bottom of scroller
 CGPoint bottomOffset = CGPointMake(0, collectionViewReload.contentSize.height -     collectionViewReload.bounds.size.height);
 [collectionViewReload setContentOffset:bottomOffset animated:NO];
 }

我尝试在 viewDidLoad 中调用 [self scrollToBottom]。这是行不通的。关于在视图加载时如何滚动到底部的任何想法?

【问题讨论】:

  • 尝试在 viewWillAppear 中进行,如果不起作用,请尝试 viewDidAppear。
  • 太棒了!!谢谢乔尔,viewDidAppear 有效。

标签: ios objective-c uiscrollview uicollectionview


【解决方案1】:

我发现在 viewWillAppear 中没有任何用处。我只能让它在 viewDidLayoutSubviews 中工作:

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:endOfModel inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
}

【讨论】:

  • 请注意,在导航回此视图控制器或方向更改后,视图将再次滚动到底部。如果需要,不要忘记使用适当的条件(可能是布尔值)来处理它。
【解决方案2】:

只是为了详细说明我的评论。

viewDidLoad 在元素可见之前调用,因此某些 UI 元素无法很好地操作。诸如在工作中移动按钮但处理子视图通常不会(如滚动 CollectionView)。

大多数这些操作在 viewWillAppear 或 viewDidAppear 中调用时效果最佳。这是 Apple 文档中的一个例外,它指出了在覆盖这些方法中的任何一个时要做的重要事情:

您可以重写此方法以执行相关的其他任务 与呈现视图。 如果你重写这个方法,你必须调用 在您的实施中的某个时刻超级。

super 调用通常在自定义实现之前调用。 (所以在被覆盖的方法中的第一行代码)。

【讨论】:

    【解决方案3】:

    所以遇到了类似的问题,这是另一种解决方法不使用 scrollToItemAtIndexPath

    仅当内容大于视图框架时才会滚动到底部。

    使用 scrollToItemAtIndexPath 可能更好,但这只是另一种方法。

    CGFloat collectionViewContentHeight = myCollectionView.contentSize.height;
    CGFloat collectionViewFrameHeightAfterInserts = myCollectionView.frame.size.height - (myCollectionView.contentInset.top + myCollectionView.contentInset.bottom);
    
    if(collectionViewContentHeight > collectionViewFrameHeightAfterInserts) {
       [myCollectionView setContentOffset:CGPointMake(0, myCollectionView.contentSize.height - myCollectionView.frame.size.height) animated:NO];
    }
    

    【讨论】:

    • scrollToItemAtIndexPath滚动到最后一个单元格的底部,但是你的方法很好滚动到单元格底部+底部昆虫空间,这对我来说很好。这就是你尝试这样做的原因吗?
    【解决方案4】:

    Swift 3 示例

    let sectionNumber = 0
    self.collectionView?.scrollToItem(at: //scroll collection view to indexpath
                                      NSIndexPath.init(row:(self.collectionView?.numberOfItems(inSection: sectionNumber))!-1, //get last item of self collectionview (number of items -1)
                                                       section: sectionNumber) as IndexPath //scroll to bottom of current section
                                    , at: UICollectionViewScrollPosition.bottom, //right, left, top, bottom, centeredHorizontally, centeredVertically
                                    animated: true)
    

    【讨论】:

      【解决方案5】:

      获取最后一项的索引路径。那么……

      - (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated
      

      【讨论】:

        【解决方案6】:

        对我来说,我找到了下一个解决方案:

        在CollectionView中调用reloadData,在main上使dcg滚动。

         __weak typeof(self) wSelf = self;
        
         [wSelf.cv reloadData];
         dispatch_async(dispatch_get_main_queue(), ^{
         NSLog(@"HeightGCD:%@", @(wSelf.cv.contentSize.height));
         [wSelf.cv scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:50 inSection:0] atScrollPosition:UICollectionViewScrollPositionBottom animated:YES];
         });
        

        【讨论】:

        • 你使用 GCD 进入主线程救了我。我有一个几乎无法追踪的错误,这显然是由于我试图在后台线程上滚动造成的......我不知道我正在打开。
        【解决方案7】:

        这些对我来说都不是很好,我最终得到了这个在任何滚动视图上都可以工作

        extension UIScrollView {
            func scrollToBottom(animated: Bool) {
                let y = contentSize.height - 1
                let rect = CGRect(x: 0, y: y + safeAreaInsets.bottom, width: 1, height: 1)
                scrollRectToVisible(rect, animated: animated)
            }
        }
        

        【讨论】:

          【解决方案8】:

          问题很可能是即使您的收藏视图在屏幕上,它也可能没有实际的contentSize

          如果您在viewDidAppear 中滚动,您将获得contentSize,但您的 scollectionview 会在滚动之前短暂显示内容。

          viewDidLayoutSubviews 的问题是它被多次调用,所以你需要添加一个丑陋的布尔值来限制滚动。

          我发现的最佳解决方案是强制布局在视图中出现。

          override func viewWillAppear(_ animated: Bool) {
              super.viewWillAppear(animated)
              // force layout before scrolling to most recent
              collectionView.layoutIfNeeded()
              // now you can scroll however you want
              // e.g. scroll to the right
              let offset = collectionView.contentSize.width - collectionView.bounds.size.width
              collectionView.setContentOffSet(CGPoint(x: offset, y: 0), animated: animated)
          }
          

          【讨论】:

            【解决方案9】:

            考虑是否可以像这样使用performBatchUpdates

            private func reloadAndScrollToItem(at index: Int, animated: Bool) {
                collectionView.reloadData()
                collectionView.performBatchUpdates({
                    self.collectionView.scrollToItem(at: IndexPath(item: index, section: 0),
                                                     at: .bottom,
                                                     animated: animated)
                }, completion: nil)
            }
            

            如果index 是集合视图数据源中最后一项的索引,它将一直滚动到底部。

            【讨论】:

              猜你喜欢
              • 2018-12-06
              • 2021-10-28
              • 1970-01-01
              • 1970-01-01
              • 2019-05-31
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多