UIScrollViewを取得して上部にスクロールします


回答:


316

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

50
iOS 7でこれを行う場合はUIScrollView contentInset、残念ながらを考慮する必要がある場合があります。[self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, -self.scrollView.contentInset.top) animated:YES];私のために仕事をします
runmad

11
ナビゲーションとステータスバーの真上までスクロールすることができました。 [scrollView setContentOffset:CGPointMake(0, -scrollView.contentInset.top) animated:YES];iOS 6および7で動作します
Amozoss 2013

これは私にはうまくいきませんでした。おそらく、スプライトキットの反転ビューで何かおかしなことをしているためです。しかし、他の誰かが私と同じくらい頭がおかしい-スクロールビューがデフォルトで一番下にある-これは一番上にスクロールします:[scrollView setContentOffset:CGPointMake(0, scrollView.contentSize.height-scrollView.frame.size.height) animated:YES];
GilesDMiddleton

最新のコメント:OSのバージョンに関係なく、コンテンツのインセットを調整する必要があります。iOS 7はたまたまステータスバーの下のスクロールコンテンツを許可するためにそれを使用しますが、常にプロパティとして公開されているため、常に誰かによって使用される可能性があります。
トミー

2
iOS 11以降の場合、少なくとも私の場合、JackbTruhlář氏の次のAdjustedContentInsetを使用した回答が役に立ちました。
tnev 2017年

61

簡単にするSwift拡張機能を次に示します。

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

使用法:

myScrollView.scrollToTop()

40

iOS 11以降

新しいで作業してみてくださいadjustedContentInset

例(上にスクロール):

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)

あなたが使用している場合でもprefersLargeTitlessafe areaなど




17

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)

8

iOS7では、特定のスクロールビューを一番上に表示するのに問題がありました。これはiOS6で機能し、これを使用してスクロールビューを一番上に移動するように設定しました。

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

iOS7でも同じ問題があります。UITableViewでこれを有効にする方法を知っている人はいますか?
DZenBot 2013

1
アニメーションがNOの場合にこれがどのように機能するかは面白いですが、AnimatedがYESの場合はそうではありません。YESの場合、ほぼtopdevgm16までスクロールします
Matt Becker


2

ステータスバーの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を使用した場合、次の実行ループでこれをスローするはずです。この作業を行っていただきありがとうございます。まだ必要かどうかはわかりませんが、知っておくと役に立ちます。
Dan Rosenstark 2017年

少し前のことで、正確には覚えていませんが、うまくいかなかったと思います。通常、次の実行ループへの延期は、そのような場合に最初に試すことです。
Ortwin Gentz 2017年

2

私は以前のバージョンと同様にiOS 11と完全に互換性があるはずの答えがあると思います(垂直スクロール用)

これは、新しい調整されたコンテンツインセットを考慮し、さらに、デフォルトが何であっても追加の52pxオフセットを必要とするように見えるナビゲーションバーでprefersLargeTitlesが有効になっている場合に必要な追加オフセットを考慮します。

これは少し注意が必要でした。なぜなら、調整されたコンテンツインセットはタイトルバーの状態(大きいタイトルと小さいタイトル)に応じて変化するため、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のソリューションに触発された


2

ナビゲーションバーが scrollViewコンテンツのごく一部に重なり、コンテンツが上から始まっていないように見える場合は非常に一般的です。それを修正するために私は2つのことをしました:

  • サイズインスペクタ-スクロールビュー- コンテンツインセット-> [自動]から[なし]に変更します。
  • サイズインスペクタ- Constraints-「に上揃え」(トップアラインメント制約) - 2番目のアイテム- > 変更Superview.Topから安全Area.Topへ0に値(定数フィールド)セット

コンテンツインセット-なし ScrolView.TopをSafe Area.Topに揃えます


1

以下のために上へスクロールUITableViewControllerUICollectionViewControllerまたは任意のUIViewController持ちますUIScrollView

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


-4

私はすべての方法を試しました。しかし、私には何もうまくいきませんでした。最後に私はこのようにしました。

self.view .addSubview(self.scroll)viewDidLoadにコード行を追加しました。スクロールビューのフレームのセットアップを開始し、スクロールビューにコンポーネントを追加した後。

それは私のために働いた。

self.view .addSubview(self.scroll)最初に行を追加したことを確認してください 。次に、UI要素を追加できます。


これを削除してください。その時点では確かに理にかなっていますが、サブビュー階層の問題はこの質問には関係ありません。
Dan Rosenstark 2017年

1
@Cristikスクロールビューがビュー階層にない場合、またはコンピューターがオフになっている場合、もちろんこれは機能しません。しかし、OPはかなり狭いものを尋ねました
ダンローゼンスターク2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.