2013-03-07 29 views
5

Tôi có GLKit ứng dụng dựa trên một số đối tượng đơn giản được hiển thị.GLKit's -drawRect: không được gọi trong khi xoay màn hình

Tất cả hoạt động tốt, ngoại trừ xoay màn hình, trong đó GLKView không được cập nhật (-drawRect: không được gọi). Vì vậy, trong ma trận chiếu xoay không được cập nhật theo kích thước màn hình thay đổi động và đối tượng trông xấu (kéo dài).

+0

Bạn có đang sử dụng trình đổ bóng hoặc GLKBaseEffect không? –

+0

Đã thử cả hai: 'GLKBaseEffect' và các trình đổ bóng của riêng tôi - cùng một kết quả. '-drawRect:' sẽ được gọi sau khi hoạt ảnh kết thúc - vì vậy mọi hình ảnh GL (mà chúng ta thường đặt ở đó) sẽ bị treo vào thời điểm đó. – kpower

+1

Ok. Tôi đã nghĩ rằng có thể thuộc tính projectionMatrix trên GLKBaseEffect là lỗi. Tôi sẽ suy nghĩ ... –

Trả lời

1

Đó đơn giản là cách hoạt ảnh của UIKit hoạt động. Tôi sắp xếp giải thích cách một nửa của nó hoạt động trong this answer, nhưng tôi sẽ cố gắng tóm tắt các bit liên quan:

  • Mọi thứ đều là hình chữ nhật kết cấu. (Có một số ngoại lệ, như có lẽ là CAShapeLayer, nhưng điều này là đúng cho hầu hết các phần.)
  • UIView thuộc tính của được liên kết với thuộc tính "cây mô hình" của CALayer. Họ thay đổi ngay lập tức.
  • Hoạt ảnh hoạt động bằng cách làm động các thuộc tính "cây bản trình bày" từ giá trị bắt đầu cho giá trị mô hình hiện tại.
  • Giá trị bắt đầu của hoạt ảnh theo mặc định là giá trị mô hình trước đó. Chỉ định UIViewAnimationOptionBeginFromCurrentState làm cho nó sử dụng giá trị bản trình bày hiện tại.

Có, tất nhiên, một vài trường hợp ngoại lệ (CAShapeLayer có vẻ là hơn một rect kết cấu, UIScrollView không di chuyển hình ảnh động trên một giờ, UIView chuyển tiếp là điều hoàn toàn khác ...).

Cách xoay là nghĩa là để hoạt động là bạn nhận được một -setFrame:, mọi thứ được đặt ra (và có khả năng hiển thị lại), và sau đó thuộc tính có thể hoạt ảnh được làm động. Theo mặc định, điều này có nghĩa là mọi thứ sẽ trở lại kích thước mới nhưng được kéo dài để vừa với kích thước cũ và sau đó tạo hiệu ứng động (và unstretch) khi tiến trình xoay.

Điều đó nói rằng, GLKView có thể hoạt động khác nhau.Nếu bạn đang sử dụng GLKViewController, nó thậm chí có thể tạm dừng hiển thị trong khi hoạt ảnh xoay. Bạn có thể thử gọi -setNeedsDisplay trong khi quay, nhưng nó sẽ không giúp ích nhiều vì khung đã được đặt thành giá trị cuối cùng của nó.

Có lẽ cách dễ nhất để xử lý hoạt ảnh xoay chính là buộc chuyển tiếp không hoạt ảnh sang khung xoay và sau đó thực hiện một số thao tác trong trình kết xuất (đường viền màu đen và thanh trạng thái hoạt ảnh riêng). Ngoài ra, cách truyền thống là làm cho VC của bạn chân dung và tự mình xử lý các thông báo định hướng thiết bị, nhưng đây là một loại giun lớn (bạn phải lo lắng về định hướng thanh trạng thái xác định những thứ như chạm vào). bù đắp và định hướng bàn phím, và nó có xu hướng tương tác "thú vị" khi chuyển sang/từ các VC khác).

0

Trước hết, hãy đảm bảo rằng vào một thời điểm nào đó sớm trong vòng đời ứng dụng của bạn, hãy bật thay đổi hướng thiết bị.

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 

Sau đó, khi chế độ xem của bạn được khởi tạo để đăng ký thông báo như vậy.

[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(deviceOrientationDidChange:) name: UIDeviceOrientationDidChangeNotification object: nil]; 

Sau đó thực hiện -deviceOrientationDidChange: trong điều khiển điểm của bạn và gọi -setNeedsDisplay

+0

'-... DidChange' sẽ được gọi sau khi thay đổi định hướng xảy ra. Và lần này, 'drawRect:' cũng sẽ được gọi (vì tôi cập nhật ma trận theo thời gian và trên mỗi thay đổi khung hình). Nhưng tôi cần áp dụng các thay đổi trong quá trình này. – kpower

+0

Tôi thấy bây giờ. Tôi mặc dù bạn đã nói rằng bạn đã không nhận được bất kỳ thông tin luân phiên nào cả. Lắng nghe và thực hiện phương thức điều khiển khung nhìn '- (void) willAnimateRotationToInterfaceOrientation: (UIInterfaceOrientation) interfaceGiới hạn thời gian: (NSTimeInterval) duration'. Thời lượng sẽ cho phép bạn tính toán hoạt ảnh của mình trong quá trình chuyển đổi. –

+1

Vâng, tôi biết. Và tôi cũng có thể tái hiện lại '-setFrame:' ​​- và sẽ nhận được thay đổi kích thước xem mỗi bước hoạt ảnh. Nhưng tôi không thể trả lời những thay đổi này - ý tôi là, tôi có thể cập nhật ma trận chiếu, nhưng các cập nhật sẽ không được áp dụng, vì '-drawRect:' (và bản vẽ GL tương ứng) sẽ không được gọi cho đến khi hoạt ảnh kết thúc. – kpower

6

Đây có thể là một shot trong bóng tối kể từ khi tôi không có bất kỳ kinh nghiệm với GLKit, tuy nhiên tôi có kinh nghiệm với UIView-drawRect:. Hãy thử thay đổi contentMode về quan điểm trong câu hỏi để vẽ lại:

view.contentMode = UIViewContentModeRedraw;

này sẽ cho quan điểm cho rằng nó cần phải vẽ lại nội dung của nó khi nó ranh giới thay đổi. Nếu không, UIView sẽ chỉ đơn giản là cố gắng mở rộng nội dung của nó (mặc định cho contentMode là UIViewContentModeScaleToFill). Lý do cho điều này là dễ dàng hơn nhiều để quy mô những gì có hơn để vẽ lại nội dung và UIView được thiết kế để có hiệu quả nhất có thể.

+0

Thật không may, điều này dường như không thực hiện bất kỳ sự khác biệt trong thực tế trên một GLKView. – pmdj