iOS7 StatusBarHidden портит ScrollView, когда приложение снова выходит на передний план

В моем приложении есть раздел «Камера», который представляет собой модально представленный UINavigationController, содержащий CameraView на основе AVFoundation в качестве rootViewController. Пользователь может просматривать свои библиотеки фотографий следующим образом: Выдвигается ViewController (-> Master), который показывает все AssetGroups в TableView. Когда пользователь выбирает группу, выдвигается другой ViewController, показывающий все активы в этой группе в CollectionView. Ради экранного пространства и «стиля» я решил скрыть строку состояния, когда отображается CameraSection (используя setStatusBarHidden:withAnimation:). Это оставляет NavigationController с панелью навигации, сдвинутой вверх на 20 пикселей (высота строки состояния).

Когда я показываю TableView / CollectionView для просмотра активов, я принимаю это во внимание и соответствующим образом устанавливаю для них conentInset и т. д.

Все это работает хорошо и хорошо, пока приложение не будет отправлено в фоновый режим (кнопка «Домой») при отображении либо TableView, либо CollectionView. (теперь он будет называться "ScrollView")

Когда приложение снова выходит на передний план, «ScrollView» находится в правильном состоянии в течение очень короткого момента, прежде чем его кадр смещается на 44 пикселя вниз. (44px = фактический размер простой панели навигации - без панели состояния).

Вот несколько картинок, иллюстрирующих проблему:

Перед входом в фон (кнопка «Домой»): Перед входом в фон

После повторного выхода на передний план: введите здесь описание изображения

Если вы внимательно посмотрите, вы увидите темную линию у нижнего края панели навигации. На первой фотке все правильно выровнено. Однако во втором случае scrollView, похоже, имеет смещение кадра вниз на 44 пикселя.

Когда contentSize collectionView больше, чем «Screen-Height» (начинает прокручиваться), вы также можете увидеть, что нижний край слишком низкий (например, последняя строка не полностью видна + вставка scrollIndicator также неверна).

Я уже пытался зарегистрироваться для уведомлений, таких как UIApplicationDidBecomeActiveNotification или UIApplicationDidChangeStatusBarFrameNotification, и переустановить contentInset и фрейм collectionView в обратном вызове. Ключ-значение, наблюдающий за фреймом collectionView, никогда не выполнял обратный вызов, как KVO "topLayoutGuide" viewController.

Кажется, что кадр незаметно меняется без каких-либо уведомлений или событий. Странно, когда я NSLog фрейм collectionView и contentInset до и после повторного входа, они показывают точно такие же значения!?

Я вообще не использую InterfaceBuilder, поэтому все делается в коде (без AutoLayout).

Буду очень признателен за любую помощь в решении этой проблемы.

На данный момент, боюсь, мне придется довольствоваться написанием собственного навигационного бара и сокрытием навигационного контроллера, чтобы исправить это:/

  • Еще одна проблема, которую я заметил: когда вы скрываете строку состояния, механизм scrollToTop в scrollView больше не работает. Я предполагаю, что нажатие должно быть в строке состояния, чтобы начать прокрутку, поэтому, чтобы заставить это работать, скрывая строку состояния, потребуется TapGestureRecog?

ИЗМЕНИТЬ

К вашему сведению, каждый ViewController, который я использую, наследуется от базового класса, который устанавливает automagicallyAdjustScrollViewInset в NO.


person CodingMeSwiftly    schedule 02.04.2014    source источник


Ответы (1)


ИЗМЕНИТЬ

Собственно, решение ниже тоже неверно.

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

После сохранения постоянного значения этого свойства все работает нормально.

СТАРЫЙ ОТВЕТ - НЕ РАБОТАЕТ!!

Хорошо, это ОЧЕНЬ ОЧЕНЬ некрасиво, но я смог решить эту проблему, сделав это:

В viewWillAppear:animated: зарегистрируйтесь, чтобы получать уведомления, когда приложение снова выходит на передний план.

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(applicationDidBecomeActive:)
                                             name:UIApplicationDidBecomeActiveNotification
                                           object:nil];

Обратный вызов выглядит следующим образом:

- (void)applicationDidBecomeActive:(NSNotification *)notification
{
    UIEdgeInsets scrollIndicatorInset = self.collectionView.scrollIndicatorInsets;
    UIEdgeInsets contentInset = self.collectionView.contentInset;

    scrollIndicatorInset.top -= 44.0;
    scrollIndicatorInset.bottom += 44.0;

    contentInset.top -= 44.0;
    contentInset.bottom += 44.0;

    [self.collectionView setScrollIndicatorInsets:scrollIndicatorInset];
    [self.collectionView setContentInset:contentInset];

    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
}

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

Конечно, это не очень хорошее решение, но оно есть :/

person CodingMeSwiftly    schedule 02.04.2014