iOS5, UIScrollView и поведение layoutSubviews

В моем приложении (код очень похож на демонстрацию Apple PhotoScroller из WWDC10) у меня есть UIScrollView. В режиме прокрутки я переопределил layoutSubviews кодом вроде:

- (void) layoutSubviews {
    [super layoutSubviews];
    // center the image as it becomes smaller than the size of the screen
    CGSize boundsSize = self.bounds.size;
    ...
 }

В iOS 4.x, если приложение запускается в альбомном режиме (пользователь держит его в альбомной ориентации), layoutSubviews вызывается дважды (очень быстро). При первом вызове boundsSize имеет размеры, которые указывают на его портретную ориентацию, но сразу после этого он вызывается снова, и self.bounds.size возвращает размеры, которые указывают на то, что устройство находится в режиме landacpe, и мои расчеты макета работают правильно.

В iOS 5.x, layoutSubviews вызывается только один раз, а bounds.size возвращает размеры, указывающие портрет, и не получает второй вызов, поэтому весь мой расчетный код испорчен.

Если пользователь физически поворачивает устройство, то вызывается layoutSubviews, и он работает правильно - поэтому пользователь запускает приложение в альбомной ориентации (рисует неправильно), поворачивает в портретную ориентацию (правильно рисует), а затем снова возвращается в альбомную (теперь рисует правильно). .

Мне не хватает второго «автоматического» вызова layoutSubviews.

Кто-нибудь еще заметил это или дал какой-нибудь совет?

Обновление:

Я нашел это в примечаниях к выпуску UIKit для iOS 5, но я не уверен, актуально ли оно или даже каково влияние этого изменения.

Обратные вызовы вращения в iOS 5 не применяются к контроллерам просмотра, которые отображаются в полноэкранном режиме. Это означает, что если ваш код представляет контроллер представления поверх другого контроллера представления, а затем пользователь впоследствии поворачивает устройство в другую ориентацию, при увольнении базовый контроллер (т.е. представляющий контроллер) не получит никаких обратных вызовов вращения. Однако обратите внимание, что представляющий контроллер получит вызов aviewWillLayoutSubviews при его повторном отображении, и свойство interfaceOrientation можно запросить из этого метода и использовать для правильной компоновки контроллера.

Дальнейшие обновления:

Используя [UIView recursiveDescription] , чтобы выгрузить иерархию представлений, я получил следующий вывод:

iOS 4 (которая работает правильно):

Портрет:

2011-12-19 15:57:06.400 stroom[10889:11603] <0x5e7f9b0 stroomViewController.m:(402)> <UIView: 0x6a6f2f0; frame = (0 0; 768 1024); autoresize = W+H; layer = <CALayer: 0x6a659d0>>
   | <UIScrollView: 0x5e911e0; frame = (-20 0; 808 1024); clipsToBounds = YES; autoresize = LM+W+RM+TM+H+BM; layer = <CALayer: 0x5e91370>; contentOffset: {0, 0}>
   |    | <stroomFullScreenPhotoScrollView: 0x5ea1010; baseClass = UIScrollView; frame = (20 0; 768 1024); clipsToBounds = YES; layer = <CALayer: 0x5ea0940>; contentOffset: {0, 0}>
   |    |    | <UIImageView: 0x5ea2600; frame = (0 224; 768 576); transform = [0.75, 0, 0, 0.75, 0, 0]; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5ea0890>>

Пейзаж:

2011-12-19 15:57:34.522 stroom[10889:11603] <0x5e7f9b0 stroomViewController.m:(402)> <UIView: 0x6d96c30; frame = (0 0; 768 1024); transform = [0, 1, -1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0x6d66440>>
   | <UIScrollView: 0x5e9eb70; frame = (-27 0; 1078 768); clipsToBounds = YES; autoresize = LM+W+RM+TM+H+BM; layer = <CALayer: 0x5eadde0>; contentOffset: {0, 0}>
   |    | <stroomFullScreenPhotoScrollView: 0x6dab850; baseClass = UIScrollView; frame = (20 0; 1038 768); clipsToBounds = YES; layer = <CALayer: 0x6dab2e0>; contentOffset: {0, 0}>
   |    |    | <UIImageView: 0x5e97f70; frame = (0 224; 1024 768); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x5e97fa0>>

iOS 5 (работает неправильно):

Портрет:

 2011-12-19 15:55:59.530 stroom[10850:16103] <0x848b520 stroomViewController.m:(402)> <UIView: 0xa884710; frame = (0 0; 768 1024); autoresize = W+H; layer = <CALayer: 0xa8849a0>>
   | <UIScrollView: 0xa883820; frame = (-20 0; 808 1024); clipsToBounds = YES; autoresize = LM+W+RM+TM+H+BM; layer = <CALayer: 0xa883a80>; contentOffset: {0, 0}>
   |    | <stroomFullScreenPhotoScrollView: 0x8699630; baseClass = UIScrollView; frame = (20 0; 768 1024); clipsToBounds = YES; layer = <CALayer: 0x8699360>; contentOffset: {0, 0}>
   |    |    | <UIImageView: 0x869a7c0; frame = (0 0; 768 576); transform = [0.75, 0, 0, 0.75, 0, 0]; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x869a800>>

Пейзаж:

 2011-12-19 15:56:32.521 stroom[10850:16103] <0x848b520 stroomViewController.m:(402)> <UIView: 0x8498530; frame = (0 0; 768 1024); transform = [0, 1, -1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0x8498560>>
   | <UIScrollView: 0x849ead0; frame = (-27 0; 1077 768); clipsToBounds = YES; autoresize = LM+W+RM+TM+H+BM; layer = <CALayer: 0x848f390>; contentOffset: {808, 0}>
   |    | <stroomFullScreenPhotoScrollView: 0x81e4b80; baseClass = UIScrollView; frame = (828 0; 768 1024); clipsToBounds = YES; layer = <CALayer: 0x81e7dc0>; contentOffset: {0, 0}>
   |    |    | <UIImageView: 0x81e5090; frame = (0 0; 768 576); transform = [0.75, 0, 0, 0.75, 0, 0]; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x81e5010>>

Из них я вижу, что contentOffset UIScrollView в iOS 5 выглядит некорректно и что пейзаж фрейм имеют неправильные размеры в iOS 5, тогда как в iOS 4 они кажутся правильными.

12
задан Damien 23 December 2011 в 15:11
поделиться