2011-12-22 25 views
15

Sử dụng Xcode 4.2.1 iPad iOS 5.0.1, tạo dự án iPad "Single View" mới. Trong bộ điều khiển, thêm:Sau khi xoay tọa độ UIView được đổi chỗ nhưng UIWindow không được?

- (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] ; 
} 

Chạy nó, hãy xoay điện thoại và bạn sẽ nhận được:

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} 

Nói cách khác, các UIView có tọa độ của nó "hoán đổi để cảnh quan" như mong đợi, nhưng nó mẹ UIWindow vẫn tuyên bố là trong chế độ chân dung ...

Ngoài ra, kích thước UIView có vẻ là hơi sai: tọa độ y mà nên ở mức 20 là 0 ...

Bất cứ ai biết wh điều này có nghĩa là gì?

Trả lời

37

Hệ tọa độ của UIWindow luôn ở hướng dọc. Nó áp dụng vòng xoay bằng cách thiết lập biến đổi của chế độ xem của rootViewController. Ví dụ: tôi đã tạo một ứng dụng thử nghiệm bằng cách sử dụng mẫu xem một lần và chạy nó. Theo hướng dọc:

(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>> 

Sau khi quay trái:

(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>> 

Sau khi xoay phải:

(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>> 

Thông báo như thế nào chuyển đổi được thiết lập (để một ma trận xoay 90 độ) khi thiết bị được xoay.

Về câu hỏi của bạn về kích thước UIView: giới hạn của chế độ xem nằm trong không gian toạ độ của chính nó và theo mặc định, nguồn gốc của lượt xem có tại điểm gốc (0,0). Khung của khung nhìn nằm trong không gian tọa độ của bố mẹ. Bạn có thể thấy 20 bạn đang mong đợi trong các mô tả đệ quy ở trên hoặc bằng cách in khung trực tiếp:

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

Làm cho tinh thần. Cảm ơn bạn. Ngẫu nhiên, cảm ơn bạn vì đã chỉ cho tôi rằng gdb có thể thực sự được sử dụng tương tác :-) – verec

+0

@rob Ngoại trừ các tài liệu ref cho UIView.frame nói: Cảnh báo Nếu thuộc tính biến đổi không phải là biến đổi nhận dạng, giá trị của thuộc tính này là không xác định và do đó nên bỏ qua. Bạn có thể giải thích về điều đó không? Giả sử tôi muốn tạo hiệu ứng cho khung của chế độ xem được xoay để trượt nó thành lớp phủ. – tribalvibes

+1

Tôi không dựa vào 'khung' trong mã của mình khi' biến đổi' không phải là danh tính. Tuy nhiên, phương thức 'frame' xuất hiện để luôn trả về' [self convertRect: self.bounds toView: self.superview] 'và vì vậy nó rất hữu ích khi gỡ lỗi. –