UITableView - прокрутіть до початку


393

У моєму поданні таблиці я маю прокрутити до вершини. Але я не можу гарантувати, що першим об'єктом буде розділ 0, рядок 0. Можливо, перегляд моєї таблиці розпочнеться з розділу 5.

Тож я отримую виняток, коли телефоную:

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

Чи є інший спосіб прокручування до перегляду вгорі таблиці?

Відповіді:


856

UITableView - це підклас UIScrollView, тому ви також можете використовувати:

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

Або

[mainTableView setContentOffset:CGPointZero animated:YES];

І в Свіфті:

mainTableView.setContentOffset(CGPointZero, animated:true)

І в Swift 3 і вище:

mainTableView.setContentOffset(.zero, animated: true)

9
Я вперше спробував це з CGRectZero, що еквівалентно CGRectMake (0, 0, 0, 0). Це не працює, але як не дивно вище. Я думаю, що йому потрібна позитивна ширина і висота. Дякую.
Келлер

5
Зауважте, вам потрібно буде анімувати: НІ, якщо ви запускаєте це в scrollToRowAtIndexPath: щоб перевести таблицю в правильне положення. Сподіваюся, це допомагає!
Fattie

3
@ hasan83 CGRectMake (0, 0, 0, 0) або CGRectZero не є видимою прямою. Я б також сказав, що [mainTableView setContentOffset: CGPointZero анімований: ТАК]; - гарніший вираз.
каталан

8
хтось помітив, що в iOS11 це все порушено і не прокручується правильно в деяких випадках?
Пітер Лапісу

11
@PeterLapisu, self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: UITableViewScrollPosition.top, animated: true)здається, працює в iOS 11
Jordan S

246

Примітка . Ця відповідь не відповідає дійсності для iOS 11 та новіших версій.

я віддаю перевагу

[mainTableView setContentOffset:CGPointZero animated:YES];

Якщо у виду таблиці ви маєте верхню вставку, її потрібно відняти:

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

12
Помідор, помідор. Хм ... Це не дуже чітко трапляється в письмовій формі.
FreeAsInBeer

14
Це найкращий спосіб використовувати, коли ви маєте перегляди заголовка або колонтитула таблиці та хочете, щоб вони також були включені.
mafonya

6
Це дійсно чіткий код, але він не працює, коли у вас tableViewнемає нуля contentInsetзверху. Наприклад: tableView.contentInset = UIEdgeInsetsMake(5.0f, 0.0f, 250.0f, 0.0f);. Якщо це так, у вашому коді tableViewпрокрутки до (0.0f, 5.0f).
tolgamorf

25
Рішення мого попереднього коментаря:[tableView setContentOffset:CGPointMake(0.0f, -tableView.contentInset.top) animated:YES];
tolgamorf

3
На iOS 11 слід подумати про використання -scrollView.adjustedContentInset.top.
Marián Černý

79

Можливі дії:

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

Вимкнути прокручування до початку:

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

Змініть та використовуйте його відповідно до вимог.

Швидкий 4

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

Те рішення, яке ідеально - scrollToFirstRow
Mehul

Відмінна резюме. Якщо у вас є заголовки розділів, вам доведеться використовувати option4 scrollToHeader.
Вінсент

Чи є спосіб прокрутити вгору до панелі пошуку над таблицею перегляду?
Тайлер Рутт

27

Краще не використовувати NSIndexPath (порожня таблиця) і не вважати, що верхньою точкою є CGPointZero (вставки вмісту), саме це я використовую -

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

Сподіваюсь, це допомагає.


За станом на iOS 11. більше не діє
rmaddy

21

Швидкий 4 :

Це дуже добре працює:

//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
Якщо ви не маєте таблицюHeaderView у таблиціView, а вона вбудована (прокрутки із вмістом)
finneycanhelp

1
У мене є як звичайний, так і a UITableViewStyleGrouped(заголовки прокручуються із вмістом), і цей код працює. Будьте впевнені, що ви знаходитесь у головному потоці, і ви запустите цей код після того, як з'явиться перегляд ( viewDidAppear). Якщо у вас все-таки виникають проблеми, спробуйте ввести код всередині цього:DispatchQueue.main.asyncAfter(deadline: .now()+0.1, execute: { // the code }
Алессандро Орнано

1
Дякую. Він доставить вас до першої комірки. Однак він не відображає заголовка подання таблиці.
finneycanhelp

Це не вдасться, якщо з якихось причин таблиця ViewView порожня (немає комірки в 0 розділі на 0 рядок)
Максим Скрябін

17

У мене виникла проблема, яка викликає спробування деяких методів на порожньому tableView. Ось ще один варіант для Swift 4, який обробляє порожні перегляди таблиці.

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

Використання:

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

Це не враховує жодного заголовка таблиці чи заголовка розділу.
rmaddy

16

НЕ ВИКОРИСТОВУЙТЕ

 tableView.setContentOffset(.zero, animated: true)

Іноді це може встановити компенсацію неправильно. Наприклад, у моєму випадку клітина насправді була трохи вище зору із захисними вставками. Не добре.

ВСТАНОВИТИ ВИКОРИСТАННЯ

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

1
Ідеальне рішення.
Baby Groot

Саме те, що я шукав, дякую.
Саймон

Жодне з цих рішень не є дійсним. Перший не працює в iOS 11 або пізнішої версії. Другий не працює, якщо у подання таблиці є заголовок таблиці, або в першому розділі є заголовок розділу, якщо ви дійсно не хочете, щоб перший рядок був у верхній частині і не піклується про те, щоб показувати заголовки.
rmaddy

@rmaddy, що найкраще рішення?
ScottyBlades

15

На iOS 11 використовуйте, adjustedContentInsetщоб правильно прокручувати доверху в обох випадках, коли видно смугу стану дзвінка чи ні.

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

Швидкий:

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

Для таблиць, у яких є contentInset, встановлення зміщення змісту CGPointZeroне працюватиме. Він буде прокручуватися до верхньої частини вмісту проти прокрутки до столу.

Враховуючи вставку вмісту, це призводить до цього:

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

1
Дякую, я продовжував встановлювати це на CGPointZero і не міг зрозуміти, чому це відбувається.
johnrechd

За станом на iOS 11. більше не діє
rmaddy

10

Цей код дозволить вам прокрутити певний розділ доверху

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

Це був найпростіший код, і він працював нормально. Я фактично поставив CGPointMake (0.0f, 0.0f). Ура!
Феліпе

Цей код дуже корисний для того, щоб зробити прокрутку розділу вгорі
srinivas n


8

Швидкий 3

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

якщо tableView.setContentOffsetне працює.

Використання:

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

1
Це неправда для iOS 11 або новішої версії.
rmaddy

7

Оскільки у мене tableViewповно всяких вводів, це було єдине, що добре працювало:

Швидкий 3

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

Швидкий 2

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

це було мені більш корисно
Tejzeratul

чудова відповідь, оцініть це
Джеремі Бадер

7

Додавши до вже сказаного, ви можете створити розширення (Swift) або категорію (Objective C), щоб зробити це простіше у майбутньому:

Швидкий:

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

У будь-який час, коли ви хочете прокрутити будь-яку дану таблицю View на верхню частину, ви можете зателефонувати за цим кодом:

tableView.scrollToTop(animated: true)

2
За станом на iOS 11. більше не діє
rmaddy

6

Я віддаю перевагу наступному, оскільки він враховує вкладку. Якщо вставки немає, вона все одно прокручуватиметься до верху, оскільки вставка буде 0.

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

За станом на iOS 11. більше не діє
rmaddy

5

Швидкий:

якщо у вас немає заголовка tableView:

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

якщо так :

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

5

Swift 5, iOS 13

Я знаю, що на це питання вже є багато відповідей, але, з мого досвіду, існує лише один метод, який завжди працює:

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

Якщо ви працюєте в системі async, таблицях, які анімують за допомогою клавіатур тощо, інші відповіді часто прокручуються до майже нижнього, а не абсолютного дна. Цей метод приведе вас до абсолютного кінця таблиці кожен раз.


Також потрібно перевірити, чи є розділ
Онур Тун

4

Ось що я використовую для правильної роботи на 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

У Swift 5 дуже багато відповіді @ Адріана

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

}

Використання:

tableView.scrollToTop()

2
1. Це також справедливо в Swift 4. 2. Це не працює, якщо є заголовок таблиці або заголовок розділу.
rmaddy

3

використання contentOffset - це не правильний шлях. це було б краще, оскільки це природний спосіб подання таблиці

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

2
Це не спрацює, якщо є заголовок таблиці або заголовок розділу.
rmaddy

3

Це був єдиний фрагмент коду, який працював на мене

Швидкий 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 - це висота осередку мого заголовка та таблиці


Це далеко не правильний спосіб прокручування до вершини. Немає сенсу використовувати три окремі рядки просто для встановлення зміщення вмісту. Потрібен лише останній рядок, але жорстке кодування конкретного зміщення не є правильним рішенням.
rmaddy

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

викликайте цю функцію там, де ви хочете, щоб UITableView прокрутіть доверху


2

Swift 4 через розширення, обробляє подання порожнього столу:

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

Це не
вірно

2

Я використовую tabBarController, і я маю кілька розділів у своєму перегляді таблиці на кожній вкладці, тому це найкраще рішення для мене.

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

Мені довелося додати помноження -1 *на суму рядка стану та панелі навігації, тому що вона йшла такої висоти поза екраном,

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

1

стрімко

ваш рядок = selectioncellRowNumber ваш розділ, якщо у вас = selectionNumber, якщо ви не встановили, це нуль

//UITableViewScrollPosition.Middle або знизу або вгорі

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



0

Якщо ви хочете перемістити анімацію прокрутки в таблиці, використовуйте цей код. Прокрутка рухається до верху з анімацією за 0,5 секунди.

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

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

[UIView commitAnimations];

0

З Swift:

self.scripSearchView.quickListTbl?.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.