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?

Ilya Suzdalnitski
quelle

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)
Catlan
quelle
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];
fabb
quelle
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)
  }
AG
quelle
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.

Kof
quelle
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)
Alessandro Ornano
quelle
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
Adrian
quelle
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)
ScottyBlades
quelle
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)
}
Thanh Pham
quelle
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];
Eran Goldin
quelle
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)];
Ramesh Muthe
quelle
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

Schnell:

tableView.setContentOffset(CGPointZero, animated: true)
Esqarrouth
quelle
Ab
8

Swift 3

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

wenn tableView.setContentOffsetnicht funktionieren.

Verwenden:

tableView.beginUpdates()
tableView.setContentOffset(CGPoint.zero, animated: true)
tableView.endUpdates()
Исмаил Хасбулатов
quelle
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)
}
Budidino
quelle
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)
ocwang
quelle
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)
Jacob
quelle
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)
jmcastel
quelle
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.

bsod
quelle
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)
    }
}
Hans Brende
quelle
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()
dengST30
quelle
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)
Gulz
quelle
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

jimmyruby
quelle
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

Sayali Shinde
quelle
2

Swift 4 über Erweiterung, behandelt leere Tabellenansicht:

extension UITableView {
    func scrollToTop(animated: Bool) {
        self.setContentOffset(CGPoint.zero, animated: animated);
    }
}
Shawn
quelle
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
            }
        }

    }

}
Okan
quelle
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)
Carlos.V
quelle
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)
idris yıldız
quelle
1

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

Schnell:

self.TableView.setContentOffset(CGPointMake(0, 1), animated:true)
Kavin Kumar Arumugam
quelle
1

In Swift-3:

self.tableView.setContentOffset(CGPoint.zero, animated: true)
Jeni Khant
quelle
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];
Matheus Veloza
quelle
0

Mit Swift:

self.scripSearchView.quickListTbl?.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
Dhananjay Patil
quelle