2012-03-17 3 views
0

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

- (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, причем наиболее тщательное перетаскивание. Кто-нибудь сделал что-то подобное? Очень важно, если вы можете помочь.

ответ

1

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

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

У меня есть панель поиска и тянуть к-обновлению вещи также претендующую на эту верхнюю области вставки, так что я все еще на чертежной доске, но спасибо за хороший, тщательный ответ. – danh

0

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

- (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]; 
} 
Смежные вопросы