我正在试图弄清楚当屏幕首次加载时如何一直滚动到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]。这不起作用。关于如何在视图加载时滚动到底部的任何想法?
答案 0 :(得分:34)
我发现viewWillAppear没有任何效果。我只能在viewDidLayoutSubviews中使用它:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
[self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:endOfModel inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
}
答案 1 :(得分:17)
只是详细说明我的意见。
在元素可视化之前调用viewDidLoad,因此无法很好地操作某些UI元素。比如在工作中移动按钮但处理子视图通常不会(比如滚动CollectionView)。
在viewWillAppear或viewDidAppear中调用时,大多数这些操作都会起作用。以下是Apple文档中的一个除了指出在重写这些方法时要做的重要事情:
您可以覆盖此方法以执行其他相关任务 与呈现视图。 如果覆盖此方法,则必须调用 在实施的某个时刻超级。
超级调用通常在自定义实现之前调用。 (所以重写方法中的第一行代码)。
答案 2 :(得分:7)
所以有一个类似的问题,这是另一种方法而不使用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];
}
答案 3 :(得分:6)
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)
答案 4 :(得分:3)
获取最后一项的索引路径。然后...
- (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated
答案 5 :(得分:3)
对我来说,我找到了下一个解决方案:
在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];
});
答案 6 :(得分:2)
这些都不适合我,我最终得到了这个,它可以在任何滚动视图上使用
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)
}
}
答案 7 :(得分:0)
问题可能是,即使您的收藏夹视图在屏幕上,也可能没有实际的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)
}
答案 8 :(得分:0)
考虑是否可以像这样使用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
是集合视图数据源中最后一项的索引,它将一直滚动到底部。