После поворота координаты UIView меняются местами, а UIWindow - нет? - PullRequest
15 голосов
/ 22 декабря 2011

Используя Xcode 4.2.1 iPad iOS 5.0.1, создайте новый проект iPad «Single View». В контроллере добавьте:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}

- (void) dumpView: (UIView *) view {
    CGRect frame = view.frame ;
    CGRect bounds = view.bounds ;
    CGPoint center = view.center ;

    NSLog(@"view [%@]:%d frame=%@ bounds=%@ center=%@"
          ,   NSStringFromClass(view.class)
          ,   [view hash]
          ,   NSStringFromCGRect(frame)
          ,   NSStringFromCGRect(bounds)
          ,   NSStringFromCGPoint(center)) ;
}

- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation) fromInterfaceOrientation {

    NSLog(@"INViewController.didRotateFromInterfaceOrientation: %d to %d", fromInterfaceOrientation, self.interfaceOrientation) ;
    [self dumpView: self.view] ;
    [self dumpView: self.view.superview] ;
}

Запустите его, поверните устройство, и вы получите:

INViewController.didRotateFromInterfaceOrientation: 2 to 4
view [UIView]   bounds={{0, 0}, {1024, 748}} center={394, 512}
view [UIWindow] bounds={{0, 0}, {768, 1024}} center={384, 512}

Другими словами, UIView имеет свои координаты, «как положено», как и ожидалось, но его родительское окно UIWindow все еще утверждает, что находится в портретном режиме ...

Кроме того, размер UIView кажется немного неправильным: координата y, которая должна быть в 20, находится в 0 ...

Кто-нибудь знает, что это значит?

1 Ответ

37 голосов
/ 22 декабря 2011

Система координат UIWindow всегда находится в портретной ориентации.Он применяет вращение, устанавливая преобразование представления своего rootViewController.Например, я создал тестовое приложение, используя шаблон с одним представлением, и запустил его.В портретной ориентации:

(gdb) po [[(id)UIApp keyWindow] recursiveDescription]
<UIWindow: 0x9626a90; frame = (0 0; 768 1024); layer = <UIWindowLayer: 0x9626b80>>
   | <UIView: 0x96290e0; frame = (0 20; 768 1004); autoresize = W+H; layer = <CALayer: 0x96286a0>>

После поворота влево:

(gdb) po [[(id)UIApp keyWindow] recursiveDescription]
<UIWindow: 0x9626a90; frame = (0 0; 768 1024); layer = <UIWindowLayer: 0x9626b80>>
   | <UIView: 0x96290e0; frame = (0 0; 748 1024); transform = [0, 1, -1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0x96286a0>>

После поворота вправо:

(gdb) po [[(id)UIApp keyWindow] recursiveDescription]
<UIWindow: 0x9626a90; frame = (0 0; 768 1024); layer = <UIWindowLayer: 0x9626b80>>
   | <UIView: 0x96290e0; frame = (20 0; 748 1024); transform = [0, -1, 1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0x96286a0>>

Обратите внимание, как установлено преобразование (в 90-матрица поворота градусов), когда устройство поворачивается.

Относительно вашего вопроса о размере UIView: границы представления находятся в своем собственном координатном пространстве, и по умолчанию источник границ представления находится в начале координат (0,0) его координатного пространства.Кадр представления находится в координатном пространстве его родителя.Вы можете увидеть 20 ожидаемых значений в рекурсивных описаниях выше или распечатав рамку напрямую:

(gdb) p (CGRect)[[[[(id)UIApp keyWindow] subviews] lastObject] frame]
$2 = {
  origin = {
    x = 0, 
    y = 20
  }, 
  size = {
    width = 768, 
    height = 1004
  }
}
...