让 UIScrollView 滚动到顶部

如何使 UIScrollView 滚动到顶部?

133954 次浏览

IOS7更新

[self.scrollView setContentOffset:
CGPointMake(0, -self.scrollView.contentInset.top) animated:YES];

原创的

[self.scrollView setContentOffset:CGPointZero animated:YES];

或者,如果你想保留水平滚动的位置,只是重置垂直位置:

[self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, 0)
animated:YES];

使用 setContentOffset:animated:

[scrollView setContentOffset:CGPointZero animated:YES];

在 iOS7中,我很难让一个特定的 scrollview 到达顶部,这在 iOS6中是可行的,我用它来设置 scrollview 到达顶部。

[self.myScroller scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];

要完全复制状态栏 scrollToTop 行为,我们不仅需要设置 contentOffset,还要确保显示 scrollIndicators。否则用户很快就会迷路。

完成此任务的唯一公共方法是 flashScrollIndicators。不幸的是,在设置 contentOffset 之后调用它一次没有任何效果,因为它是立即重置的。我发现它的工作时,做的闪光每次在 scrollViewDidScroll:

// define arbitrary tag number in a global constants or in the .pch file
#define SCROLLVIEW_IS_SCROLLING_TO_TOP_TAG 19291


- (void)scrollContentToTop {
[self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, -self.scrollView.contentInset.top) animated:YES];


self.scrollView.tag = SCROLLVIEW_IS_SCROLLING_TO_TOP_TAG;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.scrollView.tag = 0;
});
}

在您的 UIScrollViewgenerate (或 UITable/UICollectionViewgenerate)中实现以下功能:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView.tag == SCROLLVIEW_IS_SCROLLING_TO_TOP_TAG) {
[scrollView flashScrollIndicators];
}
}

与状态栏 scrollToTop 行为相比,隐藏延迟稍微短一些,但看起来仍然不错。

注意,我正在滥用 view 标记来传递“ isScrollingToTop”状态,因为我需要跨视图控制器进行此操作。如果您正在为其他事情使用标记,那么您可能需要使用 iVar 或属性来替换它。

Swift 2.0/3.0/4.0和 iOS 7 + 的答案:

let desiredOffset = CGPoint(x: 0, y: -self.scrollView.contentInset.top)
self.scrollView.setContentOffset(desiredOffset, animated: true)

下面是一个简单的 Swift 扩展:

extension UIScrollView {
func scrollToTop() {
let desiredOffset = CGPoint(x: 0, y: -contentInset.top)
setContentOffset(desiredOffset, animated: true)
}
}

用法:

myScrollView.scrollToTop()

我尝试了所有的方法。但没有一个适合我。最后我喜欢这样。

我在 viewDidLoad 中添加了 self.view .addSubview(self.scroll)代码行。开始设置滚动视图框架并添加组件到滚动视图。

这招对我很管用。

确保你在开头添加了 self.view .addSubview(self.scroll)行。然后你就可以添加 UI 元素了。

Swift 3.0.1版本的 Rob Mayoff 的回答:

self.scrollView.setContentOffset(
CGPoint(x: 0,y: -self.scrollView.contentInset.top),
animated: true)

滚动到顶部的 UITableViewControllerUICollectionViewController或任何具有 UIScrollViewUIViewController

extension UIViewController {


func scrollToTop(animated: Bool) {
if let tv = self as? UITableViewController {
tv.tableView.setContentOffset(CGPoint.zero, animated: animated)
} else if let cv = self as? UICollectionViewController{
cv.collectionView?.setContentOffset(CGPoint.zero, animated: animated)
} else {
for v in view.subviews {
if let sv = v as? UIScrollView {
sv.setContentOffset(CGPoint.zero, animated: animated)
}
}
}
}
}

IOS11及以上版本

试着玩玩新的 adjustedContentInset (它甚至可以与 ABC1、 safe area等协同工作。)

例如(滚动到顶部) :

var offset = CGPoint(
x: -scrollView.contentInset.left,
y: -scrollView.contentInset.top)


if #available(iOS 11.0, *) {
offset = CGPoint(
x: -scrollView.adjustedContentInset.left,
y: -scrollView.adjustedContentInset.top)
}


scrollView.setContentOffset(offset, animated: true)

为了 Swift 4

scrollView.setContentOffset(.zero, animated: true)

我想我有一个答案,应该是完全兼容 iOS11以及以前的版本(垂直滚动)

这考虑到了新的 调整内容,也考虑到了在导航栏上启用 首选大标题时所需的额外偏移量,这似乎需要在默认值之上额外增加52像素的偏移量

这有点棘手,因为 adjustedContentInset 根据 titleBar 状态(大标题 vs 小标题)而变化,所以我需要检查一下 titleBar 的高度,如果它已经处于大状态,就不应用52px 偏移量。找不到任何其他方法来检查导航栏的状态,所以如果有人有一个更好的选择比看看是否高度 > 44.0我想听到它

func scrollToTop(_ scrollView: UIScrollView, animated: Bool = true) {
if #available(iOS 11.0, *) {
let expandedBar = (navigationController?.navigationBar.frame.height ?? 64.0 > 44.0)
let largeTitles = (navigationController?.navigationBar.prefersLargeTitles) ?? false
let offset: CGFloat = (largeTitles && !expandedBar) ? 52: 0
scrollView.setContentOffset(CGPoint(x: 0, y: -(scrollView.adjustedContentInset.top + offset)), animated: animated)
} else {
scrollView.setContentOffset(CGPoint(x: 0, y: -scrollView.contentInset.top), animated: animated)
}
}

灵感来自雅各布的解决方案

导航栏重叠是 scrollView 内容的一小部分时,这种情况很常见,而且看起来内容不是从顶部开始的。为了修好它,我做了两件事:

  • 尺寸检查器-滚动视图 -内容插入—— > 从自动变为从不。
  • 尺寸检查器-约束-“顶部对齐到”(顶部对齐约束)-第二项-> 从 Superview 到安全区设置为0的值(常量字段)

Content insets - Never Align ScrolView.Top to Safe Area.Top

在 SWIFT 5 只需将内容偏移量设置为零

scrollView.setContentOffset(CGPoint.zero, animated: true)

IOS 2.0 + Mac Catalyst 13.0 +

你可以试试: scrollView.scrollsToTop = true

您可以从 Developer.apple.com 文件引用它

在现代的 iOS 系统中,将滚动视图的内容偏移设置为左上角的 adjustedContentInset:

let point = CGPoint(x: -scrollView.adjustedContentInset.left,
y: -scrollView.adjustedContentInset.top)
    

scrollView.setContentOffset(point, animated: true)