Trong triển khai của tôi, tôi đã phân lớp UIView cho chế độ xem mà tôi muốn xoay và một cái gì đó như viewController cho chế độ xem này, đây chỉ là lớp con của NSObject.
Trong giao diện nàyController Tôi thực hiện tất cả các kiểm tra liên quan đến thay đổi định hướng, quyết định xem có nên thay đổi hướng của chế độ xem mục tiêu hay không, và nếu có thì tôi gọi phương thức của tôi để thay đổi hướng của nó.
Trước hết, chúng tôi cần sửa định hướng của giao diện ứng dụng toàn bộ sang chế độ Chân dung, để ACCaptureVideoPreviewLayer của chúng tôi luôn ở trạng thái tĩnh. này được thực hiện trong MainViewController.h
:
(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation`
{
return interfaceOrientation==UIInterfaceOrientationPortrait;
}
Nó trả NO cho tất cả các hướng trừ Portrait.
Để tùy chỉnh của chúng tôi viewController có thể theo dõi những thay đổi của hướng thiết bị chúng ta cần phải làm cho nó một người quan sát thông báo tương ứng:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(orientationChanged) name:UIDeviceOrientationDidChangeNotification object:nil];
tôi đặt những dòng này trong phương pháp (void)awakeFromNib
của viewController tôi. Vì vậy, mỗi lần định hướng thiết bị được thay đổi, phương thức của viewController orientationChanged
sẽ được gọi.
Mục đích của nó là kiểm tra định hướng mới của thiết bị là gì, định hướng cuối cùng của thiết bị và quyết định xem có thay đổi thiết bị hay không. Đây là triển khai:
if(UIInterfaceOrientationPortraitUpsideDown==[UIDevice currentDevice].orientation ||
lastOrientation==(UIInterfaceOrientation)[UIDevice currentDevice].orientation)
return;
[[UIApplication sharedApplication]setStatusBarOrientation:[UIDevice currentDevice].orientation animated:NO];
lastOrientation=[UIApplication sharedApplication].statusBarOrientation;
[resultView orientationChanged];
Nếu định hướng giống như trước hoặc trong PortraitUpsideDown thì không làm gì cả. Khác nó đặt hướng thanh trạng thái thành một hướng thích hợp, để khi có cuộc gọi đến hoặc sự hiện diện hóa, nó sẽ xuất hiện ở phía bên phải của màn hình. Và sau đó tôi cũng gọi phương thức ở chế độ xem đích nơi tất cả các thay đổi tương ứng cho hướng mới được thực hiện, như xoay, thay đổi kích thước, di chuyển các phần tử giao diện khác trong chế độ xem này tương ứng với hướng mới.
Đây là việc thực hiện các orientationChanged
theo quan điểm mục tiêu:
Float32 angle=0.f;
UIInterfaceOrientation orientation=[UIApplication sharedApplication].statusBarOrientation;
switch (orientation) {
case UIInterfaceOrientationLandscapeLeft:
angle=-90.f*M_PI/180.f;
break;
case UIInterfaceOrientationLandscapeRight:
angle=90.f*M_PI/180.f;
break;
default: angle=0.f;
break;
}
if(angle==0 && CGAffineTransformIsIdentity(self.transform)) return;
CGAffineTransform transform=CGAffineTransformMakeRotation(angle);
[UIView beginAnimations:@"rotateView" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration:0.35f];
self.transform=transform;
[UIView commitAnimations];
Tất nhiên ở đây bạn có thể thêm bất kỳ thay đổi khác như dịch thuật, mở rộng quy mô các quan điểm khác nhau của giao diện của bạn cần phải đáp ứng với định hướng mới và animate chúng.
Ngoài ra, bạn có thể không cần viewController cho điều này, nhưng làm tất cả chỉ trong lớp của chế độ xem của bạn. Hy vọng rằng ý tưởng chung là rõ ràng.
Cũng đừng quên để ngừng nhận thông báo cho thay đổi hướng khi bạn không cần đến chúng thích:
[[NSNotificationCenter defaultCenter]removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
[[UIDevice currentDevice]endGeneratingDeviceOrientationNotifications];
Có vấn đề tương tự. Một giải pháp _obvious_ đáng buồn là không có sẵn: tôi đã hy vọng quan sát (với KVO) 'transform' của lớp 'presentationLayer' của khung nhìn mà không may mắn - key-value-observing không có sẵn trong thời gian chạy animation. Kết thúc bằng cách sử dụng (có thể) cùng một giải pháp như bạn: nhúng lớp xem trước vào một 'UIView' một cách thủ công xoay nó. –
Vâng, tôi cũng đã kết thúc bằng cách xoay thủ công chế độ xem có chứa previewLayer. Hóa ra là không phức tạp lắm. Tôi áp dụng CGAffineTransformMakeRotation() và sau đó thay đổi khung thành kích thước chính xác. Nhưng bây giờ tôi có chính xác hành vi tôi muốn. – BartoNaz
@BartoNaz Tôi đã đấu tranh với điều này trong một vài ngày nay và mọi thứ tôi cố gắng không cho tôi ảnh hưởng của camera.app nơi AVCaptureVideoPreviewLayer vẫn bị khóa vào chế độ xem và không xoay vòng hoạt ảnh. Bạn có thể vui lòng cung cấp đoạn mã làm việc của bạn như là một câu trả lời cho câu hỏi này? Cảm ơn. –