ios UICollectionView 在屏幕加载时自动滚动到底部

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14760496/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 22:12:45  来源:igfitidea点击:

UICollectionView automatically scroll to bottom when screen loads

iosobjective-cuiscrollviewuicollectionview

提问by SNV7

I'm trying to figure out how to scroll all the way to the bottom of a UICollectionView when the screen first loads. I'm able to scroll to the bottom when the status bar is touched, but I'd like to be able to do that automatically when the view loads as well. The below works fine if I want to scroll to the bottom when the status bar is touched.

我试图弄清楚如何在屏幕第一次加载时一直滚动到 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];
 }

I've tried calling [self scrollToBottom] in the viewDidLoad. This isn't working. Any ideas on how I can scroll to the bottom when the view loads?

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

采纳答案by Firo

Just to elaborate on my comment.

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

viewDidLoad is called before elements are visual so certain UI elements cannot be manipulated very well. Things like moving buttons around work but dealing with subviews often does not (like scrolling a CollectionView).

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

Most of these actions will work best when called in viewWillAppear or viewDidAppear. Here is an except from the Apple docs that points out an important thing to do when overriding either of these methods:

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

You can override this method to perform additional tasks associated with presenting the view. If you override this method, you must call super at some point in your implementation.

您可以覆盖此方法以执行与呈现视图相关的其他任务。如果覆盖此方法,则必须在实现中的某个时刻调用 super。

The super call is generally called before custom implementations. (so the first line of code inside of the overridden methods).

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

回答by Will Larche

I found that nothing would work in viewWillAppear. I can only get it to work in viewDidLayoutSubviews:

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

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

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

回答by Fazri

So had a similar issue and here is another way to come at it without using scrollToItemAtIndexPath

所以有一个类似的问题,这是另一种不使用 scrollToItemAtIndexPath 的方法

This will scroll to the bottom only if the content is larger than the view frame.

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

It's probably better to use scrollToItemAtIndexPath but this is just another way to do it.

使用 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];
}

回答by mourodrigo

Swift 3 example

斯威夫特 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)

回答by mourodrigo

Get indexpath for last item. Then...

获取最后一项的索引路径。然后...

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

回答by Dmitry Nelepov

For me, i found next solution:

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

call reloadData in CollectionView, and make dcg on main to scroll.

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

 __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];
 });

回答by Jason Moore

The issue is likely that even if your collection view is on screen, it might not have the actual contentSize.

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

If you scroll in viewDidAppear, you will have a contentSize, but your scollectionview will briefly show content before scrolling.

如果您滚动viewDidAppear,您将有一个contentSize,但您的 scollectionview 将在滚动前简要显示内容。

And the problem with viewDidLayoutSubviewsis that it is called multiple times, so you then need to add an ugly boolean to limit scrolling.

问题viewDidLayoutSubviews在于它被多次调用,因此您需要添加一个丑陋的布尔值来限制滚动。

The best solution i've found is to force layout in view will appear.

我发现的最佳解决方案是强制显示布局。

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)
}