iOS7 StatusBarHidden повреждает ScrollView, когда приложение возвращается на передний план
Мое приложение имеет раздел "Камера", который представляет собой модально представленный UINavigationController, содержащий CameraView на основе AVFoundation в качестве его rootViewController. Пользователь может просматривать свои библиотеки фотографий следующим образом: Выдвигается ViewController (->Master), который показывает все группы активов в TableView. Когда пользователь выбирает группу, другой ViewController выдвигается, показывая все активы в этой группе в CollectionView. Ради экранного пространства и "стиля" я решил скрыть строку состояния, когда отображается CameraSection (используя setStatusBarHidden:withAnimation:
) Это оставляет NavigationController с панелью навигации, уменьшенной на 20 пикселей (высота StatusBar).
Когда я показываю TableView / CollectionView для просмотра активов, я учитываю это и устанавливаю conentInset и т. Д. Для них соответственно.
Все это работает хорошо и хорошо, пока приложение не будет отправлено в фоновый режим (кнопка "Домой"), показывая либо TableView, либо CollectionView. (сейчас назовем его "ScrollView")
Когда приложение снова выходит на передний план, "ScrollView" находится в нужном состоянии в течение очень короткого момента, пока его кадр не сместится на 44 пикселя вниз. (44px = фактический размер простой навигационной панели - без строки состояния).
Вот несколько картинок, иллюстрирующих проблему:
Перед входом в фон (кнопка "Домой"):
После повторного выхода на передний план:
Когда вы присмотритесь, вы можете увидеть темную линию волос у нижнего края панели навигации. На первом рисунке все выровнено как раз правильно. Во втором, однако, scrollView, кажется, имеет смещение кадра вниз на 44px.
Когда contentSize collectionView больше, чем "Screen-Height" (начинает прокручиваться), вы также можете увидеть, что нижний край слишком низок (например, последняя строка не полностью видна + вставка scrollIndicator также неверна).
Я уже пытался зарегистрироваться на уведомления, как UIApplicationDidBecomeActiveNotification
или же UIApplicationDidChangeStatusBarFrameNotification
и переустановка contentInset и фрейма collectionView в обратном вызове.
Key-Value, наблюдающий фрейм collectionView, никогда не вызывал, так же как KVO "topLayoutGuide" viewController.
Похоже, что рамка тихо меняется без каких-либо уведомлений или событий. Как ни странно, когда я NSLog frame и contentInset collectionView до и после повторного ввода, они показывают одинаковые значения!
Я вообще не использую InterfaceBuilder, поэтому все делается в коде (без AutoLayout).
Я был бы очень признателен за любую помощь по этой проблеме.
На данный момент, боюсь, мне придется довольствоваться написанием пользовательского навигационного бара и скрытием навигационного контроллера, чтобы исправить это:/
- Еще одна проблема, которую я заметил: когда вы скрываете строку состояния, механизм scrollToTop scrollView больше не работает. Я полагаю, что нажатие должно быть в строке состояния, чтобы начать прокрутку, так что, чтобы заставить это работать, скрывая строку состояния, будет необходим TapGestureRecog?
РЕДАКТИРОВАТЬ
К вашему сведению, каждый ViewController, который я использую, наследует от базового класса, который устанавливает automagicallyAdjustScrollViewInset
в NO.
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];
}
Важно отменить регистрацию, когда обратный вызов был вызван один раз, потому что в противном случае смещения будут повреждены после дополнительного повторного ввода.
Конечно, не хорошее решение, но решение это:/