UITableView - Scrollen Sie nach oben


393

In meiner Tabellenansicht muss ich nach oben scrollen. Ich kann jedoch nicht garantieren, dass das erste Objekt Abschnitt 0, Zeile 0 ist. Möglicherweise beginnt meine Tabellenansicht mit Abschnitt 5.

Ich bekomme also eine Ausnahme, wenn ich anrufe:

[mainTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];

Gibt es eine andere Möglichkeit, zum Anfang der Tabellenansicht zu scrollen?

Antworten:


857

UITableView ist eine Unterklasse von UIScrollView, daher können Sie auch Folgendes verwenden:

[mainTableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];

Oder

[mainTableView setContentOffset:CGPointZero animated:YES];

Und in Swift:

mainTableView.setContentOffset(CGPointZero, animated:true)

Und in Swift 3 und höher:

mainTableView.setContentOffset(.zero, animated: true)

9
Ich habe dies zuerst mit CGRectZero versucht, was CGRectMake (0, 0, 0, 0) entspricht. Dies funktioniert nicht, aber seltsamerweise funktioniert das oben Genannte. Ich denke, es braucht eine positive Breite und Höhe. Vielen Dank.
Keller

5
Beachten Sie, dass Sie animiert werden möchten : NEIN, wenn Sie dies in scrollToRowAtIndexPath ausführen: damit die Tabelle an der richtigen Position beginnt. Ich hoffe es hilft!
Fattie

3
@ hasan83 CGRectMake (0, 0, 0, 0) oder CGRectZero ist kein sichtbares Rect. Ich würde auch sagen, dass [mainTableView setContentOffset: CGPointZero animiert: YES]; ist der schönere Ausdruck.
Catlan

8
Hat jemand bemerkt, dass in iOS11 alles kaputt ist und in einigen Fällen nicht richtig gescrollt wird?
Peter Lapisu

11
@ PeterLapisu self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: UITableViewScrollPosition.top, animated: true)scheint in iOS 11 zu funktionieren
Jordan S

246

Hinweis : Diese Antwort gilt nicht für iOS 11 und höher.

ich bevorzuge

[mainTableView setContentOffset:CGPointZero animated:YES];

Wenn Ihre Tabellenansicht einen oberen Einschub enthält, müssen Sie diesen subtrahieren:

[mainTableView setContentOffset:CGPointMake(0.0f, -mainTableView.contentInset.top) animated:YES];

12
Tomate, Tomate. Hmm ... Das kommt schriftlich nicht sehr deutlich rüber.
FreeAsInBeer

14
Dies ist die beste Methode, wenn Sie Tabellenkopf- oder Fußzeilenansichten haben und diese auch einschließen möchten.
Mafonya

6
Dies ist in der Tat ein klarer Code, aber er funktioniert nicht, wenn Sie von oben tableViewnicht Null haben contentInset. Zum Beispiel : tableView.contentInset = UIEdgeInsetsMake(5.0f, 0.0f, 250.0f, 0.0f);. Wenn dies der Fall ist, wird in Ihrem Code ein tableViewBildlauf durchgeführt (0.0f, 5.0f).
Tolgamorf

25
Die Lösung für meinen vorherigen Kommentar:[tableView setContentOffset:CGPointMake(0.0f, -tableView.contentInset.top) animated:YES];
Tolgamorf

3
Unter iOS 11 sollten Sie -scrollView.adjustedContentInset.topstattdessen die Verwendung in Betracht ziehen .
Marián Černý

79

Mögliche Aktionen:

1

func scrollToFirstRow() {
    let indexPath = NSIndexPath(forRow: 0, inSection: 0)
    self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
}

2

func scrollToLastRow() {
    let indexPath = NSIndexPath(forRow: objects.count - 1, inSection: 0)
    self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: true)
}

3

func scrollToSelectedRow() {
    let selectedRows = self.tableView.indexPathsForSelectedRows
    if let selectedRow = selectedRows?[0] as? NSIndexPath {
        self.tableView.scrollToRowAtIndexPath(selectedRow, atScrollPosition: .Middle, animated: true)
    }
}

4

func scrollToHeader() {
    self.tableView.scrollRectToVisible(CGRect(x: 0, y: 0, width: 1, height: 1), animated: true)
}

5

func scrollToTop(){
    self.tableView.setContentOffset(CGPointMake(0,  UIApplication.sharedApplication().statusBarFrame.height ), animated: true)
}

Bildlauf nach oben deaktivieren:

func disableScrollsToTopPropertyOnAllSubviewsOf(view: UIView) {
    for subview in view.subviews {
        if let scrollView = subview as? UIScrollView {
            (scrollView as UIScrollView).scrollsToTop = false
        }
        self.disableScrollsToTopPropertyOnAllSubviewsOf(subview as UIView)
    }
}

Ändern und verwenden Sie es gemäß den Anforderungen.

Swift 4

  func scrollToFirstRow() {
    let indexPath = IndexPath(row: 0, section: 0)
    self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
  }

Das ist die Lösung, perfekt - scrollToFirstRow
Mehul

Hervorragende Zusammenfassung. Wenn Sie Abschnittsüberschriften haben, müssen Sie Option 4 scrollToHeader verwenden.
Vincent

Gibt es eine Möglichkeit, zu einer Suchleiste über der Tabellenansicht zu scrollen?
Tyler Rutt

27

Es ist besser, weder NSIndexPath (leere Tabelle) zu verwenden, noch anzunehmen, dass der oberste Punkt CGPointZero (Inhaltseinfügungen) ist. Das verwende ich -

[tableView setContentOffset:CGPointMake(0.0f, -tableView.contentInset.top) animated:YES];

Hoffe das hilft.


Ab

21

Swift 4 :

Das funktioniert sehr gut:

//self.tableView.reloadData() if you want to use this line remember to put it before 
let indexPath = IndexPath(row: 0, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)

3
Nicht, wenn Sie eine tableHeaderView in Ihrer tableView haben und diese inline ist (scrollt mit dem Inhalt)
finneycanhelp

1
Ich habe sowohl eine Ebene als auch eine UITableViewStyleGrouped(Kopfzeilen scrollen mit dem Inhalt) und dieser Code funktioniert. Stellen Sie sicher, dass Sie sich im Hauptthread befinden und diesen Code starten, nachdem die Ansicht angezeigt wurde ( viewDidAppear). Wenn Sie immer noch Probleme haben, versuchen Sie, den Code in diesen zu setzen:DispatchQueue.main.asyncAfter(deadline: .now()+0.1, execute: { // the code }
Alessandro Ornano

1
Vielen Dank. Sie gelangen in die erste Zelle. Der Header der Tabellenansicht wird jedoch nicht angezeigt.
Finneycanhelp

Dies wird fehlschlagen, wenn die tableView aus irgendeinem Grund leer ist (keine Zelle in 0 Abschnitt in 0 Zeile)
Maxim Skryabin

17

Ich habe ein Problem beim Aufrufen einiger Methoden auf einer leeren Seite festgestellt tableView. Hier ist eine weitere Option für Swift 4, die leere Tabellenansichten verarbeitet.

extension UITableView {
  func hasRowAtIndexPath(indexPath: IndexPath) -> Bool {
    return indexPath.section < self.numberOfSections && indexPath.row < self.numberOfRows(inSection: indexPath.section)
  }

  func scrollToTop(animated: Bool) {
    let indexPath = IndexPath(row: 0, section: 0)
    if self.hasRowAtIndexPath(indexPath: indexPath) {
      self.scrollToRow(at: indexPath, at: .top, animated: animated)
    }
  }
}

Verwendungszweck:

// from yourViewController or yourTableViewController
tableView.scrollToTop(animated: true)//or false

Dies berücksichtigt keine Tabellen- oder Abschnittsüberschriften.
rmaddy

16

NICHT VERWENDEN

 tableView.setContentOffset(.zero, animated: true)

Manchmal kann der Offset falsch eingestellt werden. In meinem Fall befand sich die Zelle beispielsweise tatsächlich leicht über der Ansicht mit Einfügungen für sichere Bereiche. Nicht gut.

STATT VERWENDUNG

 tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)

1
Perfekte Lösung.
Baby Groot

Genau das, wonach ich gesucht habe, danke.
Simon

Keine dieser Lösungen ist gültig. Das erste funktioniert nicht unter iOS 11 oder höher. Die zweite Funktion funktioniert nicht, wenn die Tabellenansicht eine Tabellenüberschrift oder der erste Abschnitt eine Abschnittsüberschrift enthält, es sei denn, Sie möchten wirklich die erste Zeile oben und möchten keine Überschriften anzeigen.
rmaddy

@rmaddy was ist die beste Lösung?
ScottyBlades

15

Verwenden Sie unter iOS 11, um adjustedContentInsetin beiden Fällen, in denen die Statusleiste für Anrufe angezeigt wird oder nicht, korrekt nach oben zu scrollen.

if (@available(iOS 11.0, *)) {
    [tableView setContentOffset:CGPointMake(0, -tableView.adjustedContentInset.top) animated:YES];
} else {
    [tableView setContentOffset:CGPointMake(0, -tableView.contentInset.top) animated:YES];
}

Schnell:

if #available(iOS 11.0, *) {
    tableView.setContentOffset(CGPoint(x: 0, y: -tableView.adjustedContentInset.top), animated: true)
} else {
    tableView.setContentOffset(CGPoint(x: 0, y: -tableView.contentInset.top), animated: true)
}

12

Bei Tabellen mit a funktioniert das contentInsetFestlegen des Inhaltsversatzes auf CGPointZeronicht. Es wird zum Inhaltsverzeichnis gescrollt und nicht zum Tischverzeichnis.

Die Berücksichtigung des eingefügten Inhalts führt stattdessen dazu:

[tableView setContentOffset:CGPointMake(0, -tableView.contentInset.top) animated:NO];

1
Vielen Dank, ich habe es immer wieder auf CGPointZero eingestellt und konnte nicht verstehen, warum dies geschah.
Johnrechd

Ab

10

Mit diesem Code können Sie einen bestimmten Abschnitt nach oben scrollen

CGRect cellRect = [tableinstance rectForSection:section];
CGPoint origin = [tableinstacne convertPoint:cellRect.origin 
                                    fromView:<tableistance>];
[tableinstance setContentOffset:CGPointMake(0, origin.y)];

Dies war der einfachste Code und es funktionierte in Ordnung. Ich habe tatsächlich CGPointMake (0.0f, 0.0f) geputtet. Prost!
Felipe

Dieser Code ist sehr nützlich, um den Abschnitt nach oben zu scrollen
srinivas n


8

Swift 3

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

wenn tableView.setContentOffsetnicht funktionieren.

Verwenden:

tableView.beginUpdates()
tableView.setContentOffset(CGPoint.zero, animated: true)
tableView.endUpdates()

1
Dies gilt nicht für iOS 11 oder höher.
rmaddy

7

Da meine tableViewmit allen Arten von Einsätzen gefüllt ist, war dies das einzige, was gut funktionierte:

Swift 3

if tableView.numberOfSections > 0 && tableView.numberOfRows(inSection: 0) > 0 {
  tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
}

Swift 2

if tableView.numberOfSections > 0 && tableView.numberOfRowsInSection(0) > 0 {
  tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: .Top, animated: true)
}

das war nützlicher für mich
Tejzeratul

tolle Antwort, schätze es
Jeremy Bader

7

Sie können eine Erweiterung (Swift) oder Kategorie (Ziel C) erstellen, um dies in Zukunft zu vereinfachen:

Schnell:

extension UITableView {
    func scrollToTop(animated: Bool) {
        setContentOffset(CGPointZero, animated: animated)
    }
}

Wenn Sie eine bestimmte Tabellenansicht nach oben scrollen möchten, können Sie den folgenden Code aufrufen:

tableView.scrollToTop(animated: true)

2
Ab

6

Ich bevorzuge das Folgende, da es einen Einschub berücksichtigt. Wenn kein Einschub vorhanden ist, wird immer noch nach oben gescrollt, da der Einschub 0 ist.

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

Ab

5

Swift:

Wenn Sie keinen tableView-Header haben:

tableView.setContentOffset(CGPointMake(0,  UIApplication.sharedApplication().statusBarFrame.height ), animated: true)

wenn ja :

tableView.setContentOffset(CGPointMake(0, -tableViewheader.frame.height   + UIApplication.sharedApplication().statusBarFrame.height ), animated: true)

5

Swift 5, iOS 13

Ich weiß, dass diese Frage bereits viele Antworten hat, aber meiner Erfahrung nach gibt es nur eine Methode, die immer funktioniert:

tableView.scrollToRow(at: IndexPath(row: someArray.count - 1, section: 0), at: .bottom, animated: true)

Wenn Sie asynchron arbeiten, Tabellen mit Tastaturen animieren usw., werden die anderen Antworten häufig fast nach unten und nicht nach unten gescrollt. Diese Methode bringt Sie jedes Mal zum absoluten Ende einer Tabelle.


Sie müssen auch überprüfen, ob es einen Abschnitt gibt
Onur Thunfisch

4

Folgendes verwende ich, um unter iOS 11 richtig zu arbeiten:

extension UIScrollView {
    func scrollToTop(animated: Bool) {
        var offset = contentOffset
        if #available(iOS 11, *) {
            offset.y = -adjustedContentInset.top
        } else {
            offset.y = -contentInset.top
        }
        setContentOffset(offset, animated: animated)
    }
}

4

In Swift 5 vielen Dank @ Adrian Antwort

extension UITableView{

    func hasRowAtIndexPath(indexPath: IndexPath) -> Bool {
        return indexPath.section < numberOfSections && indexPath.row < numberOfRows(inSection: indexPath.section)
    }

    func scrollToTop(_ animated: Bool = false) {
        let indexPath = IndexPath(row: 0, section: 0)
        if hasRowAtIndexPath(indexPath: indexPath) {
            scrollToRow(at: indexPath, at: .top, animated: animated)
        }
    }

}

Verwendungszweck:

tableView.scrollToTop()

2
1. Dies gilt auch in Swift 4. 2. Dies funktioniert nicht, wenn ein Tabellenkopf oder ein Abschnittskopf vorhanden ist.
rmaddy

3

Die Verwendung von contentOffset ist nicht der richtige Weg. Dies wäre besser, da dies die natürliche Art der Tabellenansicht ist

tableView.scrollToRow(at: NSIndexPath.init(row: 0, section: 0) as IndexPath, at: .top, animated: true)

2
Dies funktioniert nicht, wenn ein Tabellenkopf oder ein Abschnittskopf vorhanden ist.
rmaddy

3

Dies war das einzige Code-Snippet, das für mich funktioniert hat

Swift 4:

    tableView.scrollRectToVisible(CGRect(x: 0, y: 0, width: 1, height: 1), animated: true)
    tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
    tableView.setContentOffset(CGPoint(x: 0, y: -70), animated: true)

PS 70 ist die Höhe meiner Header- und Tabellenansichtszelle


Dies ist bei weitem nicht der richtige Weg, um nach oben zu scrollen. Es macht keinen Sinn, drei separate Zeilen zu verwenden, um nur den Inhaltsversatz festzulegen. Es wird nur die letzte Zeile benötigt, aber die Hardcodierung eines bestimmten Versatzes ist nicht die richtige Lösung.
rmaddy

2
func scrollToTop() {
        NSIndexPath *topItem = [NSIndexPath indexPathForItem:0 inSection:0];
        [tableView scrollToRowAtIndexPath:topItem atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

Rufen Sie diese Funktion überall dort auf, wo UITableView nach oben scrollen soll


2

Swift 4 über Erweiterung, behandelt leere Tabellenansicht:

extension UITableView {
    func scrollToTop(animated: Bool) {
        self.setContentOffset(CGPoint.zero, animated: animated);
    }
}

Dies gilt nicht ab iOS 11.
rmaddy

2

Ich verwende tabBarController und habe auf jeder Registerkarte ein paar Abschnitte in meiner Tabellenansicht, daher ist dies die beste Lösung für mich.

extension UITableView {

    func scrollToTop(){

        for index in 0...numberOfSections - 1 {
            if numberOfSections > 0 && numberOfRows(inSection: index) > 0 {
                scrollToRow(at: IndexPath(row: 0, section: index), at: .top, animated: true)
                break
            }

            if index == numberOfSections - 1 {
                setContentOffset(.zero, animated: true)
                break
            }
        }

    }

}

1

Ich musste das Multiplizieren mit -1 *zur Summe der Statusleiste und der Navigationsleiste addieren , weil es so hoch vom Bildschirm war.

self.tableView.setContentOffset(CGPointMake(0 , -1 * 
  (self.navigationController!.navigationBar.height +  
  UIApplication.sharedApplication().statusBarFrame.height) ), animated:true)

1

in schnell

Ihre Zeile = selectioncellRowNumber Ihr Abschnitt, wenn Sie = selectionNumber haben, wenn Sie nicht gesetzt haben, ist auf Null

//UITableViewScrollPosition.Middle oder Bottom oder Top

var lastIndex = NSIndexPath(forRow:  selectioncellRowNumber, inSection: selectionNumber)
self.tableView.scrollToRowAtIndexPath(lastIndex, atScrollPosition: UITableViewScrollPosition.Middle, animated: true)

1

Hier ist der Code für ScrollTableView, um programmgesteuert nach oben zu gelangen

Schnell:

self.TableView.setContentOffset(CGPointMake(0, 1), animated:true)

1

In Swift-3:

self.tableView.setContentOffset(CGPoint.zero, animated: true)

0

Wenn Sie eine Scroll-Animation in der Tabelle verschieben möchten, verwenden Sie diesen Code. Der Bildlauf wird in 0,5 Sekunden mit Animation nach oben verschoben.

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

[_tableContent scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];

[UIView commitAnimations];

0

Mit Swift:

self.scripSearchView.quickListTbl?.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.