wake-up-neo.com

Holen Sie sich UIScrollView, um nach oben zu scrollen

Wie kann ich einen UIScrollView-Bildlauf nach oben ausführen?

159
abcd

UPDATE FÜR iOS 7

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

ORIGINAL

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

oder wenn Sie die horizontale Bildlaufposition beibehalten und einfach die vertikale Position zurücksetzen möchten:

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

Hier ist eine Swift Erweiterung, die es einfach macht:

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

Verwendung:

myScrollView.scrollToTop()
51

iOS 11 und höher

versuchen Sie, mit dem neuen adjustedContentInset zu arbeiten.

Zum Beispiel (nach oben scrollen):

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)

Auch wenn Sie prefersLargeTitles, safe area etc.

32
Jakub Truhlář

Für Swift 4

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

Verwenden setContentOffset:animated:

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

Antwort für Swift 2.0/3.0/4.0 und iOS 7+:

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

In iOS7 hatte ich Probleme damit, eine bestimmte Bildlaufansicht nach oben zu verschieben, was in iOS6 funktioniert hat, und habe diese verwendet, um die Bildlaufansicht nach oben zu verschieben.

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

Swift 3.0.1 Version von Rob Mayoffs Antwort :

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

Um das Verhalten von scrollToTop in der Statusleiste vollständig zu replizieren, müssen Sie nicht nur contentOffset festlegen, sondern auch sicherstellen, dass die scrollIndicators angezeigt werden. Andernfalls kann der Benutzer schnell verloren gehen.

Die einzige öffentliche Methode, um dies zu erreichen, ist flashScrollIndicators. Leider hat ein einmaliger Aufruf nach dem Setzen des contentOffset keine Auswirkung, da dieser sofort zurückgesetzt wird. Ich fand es funktioniert, wenn ich den Blitz jedes Mal in 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;
    });
}

Implementieren Sie in Ihrem UIScrollViewDelegate (oder UITable/UICollectionViewDelegate) Folgendes:

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

Die Ausblendverzögerung ist im Vergleich zum scrollToTop-Verhalten in der Statusleiste etwas kürzer, sieht aber trotzdem gut aus.

Beachten Sie, dass ich das View-Tag missbrauche, um den Status "isScrollingToTop" zu übermitteln, da ich dies für mehrere View-Controller benötige. Wenn Sie Tags für etwas anderes verwenden, möchten Sie diese möglicherweise durch eine iVar oder eine Eigenschaft ersetzen.

2
Ortwin Gentz

Ich denke, ich habe eine Antwort, die mit iOS 11 sowie früheren Versionen (für vertikales Scrollen) vollständig kompatibel sein sollte.

Dies berücksichtigt das neue adjustedContentInset und berücksichtigt auch den zusätzlichen Offset, der erforderlich ist, wenn prefersLargeTitles in der Navigationsleiste aktiviert ist, was einen zusätzlichen 52px-Offset über den Standardwert hinaus zu erfordern scheint ist

Dies war etwas schwierig, da sich das adjustierte Inhalts-Set in Abhängigkeit vom Status der Titelleiste ändert (großer Titel vs. kleiner Titel). Ich musste also überprüfen, wie hoch die Titelleiste war, und den 52-Pixel-Versatz nicht anwenden, wenn er bereits groß ist. Es konnte keine andere Methode gefunden werden, um den Status der Navigationsleiste zu überprüfen. Wenn also jemand eine bessere Option hat als zu sehen, ob die Höhe> 44,0 ist, würde ich sie gerne hören

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

Inspiriert von Jakubs Lösung

2
user2898617

Scrolle nach oben für UITableViewController, UICollectionViewController oder ein beliebiges UIViewController mit 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

Es kommt sehr häufig vor, dass Ihre Navigationsleiste den kleinen Teil des scrollView-Inhalts überlappt und der Inhalt nicht von oben beginnt. Um das Problem zu beheben, habe ich zwei Dinge getan:

  • Größeninspektor - Bildlaufansicht - Inhaltseinfügungen -> Wechseln von Automatisch zu Nie.
  • Größeninspektor - Einschränkungen - "Oben ausrichten an" (Einschränkungen für die obere Ausrichtung) - Zweites Element -> Wechseln Sie von "Superview.Top" zu "Safe Area.Top" und der Wert (konstantes Feld) auf 0 gesetzt

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

0
Vitya Shurapov