ChatGPT解决这个技术问题 Extra ChatGPT

获取 UIScrollView 滚动到顶部

如何让 UIScrollView 滚动到顶部?


r
rob mayoff

iOS 7 更新

[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];

如果您在 iOS 7 上执行此操作,那么很遗憾,您可能必须考虑 UIScrollView contentInset[self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, -self.scrollView.contentInset.top) animated:YES]; 为我完成这项工作
我能够滚动到顶部,导航和状态栏的正下方。 [scrollView setContentOffset:CGPointMake(0, -scrollView.contentInset.top) animated:YES]; 它适用于 iOS 6 和7
这对我不起作用,可能是因为我在 sprite kit 中使用倒置视图做一些疯狂的事情。但是,如果其他人像我一样疯狂-默认情况下您的滚动视图位于底部-这会将其滚动到顶部:[scrollView setContentOffset:CGPointMake(0, scrollView.contentSize.height-scrollView.frame.size.height) animated:YES];
最新评论:无论操作系统版本如何,您都应该调整内容插图。 iOS 7 碰巧使用它来允许在状态栏下方滚动内容,但它总是作为属性公开,因此总是被某人潜在使用。
对于 iOS 11+,Jakub Truhlář 在下面使用adjustedContentInset 的回答很有帮助,至少在我的情况下是这样。
A
Andrew Schreiber

这是一个 Swift 扩展,它使它变得简单:

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

用法:

myScrollView.scrollToTop()

M
Massimo Polimeni

对于斯威夫特 4

scrollView.setContentOffset(.zero, animated: true)

绝对是最好的现代答案。
J
Jakub Truhlář

iOS 11 及更高版本

尝试使用新的 adjustedContentInset (它甚至可以与 prefersLargeTitlessafe 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)

J
Jack Humphries

使用setContentOffset:animated:

[scrollView setContentOffset:CGPointZero animated:YES];

C
Cœur

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)

C
Cœur

在 iOS7 中,我无法让特定的滚动视图转到顶部,这在 iOS6 中有效,并使用它来设置滚动视图到顶部。

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

我在iOS7中有同样的问题。有谁知道如何为 UITableView 启用此功能?
有趣的是,当动画为 NO 时,这是如何工作的,但在动画为 YES 时则不然。如果是,那么它几乎滚动到 topdevgm16
A
Abdul Karim Khan

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

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

C
Community

rob mayoff's answer 的 Swift 3.0.1 版本:

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

u
user2898617

我想我的答案应该完全兼容 iOS 11 以及之前的版本(用于垂直滚动)

这考虑了新的adjustedContentInset,并且还考虑了在navigationBar 上启用prefersLargeTitles 时所需的额外偏移量,这似乎需要在默认值之上额外增加52px 偏移量

这有点棘手,因为adjustedContentInset 会根据titleBar 状态(大标题与小标题)而变化,因此我需要检查并查看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)
    }
}

受到 Jakub 解决方案的启发


V
Vitya Shurapov

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

大小检查器 - 滚动视图 - 内容插入 -> 从自动更改为从不。

Size Inspector - Constraints-“Align Top to”(顶部对齐约束)-第二项->从Superview.Top更改为Safe Area.Top并将值(常量字段)设置为0

https://i.stack.imgur.com/XpLaE.png


O
Ortwin Gentz

要完全复制状态栏的 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;
    });
}

在你的 UIScrollViewDelegate(或 UITable/UICollectionViewDelegate)中实现这个:

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

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

请注意,我滥用视图标签来传达“isScrollingToTop”状态,因为我需要跨视图控制器。如果您将标签用于其他内容,您可能希望将其替换为 iVar 或属性。


我还没有测试过,但如果你只使用 DISPATCH_TIME_NOW ,它应该在下一个运行循环中抛出这个。感谢您完成这项工作,不确定我是否还需要它,但很高兴知道。
这是一段时间以前,我不记得确切,但我相信这没有奏效。推迟到下一个运行循环通常是我在这种情况下尝试的第一件事。
p
pkamb

在现代 iOS 中,将滚动视图的内容偏移设置回其左上角 adjustedContentInset

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

S
Shoaib

滚动到顶部以查看 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)
            }
        }
    }
  }
}

b
bhucho

iOS 2.0+ Mac Catalyst 13.0+

您可以尝试:scrollView.scrollsToTop = true

您可以参考 documentation of developer.apple.com


您好,欢迎来到 Stack Overflow!请拿走tour。感谢您提供答案,但您能否添加关于它如何解决问题的解释?
这样做只会启用/禁用滚动到顶部的手势,这不是问题所在。
N
Narasimha Nallamsetty

我尝试了所有方法。但没有什么对我有用。最后我做到了。

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

它对我有用。

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


请删除这个。虽然当时它肯定是有道理的,但您的子视图层次结构问题与这个问题无关。
@Cristik 如果您的滚动视图不在视图层次结构中,或者您的计算机已关闭,那么这些当然都不起作用。但是OP问了一些非常狭窄的问题