Изменение размера UITableView при прокрутке - PullRequest
0 голосов
/ 17 марта 2012

У меня есть ВК с табличным представлением. Когда происходит событие, я хочу добавить UIView сверху главного окна. Когда пользователь прокручивает табличное представление, я хочу изменить макет представления так, чтобы выпадающее представление «прокручивалось». Я подумал, что сделаю это, переместив рамку upperView и изменив размеры табличного представления (оба относительно смещения прокрутки). У меня это почти работает следующим образом:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {

    CGFloat contentOffsetY = scrollView.contentOffset.y;

    if (contentOffsetY > 0) {
        CGFloat upperHeight = self.upperView.frame.size.height;
        CGFloat fullTableHeight = self.view.frame.size.height;

        CGFloat offsetY = (contentOffsetY < upperHeight)? -scrollView.contentOffset.y : -upperHeight;

        self.upperView.frame = CGRectMake(0, offsetY, 320, upperHeight);
        scrollView.frame = CGRectMake(0, upperHeight+offsetY, 320, fullTableHeight-(upperHeight+offsetY));
    }
    NSLog(@"%f", self.upperView.frame.origin.y);
}

Начало координат верхнего вида начинается с 0,0.

Проблема в том, что после небольшого перемещения назад и вперед я теряю несколько верхних пикселей этого верхнего вида. Кажется, он не может вернуть свое происхождение к нулю. В журнале считываются отрицательные значения, и он достигает только -1, с самым тщательным перетаскиванием. Кто-нибудь сделал что-то подобное? Очень признателен, если вы можете помочь.

Ответы [ 2 ]

1 голос
/ 17 марта 2012

Звучит так, будто вы всегда прокручиваете табличное представление вверх, когда отображаете раскрывающееся представление. Предполагая, что это так, есть лучший способ сделать это.

UITableView наследует свойство contentInset от UIScrollView. Свойство contentInset определяет границу для каждого края вида прокрутки. Каждая граница имеет свою толщину, которая по умолчанию равна нулю. Эти границы просто влияют на то, насколько далеко представление прокрутки позволяет пользователю прокручивать контент - они не скрывают контент! Если вы установите верхнюю вставку больше нуля и дадите виду прокрутки подпредставление с отрицательным началом Y, то это подпредставление может быть видно на границе и будет прокручиваться с остальной частью содержимого представления прокрутки.

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

Нам понадобится переменная экземпляра, которая отслеживает текущее состояние раскрывающегося представления:

typedef enum {
    DropInViewStateHidden,
    DropInViewStateAppearing,
    DropInViewStateVisible
} DropInViewState;

@implementation ViewController {
    DropInViewState _dropInViewState;
}

В моем тестовом проекте я просто использовал кнопку для запуска раскрывающегося списка. Вот действие:

- (IBAction)dropIn {
    if (_dropInViewState != DropInViewStateHidden)
        return;

    CGRect frame = self.dropInView.frame;
    frame.origin.y = -frame.size.height;
    self.dropInView.frame = frame;
    [self.tableView addSubview:self.dropInView];

    self.tableView.contentInset = UIEdgeInsetsMake(frame.size.height, 0, 0, 0);
    [self.tableView setContentOffset:frame.origin animated:YES];

    _dropInViewState = DropInViewStateAppearing;
}

Когда прокручивается табличное представление, мы проверяем состояние раскрывающегося представления. Если он находится в «видимом» состоянии и был прокручен за пределами экрана, мы его скрываем. Есть немного хитрости, потому что, когда мы делаем видимым раскрывающийся вид и прокручиваем его на экран, мы можем получать scrollViewDidScroll: сообщений, которые заставляют нас думать, что раскрывающийся вид скрыт. Вот почему мы начинаем с состояния DropInViewStateAppearing и переходим в состояние DropInViewVisible, когда знаем, что представление появилось.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    switch (_dropInViewState) {
        case DropInViewStateHidden:
            break;
        case DropInViewStateVisible:
            if (scrollView.contentOffset.y >= 0) {
                // dropInView has been scrolled off-screen
                self.tableView.contentInset = UIEdgeInsetsZero;
                [self.dropInView removeFromSuperview];
                _dropInViewState = DropInViewStateHidden;
                break;
            }
        case DropInViewStateAppearing:
            // When I first add dropInView to tableView and tell tableView
            // to scroll to reveal dropInView, I may get a bunch of
            // scrollViewDidScroll: messages with contentOffset.y >= 0.
            // I don't want those messages to hide dropInView, so I sit in
            // DropInViewStateAppearing until contentOffset.y goes negative,
            // which means at least part of dropInView is actually on-screen.
            if (scrollView.contentOffset.y < 0)
                _dropInViewState = DropInViewStateVisible;
            break;
    }
}
0 голосов
/ 17 марта 2012

Понял это: UITableView не полностью сообщает didScroll во время отказов.Вот почему мне не хватало нескольких пикселей.Изменение размера во время скачка заставляет скачок смешиваться и останавливаться.Это исправление в моем коде выше позволяет работать отскоку (перемещая, не изменяя размер таблицы), и гарантирует, что верхний вид правильно размещается во время отказов (когда contentOffset.y <= 0). </p>

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {

    CGFloat contentOffsetY = scrollView.contentOffset.y;

    CGFloat upperHeight = self.upperView.frame.size.height;
    CGFloat fullTableHeight = self.view.frame.size.height;

    CGFloat offsetY = (contentOffsetY < upperHeight)? -scrollView.contentOffset.y : -upperHeight;

    if (contentOffsetY > 0) {
        self.upperView.frame = CGRectMake(0, offsetY, 320, upperHeight);
        scrollView.frame = CGRectMake(0, upperHeight+offsetY, 320, fullTableHeight-(upperHeight+offsetY));
    } else {
        self.upperView.frame = CGRectMake(0, 0, 320, upperHeight);
        scrollView.frame = CGRectMake(0.0, upperHeight, 320, scrollView.frame.size.height);
    }
    [super scrollViewDidScroll:scrollView];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...