web-dev-qa-db-ja.com

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

UIScrollViewを一番上までスクロールするにはどうすればよいですか?

157
Jack

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];
304
rob mayoff

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

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

使用法:

myScrollView.scrollToTop()
51

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などを使用しても.

30
Jakub Truhlář

Swift 4の場合

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

setContentOffset:animated:を使用

[scrollView setContentOffset:CGPointZero animated:YES];
22
Bryan Chen

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)
16
worthbak

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

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

rob mayoff's answer のSwift 3.0.1バージョン:

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

ステータスバーのscrollToTopの動作を完全に複製するには、contentOffsetを設定するだけでなく、scrollIndicatorsが表示されるようにする必要もあります。そうしないと、ユーザーはすぐに迷子になります。

これを実現する唯一のパブリックメソッドはflashScrollIndicatorsです。残念ながら、contentOffsetを設定した後に1回呼び出しても、すぐにリセットされるため、効果はありません。 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の動作に比べて少し短いですが、見た目はいいです。

View Controller全体でこれが必要なため、「isScrollingToTop」状態を伝えるためにviewタグを悪用していることに注意してください。他のタグを使用している場合、これをiVarまたはプロパティに置き換えることができます。

2
Ortwin Gentz

私はiOS 11と以前のバージョン(垂直スクロール用)と完全に互換性があるべき答えがあると思う

これは、新しいadjustedContentInsetを考慮に入れ、さらにprefersLargeTitlesがデフォルトに加えて追加の52pxオフセットを必要とするように見えるnavigationBarで有効になっている場合に必要な追加のオフセットも考慮しますは

AdjustContentInsetは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のソリューションに触発された

1
user2898617

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

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

  • サイズインスペクター-スクロールビュー-コンテンツインセット->自動からネバーへの変更
  • サイズインスペクター-制約-「上に揃える」(上部の整列制約)-2番目の項目->Superview.TopからSafe Area.Topに変更0に設定された値(定数フィールド)

Content insets - NeverAlign ScrolView.Top to Safe Area.Top

0
Vitya Shurapov