UITableView - gulir ke atas


393

Dalam tampilan tabel saya, saya harus gulir ke atas. Tapi saya tidak bisa menjamin bahwa objek pertama akan menjadi bagian 0, baris 0. Mungkin tampilan tabel saya akan mulai dari bagian nomor 5.

Jadi saya mendapat pengecualian, ketika saya menelepon:

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

Apakah ada cara lain untuk menggulir ke bagian atas tampilan tabel?

Jawaban:


857

UITableView adalah subkelas dari UIScrollView, jadi Anda juga dapat menggunakan:

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

Atau

[mainTableView setContentOffset:CGPointZero animated:YES];

Dan di Swift:

mainTableView.setContentOffset(CGPointZero, animated:true)

Dan di Swift 3 & di atas:

mainTableView.setContentOffset(.zero, animated: true)

9
Saya pertama kali mencoba ini dengan CGRectZero, yang setara dengan CGRectMake (0, 0, 0, 0). Ini tidak berfungsi, tetapi anehnya hal di atas tidak. Saya kira perlu lebar dan tinggi positif. Terima kasih.
Keller

5
Catatan, Anda akan ingin dianimasikan: TIDAK jika Anda menjalankan ini di scrollToRowAtIndexPath: untuk membuat tabel mulai di posisi yang benar. Semoga ini bisa membantu!
Fattie

3
@ hasan83 CGRectMake (0, 0, 0, 0) atau CGRectZero bukan kotak yang terlihat. Saya juga akan mengatakan bahwa [mainTableView setContentOffset: CGPointZero animated: YES]; adalah ekspresi yang lebih cantik.
catlan

8
Adakah yang memperhatikan bahwa di iOS11 ini semua rusak dan tidak bergulir dengan benar dalam beberapa kasus?
Peter Lapisu

11
@PeterLapisu self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: UITableViewScrollPosition.top, animated: true)tampaknya berfungsi di iOS 11
Jordan S

246

Catatan : Jawaban ini tidak valid untuk iOS 11 dan yang lebih baru.

saya lebih memilih

[mainTableView setContentOffset:CGPointZero animated:YES];

Jika Anda memiliki inset teratas pada tampilan tabel Anda, Anda harus mengurangi itu:

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

12
Tomat, tomat. Hmm ... Itu tidak terlihat sangat jelas secara tertulis.
FreeAsInBeer

14
Ini adalah cara terbaik untuk digunakan ketika Anda memiliki tampilan header tabel atau footer dan ingin mereka dimasukkan juga.
mafonya

6
Ini memang kode yang jelas, tetapi tidak berfungsi ketika Anda tableViewmemiliki nol contentInsetdari atas. Sebagai contoh: tableView.contentInset = UIEdgeInsetsMake(5.0f, 0.0f, 250.0f, 0.0f);. Jika demikian, dalam kode Anda tableViewgulir ke (0.0f, 5.0f).
tolgamorf

25
Solusi untuk komentar saya sebelumnya:[tableView setContentOffset:CGPointMake(0.0f, -tableView.contentInset.top) animated:YES];
tolgamorf

3
Di iOS 11 Anda harus mempertimbangkan untuk menggunakannya -scrollView.adjustedContentInset.top.
Marián Černý

79

Kemungkinan Tindakan:

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

Nonaktifkan Gulir ke Atas:

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

Ubah dan gunakan sesuai kebutuhan.

Cepat 4

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

Itulah solusinya, sempurna - scrollToFirstRow
Mehul

Ringkasan yang luar biasa. Ketika Anda memiliki bagian header Anda harus menggunakan option4 scrollToHeader.
Vincent

Apakah ada cara untuk menggulir ke bilah pencarian di atas Tableview?
Tyler Rutt

27

Lebih baik tidak menggunakan NSIndexPath (tabel kosong), atau menganggap bahwa titik teratas adalah CGPointZero (insets konten), itulah yang saya gunakan -

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

Semoga ini membantu.


Tidak lagi berlaku pada iOS 11.
rmaddy

21

Swift 4 :

Ini bekerja dengan sangat baik:

//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
Tidak jika Anda memiliki tableHeaderView di tableView dan inline (
gulir

1
Saya memiliki polos dan UITableViewStyleGrouped(header bergulir dengan konten) dan kode ini berfungsi. Pastikan Anda berada di utas utama dan Anda meluncurkan kode ini setelah tampilan muncul ( viewDidAppear). Jika Anda masih memiliki masalah, coba masukkan kodenya ke dalam ini:DispatchQueue.main.asyncAfter(deadline: .now()+0.1, execute: { // the code }
Alessandro Ornano

1
Terima kasih. Ini akan membawa Anda ke sel pertama. Namun, itu tidak menampilkan header tampilan tabel.
finneycanhelp

Ini akan gagal jika tableView kosong karena alasan tertentu (tidak ada sel di 0 bagian pada 0 baris)
Maxim Skryabin

17

Saya mengalami masalah dengan panggilan yang mencoba beberapa metode kosong tableView. Berikut opsi lain untuk Swift 4 yang menangani tampilan tabel kosong.

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

Pemakaian:

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

Ini tidak memperhitungkan tajuk tabel atau tajuk bagian mana pun.
rmaddy

16

JANGAN GUNAKAN

 tableView.setContentOffset(.zero, animated: true)

Kadang-kadang dapat mengatur offset dengan tidak benar. Misalnya, dalam kasus saya, sel sebenarnya sedikit di atas tampilan dengan insets area aman. Tidak baik.

PENGGUNAAN BUKAN

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

1
Solusi Sempurna.
Baby Groot

Persis apa yang saya cari, terima kasih.
Simon

Tidak satu pun dari solusi ini yang valid. Yang pertama tidak berfungsi di iOS 11 atau lebih baru. Yang kedua tidak berfungsi jika tampilan tabel memiliki tajuk tabel atau bagian pertama memiliki tajuk bagian, kecuali jika Anda benar-benar menginginkan baris pertama di bagian atas dan tidak peduli menampilkan tajuk.
rmaddy

@rmaddy apa solusi terbaik?
ScottyBlades

15

Di iOS 11, gunakan adjustedContentInsetuntuk menggulir ke atas untuk kedua kasus dengan benar ketika bilah status panggilan masuk terlihat atau tidak.

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

Cepat:

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

Untuk tabel yang memiliki contentInset, mengatur offset konten ke CGPointZerotidak akan berfungsi. Ini akan gulir ke bagian atas konten vs ke bagian atas tabel.

Sebagai gantinya, memasukkan inset konten menghasilkan ini:

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

1
Terima kasih, saya terus mengaturnya ke CGPointZero dan tidak bisa mengerti mengapa ini terjadi.
johnrechd

Tidak lagi berlaku pada iOS 11.
rmaddy

10

Kode ini memungkinkan Anda menggulir bagian tertentu ke atas

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

Ini adalah kode paling sederhana dan berhasil OK. Saya benar-benar memasukkan CGPointMake (0.0f, 0.0f). Bersulang!
Felipe

Kode ini sangat berguna untuk membuat bagian gulir bagian atas
srinivas dan

8

Cepat:

tableView.setContentOffset(CGPointZero, animated: true)

Tidak lagi berlaku pada iOS 11.
rmaddy

8

Cepat 3

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

jika tableView.setContentOffset tidak bekerja

Menggunakan:

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

1
Ini tidak berlaku untuk iOS 11 atau lebih baru.
rmaddy

7

Karena saya tableViewpenuh dengan semua jenis insets, ini adalah satu-satunya hal yang bekerja dengan baik:

Cepat 3

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

Cepat 2

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

ini lebih bermanfaat bagi saya
Tejzeratul

jawaban yang bagus, hargai itu
Jeremy Bader

7

Menambahkan ke apa yang sudah dikatakan, Anda dapat membuat ekstensi (Swift) atau kategori (Tujuan C) untuk membuat ini lebih mudah di masa depan:

Cepat:

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

Setiap kali Anda ingin menggulir tableView apa pun yang diberikan ke atas, Anda dapat memanggil kode berikut:

tableView.scrollToTop(animated: true)

2
Tidak lagi berlaku pada iOS 11.
rmaddy

6

Saya lebih suka yang berikut ini, karena memperhitungkan inset. Jika tidak ada inset, ia akan tetap menggulir ke atas karena inset akan 0.

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

Tidak lagi berlaku pada iOS 11.
rmaddy

5

Cepat:

jika Anda tidak memiliki header tableView:

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

jika begitu :

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

5

Swift 5, iOS 13

Saya tahu pertanyaan ini sudah memiliki banyak jawaban tetapi dari pengalaman saya, hanya ada satu metode yang selalu berhasil:

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

Jika Anda bekerja di async, tabel yang bernyawa dengan keyboard, dll, jawaban yang lain akan sering scroll ke hampir bawah, bukan bagian bawah mutlak. Metode ini akan membawa Anda ke akhir tabel setiap waktu.


Anda juga perlu memeriksa apakah ada bagian
Onur Tuna

4

Inilah yang saya gunakan untuk bekerja dengan benar di iOS 11:

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

Di Swift 5, Terima kasih @ Adrian menjawab banyak

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

}

Pemakaian:

tableView.scrollToTop()

2
1. Ini juga berlaku di Swift 4. 2. Ini tidak berfungsi jika ada tajuk tabel atau tajuk bagian.
rmaddy

3

menggunakan contentOffset bukanlah cara yang benar. ini akan lebih baik karena cara alami tampilan tabel

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

2
Ini tidak akan berfungsi jika ada tajuk tabel atau tajuk bagian.
rmaddy

3

Ini adalah satu-satunya cuplikan kode yang berfungsi untuk saya

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 adalah ketinggian sel tampilan tajuk dan tabel saya


Ini jauh dari cara yang benar untuk menggulir ke atas. Tidak masuk akal untuk menggunakan tiga baris terpisah hanya untuk mengatur offset konten. Hanya baris terakhir yang dibutuhkan tetapi pengodean offset tertentu bukan solusi yang tepat.
rmaddy

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

panggil fungsi ini di mana pun Anda ingin UITableView gulir ke atas


2

Swift 4 melalui ekstensi, menangani tampilan tabel kosong:

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

Ini tidak berlaku pada iOS 11.
rmaddy

2

Saya menggunakan tabBarController dan saya memiliki beberapa bagian di tableview saya di setiap tab, jadi ini adalah solusi terbaik untuk saya.

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

Saya harus menambahkan kalikan dengan -1 *jumlah bilah status dan bilah navigasi, karena itu akan setinggi itu dari layar,

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

1

dengan cepat

baris Anda = selectioncellRowNumber bagian Anda jika Anda memiliki = selectionNumber jika Anda tidak menetapkan adalah nol

//UITableViewScrollPosition.Middle atau Bawah atau Atas

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

1

Inilah Kode Untuk ScrollTableLihat Ke Atas Secara Programatis

Cepat:

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

1

Dalam Swift-3:

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

0

Jika Anda ingin memindahkan animasi gulir di tabel, gunakan kode ini. Gulir bergerak ke atas dengan animasi dalam 0,5 detik.

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

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

[UIView commitAnimations];

0

Dengan Swift:

self.scripSearchView.quickListTbl?.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.