UITableView - прокрутите вверх

393

В моем табличном представлении я должен прокрутить к вершине. Но я не могу гарантировать, что первым объектом будет секция 0, строка 0. Может быть, мое табличное представление начнется с секции № 5.

Поэтому я получаю исключение, когда звоню:

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

Есть ли другой способ прокрутки до верхней части таблицы?

Илья Суздальницкий
источник

Ответы:

857

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)
catlan
источник
9
Сначала я попробовал это с CGRectZero, который эквивалентен CGRectMake (0, 0, 0, 0). Это не работает, но, как ни странно, выше. Я предполагаю, что это нуждается в положительной ширине и высоте. Спасибо.
Келлер
5
Обратите внимание, вам понадобится анимация: НЕТ, если вы запустите это в scrollToRowAtIndexPath: чтобы таблица начиналась в правильном положении. Надеюсь, поможет!
Толстяк
3
@ hasan83 CGRectMake (0, 0, 0, 0) или CGRectZero не является видимым прямоугольником. Я также сказал бы, что [mainTableView setContentOffset: CGPointZero animated: YES]; это красивее выражение.
Catlan
8
кто-нибудь заметил, что в iOS11 это все сломано и не прокручивается правильно в некоторых случаях?
Питер Лапису
11
@PeterLapisu, self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: UITableViewScrollPosition.top, animated: true)кажется, работает в iOS 11
Джордан С
246

Примечание . Этот ответ не подходит для iOS 11 и более поздних версий.

я предпочитаю

[mainTableView setContentOffset:CGPointZero animated:YES];

Если у вас есть верхняя вставка в табличном представлении, вы должны вычесть это:

[mainTableView setContentOffset:CGPointMake(0.0f, -mainTableView.contentInset.top) animated:YES];
Fabb
источник
12
Помидор, помидор. Хм ... Это не очень ясно в письменной форме.
FreeAsInBeer
14
Это лучший способ использовать, когда у вас есть представления верхнего или нижнего колонтитула таблицы и вы хотите, чтобы они тоже были включены.
Мафоня
6
Это действительно чистый код, но он не работает, когда у вас tableViewненулевой contentInsetсверху. Например: tableView.contentInset = UIEdgeInsetsMake(5.0f, 0.0f, 250.0f, 0.0f);. Если это так, в вашем коде tableViewпрокручивается до (0.0f, 5.0f).
Толгаморф
25
Решение моего предыдущего комментария:[tableView setContentOffset:CGPointMake(0.0f, -tableView.contentInset.top) animated:YES];
tolgamorf
3
На iOS 11 вы должны рассмотреть возможность использования -scrollView.adjustedContentInset.topвместо.
Мариан Черны
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)
}

Отключить Scroll To Top:

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

Изменить и использовать его согласно требованию.

Swift 4

  func scrollToFirstRow() {
    let indexPath = IndexPath(row: 0, section: 0)
    self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
  }
AG
источник
Это идеальное решение - 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
Нет, если у вас есть tableHeaderView в вашем tableView и он встроен (прокручивается вместе с содержимым)
finneycanhelp
1
У меня есть и обычный и UITableViewStyleGrouped(заголовки прокручивается с содержимым), и этот код работает. Убедитесь, что вы находитесь в главном потоке, и вы запускаете этот код после появления представления ( viewDidAppear). Если у вас все еще есть проблемы, попробуйте поместить код внутри этого:DispatchQueue.main.asyncAfter(deadline: .now()+0.1, execute: { // the code }
Алессандро Орнано
1
Спасибо. Это приведет вас к первой камере. Однако он не показывает заголовок табличного представления.
finneycanhelp
Это не удастся, если tableView по какой-то причине пуст (нет ячейки в секции 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)
ScottyBlades
источник
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];
}

Swift:

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 и не мог понять, почему это происходит.
Джонрехд
Больше не действует с 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

Swift:

tableView.setContentOffset(CGPointZero, animated: true)
Esqarrouth
источник
Больше не действует с iOS 11.
rmaddy
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)
}

Swift 2

if tableView.numberOfSections > 0 && tableView.numberOfRowsInSection(0) > 0 {
  tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: .Top, animated: true)
}
budidino
источник
это было более полезным для меня
Тейзератул
отличный ответ, ценю это
Джереми Бадер
7

В дополнение к тому, что уже было сказано, вы можете создать расширение (Swift) или категорию (Objective C), чтобы упростить это в будущем:

Swift:

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

В любое время, когда вы хотите прокрутить любой данный tableView к вершине, вы можете вызвать следующий код:

tableView.scrollToTop(animated: true)
ocwang
источник
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)
jmcastel
источник
5

Swift 5, iOS 13

Я знаю, что на этот вопрос уже есть много ответов, но из моего опыта есть только один метод, который всегда работает:

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

Если вы работаете в асинхронном режиме, с таблицами, которые анимируются с помощью клавиатуры и т. Д., Другие ответы часто будут прокручиваться почти до самого низа, а не до абсолютного дна. Этот метод приведет вас к абсолютному концу таблицы каждый раз.

BSOD
источник
Вы также должны проверить, есть ли раздел
Onur Tuna
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()
dengST30
источник
2
1. Это также действует в Swift 4. 2. Это не работает, если есть заголовок таблицы или заголовок раздела.
rmaddy
3

использование contentOffset не является правильным способом. это было бы лучше, так как это естественный способ представления таблицы

tableView.scrollToRow(at: NSIndexPath.init(row: 0, section: 0) as IndexPath, at: .top, animated: true)
Gulz
источник
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 - высота моего заголовка и ячейки табличного представления

jimmyruby
источник
Это далеко от правильного способа прокрутки к вершине. Нет смысла использовать три отдельные строки только для установки смещения содержимого. Требуется только последняя строка, но жесткое кодирование определенного смещения не является правильным решением.
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);
    }
}
Шон
источник
Это не относится к iOS 11.
rmaddy
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)
Carlos.V
источник
1

быстро

ваш ряд = selectioncellRowNumber вашего раздела, если у вас есть = selectionNumber, если вы не установили, равен нулю

//UITableViewScrollPosition.Middle или Bottom или Top

var lastIndex = NSIndexPath(forRow:  selectioncellRowNumber, inSection: selectionNumber)
self.tableView.scrollToRowAtIndexPath(lastIndex, atScrollPosition: UITableViewScrollPosition.Middle, animated: true)
idris yıldız
источник
1

Вот код для ScrollTableView, чтобы вверх программно

Swift:

self.TableView.setContentOffset(CGPointMake(0, 1), animated:true)
Кавин Кумар Арумугам
источник
1

В Swift-3:

self.tableView.setContentOffset(CGPoint.zero, 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)
Дхананджай Патил
источник