Подтвердить что ты не робот

UITableView - Как сохранить строки таблицы фиксированными как пользовательские прокрутки

Я хотел бы иметь возможность фиксировать положение определенных строк в UITableView по мере прокрутки пользователя.

В частности, у меня есть таблица, в которой некоторые строки являются "заголовками" для последующих строк, и я хотел бы, чтобы заголовок оставался в верхней части экрана по мере прокрутки пользователя. Затем он будет уходить с пути, когда пользователь прокручивается достаточно далеко, чтобы следующая строка заголовка заняла свое место.

Аналогичным примером может быть приложение Any.DO. Строки таблицы "Сегодня", "Томми" и "Позже" всегда видны на экране.

Есть ли у кого-нибудь предложения о том, как это можно реализовать?

Я сейчас думаю о том, чтобы следовать делегату TableDidScroll и позиционировать свою собственную ячейку в соответствующем месте перед представлением таблицы. Проблема в том, что в других случаях мне бы очень хотелось, чтобы эти ячейки были реальными ячейками таблицы, так что они могут быть, например, переупорядочены пользователем.

Спасибо,

Тим

4b9b3361

Ответ 1

Я играл с этим, и я придумал простое решение.

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

Далее мы перехватываем прокрутку вида таблицы

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    // Add some logic here to determine the section header. For example, use 
    // indexPathsForVisibleRows to get the visible index paths, from which you 
    // should be able to get the table view row that corresponds to the current 
    // section header. How this works will be implementation dependent.
    //
    // If the current section header has changed since the pervious scroll request 
    // (because a new one should now be at the top of the screen) then you should
    // update the contents.

    IndexPath *indexPathOfCurrentHeaderCell = ... // Depends on implementation
    UITableViewCell *headerCell = [self.tableView cellForRowAtIndexPath:indexPathOfCurrentHeaderCell];

    // If it exists then it on screen. Hide our false header

    if (headerCell)
        self.cellHeader.hidden = true;

    // If it doesn't exist (not on screen) or if it partially scrolled off the top,
    // position our false header at the top of the screen

    if (!headerCell || headerCell.frame.origin.y < self.tableView.contentOffset.y )
    {
        self.cellHeader.hidden = NO;
        self.cellHeader.frame = CGRectMake(0, self.tableView.contentOffset.y, self.cellHeader.frame.size.width, self.cellHeader.frame.size.height);
    }

    // Make sure it on top of all other cells

    [self.tableView bringSubviewToFront:self.cellHeader];
}

Наконец, нам нужно перехватить действия на этой ячейке и сделать правильные вещи...

Ответ 2

Это поведение по умолчанию для заголовков разделов в обычных экземплярах UITableView. Если вы хотите создать собственный заголовок, реализуйте метод tableView:viewForHeaderInSection: в делетете представления таблицы и верните представление для своего заголовка.

Хотя вам придется управлять разделами и строками, а не просто строками.

Ответ 3

Swift 5 решение

var header: UIView?

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(indexPath: indexPath) as UITableViewCell
    header = cell.contentView
    return cell
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let headerCell = tableView.cellForRow(at: IndexPath(row: 0, section: 0))
    guard headerCell == nil || (headerCell!.frame.origin.y < self.tableView.contentOffset.y + headerCell!.frame.height/2) else {
        header?.isHidden = true
        return
    }
    guard let hdr = header else { return }
    hdr.isHidden = false
    hdr.frame = CGRect(x: 0, y: tableView.contentOffset.y, width: hdr.frame.size.width, height: hdr.frame.size.height)
    if !tableView.subviews.contains(hdr) {
        tableView.addSubview(hdr)
    }
    tableView.bringSubviewToFront(hdr)
}