Saya memiliki UITableView
yang diisi dengan sel dengan tinggi variabel. Saya ingin tabel di-scroll ke bawah saat view ditampilkan.
Saat ini saya memiliki fungsi berikut
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[log count]-1 inSection:0];
[self.table scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
log adalah larik yang bisa berubah berisi objek yang membentuk konten setiap sel.
Kode di atas berfungsi dengan baik viewDidAppear
namun ini memiliki efek samping yang tidak menguntungkan yaitu menampilkan bagian atas tabel saat tampilan pertama kali muncul dan kemudian melompat ke bawah. Saya lebih suka jika table view
bisa digulir ke bawah sebelum muncul.
Saya mencoba menggulir ke dalam viewWillAppear
dan viewDidLoad
tetapi dalam kedua kasus, data belum dimuat ke dalam tabel dan keduanya memberikan pengecualian.
Panduan apa pun akan sangat dihargai, bahkan jika itu hanya kasus memberi tahu saya apa yang saya miliki adalah semua yang mungkin.
sumber
[table reloadData];
CGPoint(x: 0, y: tableView.contentSize.height)
?Saya pikir cara termudah adalah ini:
if (self.messages.count > 0) { [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.messages.count-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES]; }
Versi Swift 3:
if messages.count > 0 { userDefinedOptionsTableView.scrollToRow(at: IndexPath(item:messages.count-1, section: 0), at: .bottom, animated: true) }
sumber
messages.count
dengan yang sudah diterapkanmyTableView.dataSource!.tableView(myTableView, numberOfRowsInSection: 0)
. Ya, ini lebih lama, tetapi mungkin menghindari pengulangan kode. Anda juga perlu menangani opsionaldataSource
(jangan buka paksa seperti dalam contoh ini).Dari jawaban Yakub inilah kodenya:
- (void) viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; if (self.messagesTableView.contentSize.height > self.messagesTableView.frame.size.height) { CGPoint offset = CGPointMake(0, self.messagesTableView.contentSize.height - self.messagesTableView.frame.size.height); [self.messagesTableView setContentOffset:offset animated:YES]; } }
sumber
UIEdgeInsetsInsetRect(self.messagesTableView.frame, self.messagesTableView.safeAreaInsets).height
Jika Anda perlu menggulir ke akhir konten yang PERSIS, Anda dapat melakukannya seperti ini:
- (void)scrollToBottom { CGFloat yOffset = 0; if (self.tableView.contentSize.height > self.tableView.bounds.size.height) { yOffset = self.tableView.contentSize.height - self.tableView.bounds.size.height; } [self.tableView setContentOffset:CGPointMake(0, yOffset) animated:NO]; }
sumber
yOffset = self.tableView.contentSize.height - self.tableView.bounds.size.height;
:? Terima kasih.self.tableView.contentSize.height
konten tampilan tabel mungkin tidak terlihat, karena Anda menggulir di bawah konten. Oleh karena itu, Anda harus menggulir ke satu "celah tampilan tabel yang terlihat" di atas akhir tampilan tabel.Saya menggunakan autolayout dan tidak ada jawaban yang berhasil untuk saya. Inilah solusi saya yang akhirnya berhasil:
@property (nonatomic, assign) BOOL shouldScrollToLastRow; - (void)viewDidLoad { [super viewDidLoad]; _shouldScrollToLastRow = YES; } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; // Scroll table view to the last row if (_shouldScrollToLastRow) { _shouldScrollToLastRow = NO; [self.tableView setContentOffset:CGPointMake(0, CGFLOAT_MAX)]; } }
sumber
setContentOffset
di beberapa titik lain ketika data telah diambil dan tableview dimuat ulang?CGFLOAT_MAX
saya digunakancontentSize.height - frame.height + contentInset.bottom
saat mengatur offset konten awal. MenggunakanCGFLOAT_MAX
sepertinya mengacaukan saya.The diterima solusi dengan @JacobRelkin tidak bekerja untuk saya di iOS 7.0 menggunakan Auto Layout.
Saya memiliki subkelas khusus
UIViewController
dan menambahkan variabel instance_tableView
sebagai subview-nyaview
. Saya memposisikan_tableView
menggunakan Tata Letak Otomatis. Saya mencoba memanggil metode ini di akhirviewDidLoad
dan bahkan diviewWillAppear:
. Tidak ada yang berhasil.Jadi, saya menambahkan metode berikut ke subkelas khusus saya
UIViewController
.- (void)tableViewScrollToBottomAnimated:(BOOL)animated { NSInteger numberOfRows = [_tableView numberOfRowsInSection:0]; if (numberOfRows) { [_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:numberOfRows-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:animated]; } }
Menelepon
[self tableViewScrollToBottomAnimated:NO]
di akhirviewDidLoad
karya. Sayangnya, itu juga menyebabkantableView:heightForRowAtIndexPath:
dipanggil tiga kali untuk setiap sel.sumber
Berikut ekstensi yang saya terapkan di Swift 2.0. Fungsi-fungsi ini harus dipanggil setelah
tableview
dimuat:import UIKit extension UITableView { func setOffsetToBottom(animated: Bool) { self.setContentOffset(CGPointMake(0, self.contentSize.height - self.frame.size.height), animated: true) } func scrollToLastRow(animated: Bool) { if self.numberOfRowsInSection(0) > 0 { self.scrollToRowAtIndexPath(NSIndexPath(forRow: self.numberOfRowsInSection(0) - 1, inSection: 0), atScrollPosition: .Bottom, animated: animated) } } }
sumber
Sebenarnya cara yang "Lebih Cepat" untuk melakukannya dengan cepat adalah:
var lastIndex = NSIndexPath(forRow: self.messages.count - 1, inSection: 0) self.messageTableView.scrollToRowAtIndexPath(lastIndex, atScrollPosition: UITableViewScrollPosition.Bottom, animated: true)
bekerja Sempurna untuk saya.
sumber
Detail
Kode
import UIKit extension UITableView { func scrollToBottom(animated: Bool) { let y = contentSize.height - frame.size.height if y < 0 { return } setContentOffset(CGPoint(x: 0, y: y), animated: animated) } }
Pemakaian
tableView.scrollToBottom(animated: true)
Sampel lengkap
import UIKit class ViewController: UIViewController { private weak var tableView: UITableView? private lazy var cellReuseIdentifier = "CellReuseIdentifier" override func viewDidLoad() { super.viewDidLoad() let tableView = UITableView(frame: view.frame) view.addSubview(tableView) tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier) self.tableView = tableView tableView.dataSource = self tableView.performBatchUpdates(nil) { [weak self] result in if result { self?.tableView?.scrollToBottom(animated: true) } } } } extension ViewController: UITableViewDataSource { func numberOfSections(in tableView: UITableView) -> Int { return 1 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 100 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath ) cell.textLabel?.text = "\(indexPath)" return cell } }
sumber
Saya ingin tabel memuat dengan ujung tabel yang ditunjukkan pada bingkai. Saya menemukan menggunakan
NSIndexPath *scrollIndexPath = [NSIndexPath indexPathForRow:([self.tableView numberOfRowsInSection:0] - 1) inSection:0]; [[self tableView] scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
tidak berfungsi karena memberikan kesalahan saat tinggi meja kurang dari tinggi bingkai. Perhatikan tabel saya hanya memiliki satu bagian.
Solusi yang berhasil untuk saya adalah menerapkan kode berikut di viewWillAppear:
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; // on the initial cell load scroll to the last row (ie the latest Note) if (initialLoad==TRUE) { initialLoad=FALSE; NSIndexPath *scrollIndexPath = [NSIndexPath indexPathForRow:([self.tableView numberOfRowsInSection:0] - 1) inSection:0]; [[self tableView] scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO]; CGPoint offset = CGPointMake(0, (1000000.0)); [self.tableView setContentOffset:offset animated:NO]; } }
BOOL ivar initialLoad disetel ke TRUE di viewDidLoad.
sumber
scrollToRowAtIndexPath
sama sekali? Anda sudah meneleponsetContentOffset
setelah itu, yang mungkin membuat panggilan pertama itu tidak berguna.Untuk Swift:
if tableView.contentSize.height > tableView.frame.size.height { let offset = CGPoint(x: 0, y: tableView.contentSize.height - tableView.frame.size.height) tableView.setContentOffset(offset, animated: false) }
sumber
Anda harus menggunakan
UITableViewScrollPositionBottom
sebagai gantinya.sumber
Untuk Swift 3 (Xcode 8.1):
override func viewDidAppear(_ animated: Bool) { let numberOfSections = self.tableView.numberOfSections let numberOfRows = self.tableView.numberOfRows(inSection: numberOfSections-1) let indexPath = IndexPath(row: numberOfRows-1 , section: numberOfSections-1) self.tableView.scrollToRow(at: indexPath, at: UITableViewScrollPosition.middle, animated: true) }
sumber
Tentu saja Bug. Mungkin di suatu tempat di kode Anda yang Anda gunakan
table.estimatedRowHeight = value
(misalnya 100). Gantikan nilai ini dengan nilai tertinggi yang menurut Anda bisa didapat oleh ketinggian baris , misalnya 500 .. Ini akan menyelesaikan masalah dengan kombinasi kode berikut://auto scroll down example let delay = 0.1 * Double(NSEC_PER_SEC) let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay)) dispatch_after(time, dispatch_get_main_queue(), { self.table.scrollToRowAtIndexPath(NSIndexPath(forRow: self.Messages.count - 1, inSection: 0), atScrollPosition: UITableViewScrollPosition.Bottom, animated: false) })
sumber
Setelah banyak mengutak-atik, inilah yang berhasil bagi saya:
var viewHasAppeared = false override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() if !viewHasAppeared { goToBottom() } } override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) viewHasAppeared = true } private func goToBottom() { guard data.count > 0 else { return } let indexPath = NSIndexPath(forRow: data.count - 1, inSection: 0) tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: false) tableView.layoutIfNeeded() }
Kuncinya ternyata tidak membungkus
scrollToRowAtIndexPath
di dalamdispatch_async
seperti yang disarankan beberapa orang, tetapi hanya mengikutinya dengan panggilan kelayoutIfNeeded
.Pemahaman saya tentang ini adalah, memanggil metode gulir di utas saat ini menjamin bahwa offset gulir disetel segera, sebelum tampilan ditampilkan. Ketika saya mengirim ke utas utama, tampilan ditampilkan sesaat sebelum gulungan diterapkan.
(Juga NB Anda memerlukan
viewHasAppeared
bendera karena Anda tidak ingingoToBottom
setiap kaliviewDidLayoutSubviews
dipanggil. Ia dipanggil misalnya setiap kali orientasi berubah.)sumber
Menggunakan solusi di atas, ini akan menggulir ke bagian bawah tabel Anda (hanya jika konten tabel dimuat terlebih dahulu):
//Scroll to bottom of table CGSize tableSize = myTableView.contentSize; [myTableView setContentOffset:CGPointMake(0, tableSize.height)];
sumber
Di Swift 3.0
self.tableViewFeeds.setContentOffset(CGPoint(x: 0, y: CGFLOAT_MAX), animated: true)
sumber
Jika Anda harus memuat data secara asinkron sebelum menggulir ke bawah, berikut ini solusinya:
tableView.alpha = 0 // We want animation! lastMessageShown = false // This is ivar viewModel.fetch { [unowned self] result in self.tableView.reloadData() if !self.lastMessageShown { dispatch_async(dispatch_get_main_queue()) { [unowned self] in if self.rowCount > 0 { self.tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: self.rowCount, inSection: 0), atScrollPosition: .Bottom, animated: false) } UIView.animateWithDuration(0.1) { self.tableView.alpha = 1 self.lastMessageShown = true // Do it once } } } }
sumber
Fungsi pada swift 3 scroll ke bawah
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(false) //scroll down if lists.count > 2 { let numberOfSections = self.tableView.numberOfSections let numberOfRows = self.tableView.numberOfRows(inSection: numberOfSections-1) let indexPath = IndexPath(row: numberOfRows-1 , section: numberOfSections-1) self.tableView.scrollToRow(at: indexPath, at: UITableViewScrollPosition.middle, animated: true) } }
sumber
func scrollToBottom() { let sections = self.chatTableView.numberOfSections if sections > 0 { let rows = self.chatTableView.numberOfRows(inSection: sections - 1) let last = IndexPath(row: rows - 1, section: sections - 1) DispatchQueue.main.async { self.chatTableView.scrollToRow(at: last, at: .bottom, animated: false) } } }
Anda harus menambahkan
DispatchQueue.main.async { self.chatTableView.scrollToRow(at: last, at: .bottom, animated: false) }
atau tidak akan bergulir ke bawah.
sumber
Gunakan kode sederhana ini untuk menggulir tableView ke bawah
NSInteger rows = [tableName numberOfRowsInSection:0]; if(rows > 0) { [tableName scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:rows-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES]; }
sumber
Terima kasih Jacob atas jawabannya. sangat membantu jika ada yang tertarik dengan monotouch c # version
private void SetScrollPositionDown() { if (tblShoppingListItem.ContentSize.Height > tblShoppingListItem.Frame.Size.Height) { PointF offset = new PointF(0, tblShoppingListItem.ContentSize.Height - tblShoppingListItem.Frame.Size.Height); tblShoppingListItem.SetContentOffset(offset,true ); } }
sumber
Di iOS, ini berfungsi dengan baik untuk saya
CGFloat height = self.inputTableView.contentSize.height; if (height > CGRectGetHeight(self.inputTableView.frame)) { height -= (CGRectGetHeight(self.inputTableView.frame) - CGRectGetHeight(self.navigationController.navigationBar.frame)); } else { height = 0; } [self.inputTableView setContentOffset:CGPointMake(0, height) animated:animated];
Itu perlu dipanggil dari
viewDidLayoutSubviews
sumber
[self.tableViewInfo scrollRectToVisible: CGRectMake (0, self.tableViewInfo.contentSize.height-self.tableViewInfo.height, self.tableViewInfo.width, self.tableViewInfo.height) animasi: YA];
sumber
Jawaban yang diterima tidak berfungsi dengan tabel saya (ribuan baris, pemuatan dinamis) tetapi kode di bawah berfungsi:
- (void)scrollToBottom:(id)sender { if ([self.sections count] > 0) { NSInteger idx = [self.sections count] - 1; CGRect sectionRect = [self.tableView rectForSection:idx]; sectionRect.size.height = self.tableView.frame.size.height; [self.tableView scrollRectToVisible:sectionRect animated:NO]; } }
sumber
Tidak perlu menggulir, Anda dapat melakukannya dengan menggunakan kode ini:
[YOURTABLEVIEWNAME setContentOffset:CGPointMake(0, CGFLOAT_MAX)];
sumber
Jika Anda menyiapkan bingkai untuk tampilan tabel secara terprogram, pastikan Anda menyetel bingkai dengan benar.
sumber
Di iOS 12, jawaban yang diterima tampaknya rusak. Saya sudah membuatnya bekerja dengan ekstensi berikut
import UIKit extension UITableView { public func scrollToBottom(animated: Bool = true) { guard let dataSource = dataSource else { return } let sections = dataSource.numberOfSections?(in: self) ?? 1 let rows = dataSource.tableView(self, numberOfRowsInSection: sections-1) let bottomIndex = IndexPath(item: rows - 1, section: sections - 1) scrollToRow(at: bottomIndex, at: .bottom, animated: animated) } }
sumber
Dalam 3.0 cepat Jika Anda ingin pergi ke Cell of tableview tertentu Ubah nilai indeks sel seperti mengubah nilai "self.yourArr.count".
self.yourTable.reloadData() self.scrollToBottom() func scrollToBottom(){ DispatchQueue.global(qos: .background).async { let indexPath = IndexPath(row: self.yourArr.count-1, section: 0) self.tblComment.scrollToRow(at: indexPath, at: .bottom, animated: true) } }
sumber
Saya yakin solusi lama tidak bekerja dengan swift3.
Jika Anda mengetahui baris nomor dalam tabel, Anda dapat menggunakan:
tableView.scrollToRow( at: IndexPath(item: listCountInSection-1, section: sectionCount - 1 ), at: .top, animated: true)
sumber