Звучит так, будто вы всегда прокручиваете табличное представление вверх, когда отображаете раскрывающееся представление. Предполагая, что это так, есть лучший способ сделать это.
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;
}
}