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?

Ilya Suzdalnitski
sumber

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)
Catlan
sumber
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];
Fabb
sumber
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)
  }
AG
sumber
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.

Kof
sumber
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)
Alessandro Ornano
sumber
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
Adrian
sumber
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)
ScottyBlades
sumber
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)
}
Thanh Pham
sumber
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];
Eran Goldin
sumber
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)];
Ramesh Muthe
sumber
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)
Esqarrouth
sumber
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()
Исмаил Хасбулатов
sumber
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)
}
budidino
sumber
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)
ocwang
sumber
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)
Jacobs
sumber
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)
jmcastel
sumber
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.

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

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

Sayali Shinde
sumber
2

Swift 4 melalui ekstensi, menangani tampilan tabel kosong:

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

    }

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

Inilah Kode Untuk ScrollTableLihat Ke Atas Secara Programatis

Cepat:

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

Dalam Swift-3:

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

Dengan Swift:

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