2013-04-29 23 views
6

Bất cứ ai có thể cho tôi giải thích chi tiết về lý do tại sao iOS xử lý định hướng ngang của nó theo cách nó liên quan đến khung và chuyển đổi?iOS Landscape Orientation xử lý hậu trường

Những gì tôi đang nói về là hành vi này sau hiển thị bằng cách đăng nhập mô tả quan điểm trong các phương pháp Xem Vòng đời khác nhau:

viewDidLoad: "UIView: 0x1edb5ba0; frame = (0 0; 568 320); autoresize = W+H; layer = <CALayer: 0x1edb5c50>" 

viewWillAppear: "UIView: 0x1edb5ba0; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x1edb5c50>" 

viewDidAppear: "UIView: 0x1edb5ba0; frame = (0 0; 320 568); transform = [0, 1, -1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0x1edb5c50>" 

Các hậu quả của việc này là tinh tế, nhưng rất hấp dẫn.

Ví dụ, tôi khởi động ứng dụng của tôi với Định hướng giao diện ban đầu, và được hỗ trợ giao diện Định hướng cả hai thiết lập để "Landscape (nút home bên phải)"

tôi sau đó hiển thị rootViewController của tôi như thế này:

self.viewController = [[MyViewController alloc] initWithNibName:nil bundle:nil]; 
self.window.rootViewController = self.viewController; 

This .xib có định hướng là Landscape và frame được đặt là 0, 0, 568, 320. Nó hiển thị chính xác và tôi có thể chạm vào tất cả các điểm trên màn hình.

Vấn đề sau đó đến khi tôi trình bày một subview như vậy:

SomeView *someView = [[SomeView alloc] initWithFrame:self.view.frame]; 
[self.view addSubview:someView]; 

Tại thời điểm này trong thời gian, self.view.frame được báo cáo là (0 0; 320 568) và self.view.transform được báo cáo là biến = [0, 1, -1, 0, 0, 0]. Kịch bản trường hợp tốt nhất, kết quả cuối cùng là tôi chỉ có thể chạm vào 320px bên trái của chế độ xem mà tôi vừa mới hiển thị, trường hợp xấu nhất là bố cục của chế độ xem bị tàn sát.

Nhờ câu hỏi SO khác nhau, tôi đã học được rằng cách thích hợp để làm điều này là như sau:

SomeView *someView = [[SomeView alloc] initWithFrame:self.view.bounds]; 
[self.view addSubview:someView] 

Những gì tôi đã không biết là tại sao, và tôi rất tò mò về điều đó.

Điều mà tôi thậm chí còn tò mò hơn là lý do chế độ xem được điều chỉnh theo cách thức trong quá trình khởi tạo và hiển thị.

Đã khá lâu rồi vì tôi đã bị rối với ứng dụng chỉ dành cho cảnh quan, nhưng vì một lý do nào đó tôi nghĩ việc triển khai thực hiện điều này khác với các phiên bản iOS cũ hơn, có đúng không?

Trả lời

0

Theo táo, theo mặc định, một ứng dụng hỗ trợ cả hướng dọc và ngang. Khi định hướng của thiết bị dựa trên iOS thay đổi, hệ thống sẽ gửi một thông báo UIDeviceOrientationDidChangeNotification để cho bất kỳ bên quan tâm nào biết rằng thay đổi đã xảy ra. Theo mặc định, khung công tác UIKit lắng nghe thông báo này và sử dụng nó để tự động cập nhật định hướng giao diện của bạn. Điều này có nghĩa rằng, chỉ với một vài ngoại lệ, bạn không cần xử lý thông báo này chút nào.

Lý do tại sao bạn phải đưa ra giới hạn thay vì khung là đơn giản. Khi ứng dụng ở chế độ ngang, chiều rộng và chiều cao của nó sẽ thay đổi khi so sánh với chế độ xem dọc. Vì vậy, điều này dẫn đến hành vi bị hỏng. Nhưng khi đưa ra giới hạn, nó sẽ đưa vào xem xét định hướng của khung nhìn và có chiều cao và chiều rộng cho phù hợp.

Khi bạn có bộ điều khiển xem rất gần đầu phân cấp khung nhìn (hoặc thực sự ở trên cùng), bạn có thể thấy rằng bạn nhận được hiệu ứng 'hoán đổi' này của chiều rộng và chiều cao. Sự hoán đổi thường biểu hiện chính nó trên khung, nhưng không phải trên các giới hạn của khung nhìn.Điều này là do giới hạn có hiệu quả một số phép biến đổi được áp dụng cho khung - và đôi khi các phép biến đổi này bao gồm xoay 90 độ (do thiết bị đang ở chế độ ngang). Lưu ý rằng thời gian chính xác khi bạn kiểm tra thuộc tính khung cũng có thể là quan trọng. Nếu bạn đang kiểm tra thuộc tính sau khi lượt xem được tải nhưng trước khi nó xuất hiện trên màn hình, bạn có thể nhận được kết quả 'sai'.

0

Câu trả lời hay từ hoàng tử. Tôi chỉ muốn thêm một trích dẫn từ các docs về frame tài sản của UIView:

Cảnh báo: Nếu transform bất động sản không phải là bản sắc biến đổi, giá trị của tài sản này là undefined và do đó nên bỏ qua .

Thuộc tính bounds được thể hiện trong hệ tọa độ của chính chế độ xem, vì vậy nó không bao giờ thay đổi, cho dù bạn đặt transform.

Cập nhật: về đoạn cuối của bạn, điều gì khiến bạn cho rằng hành vi này lạ hoặc đã thay đổi? Cách duy nhất iOS có thể xoay phân cấp khung nhìn của bạn là bằng cách thay đổi các biến đổi khung nhìn. Vì vậy, nếu bạn muốn tất cả các khung nhìn của bạn trong các bộ điều khiển khung nhìn khác nhau được định hướng theo cùng một cách, bạn nên sử dụng một số loại trình điều khiển xem điều hướng hoặc trình bày các bộ điều khiển của bạn một cách bình thường. Bằng cách đó, mỗi bộ điều khiển sẽ xoay chế độ xem theo các quy tắc tương tự và bạn sẽ không phải quản lý các biến đổi liên quan theo cách thủ công.

Trong những ngày đầu, bạn có thể xem mã như thế này:

UIViewController *ctrl = ...; 
[window addSubview.ctrl.view]; 

Đây là trước khi windowrootViewController bất động sản, và người dân có xu hướng lạm dụng này cho quan điểm của riêng mình, mà có thể gây ra kết quả đáng ngạc nhiên khi thiết bị được xoay. Nếu bạn nói rằng bạn không nhìn thấy mã này nữa, đó chắc chắn là một sự thay đổi, và một sự thay đổi cho tốt hơn bởi vì mã đó đã bị hỏng. Vì vậy, mọi người chỉ học viết mã hoạt động chính xác khi có sự thay đổi định hướng.

Nếu bạn có trò chơi với tất cả giao diện người dùng được hiển thị bởi công cụ của trò chơi, bạn chỉ cần một bộ điều khiển chế độ xem gốc. Trong trường hợp này, bạn không cần phải lo lắng về biến đổi. Chỉ cần truy vấn cho các giới hạn của glView và điều chỉnh glViewport và các yếu tố trong trò chơi của bạn cho phù hợp. Vì glView sẽ có các giới hạn khác nhau của các thiết bị khác nhau, trò chơi của bạn sẽ mở rộng một cách duyên dáng trên tất cả chúng miễn là bạn không đưa ra bất kỳ giả định nào về kích thước màn hình thực tế và hướng hiện tại của chế độ xem của bạn.

Các vấn đề liên quan