私は、iOS6 で完璧に動作する UIPopoverController 内で UIImagePickerController を使用しています。iOS 7 では、画像をキャプチャするために表示される「プレビュー」画像は回転しますが、写真を撮ると正しく保存されます。
ピッカーを取得する方法は次のとおりです。
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.mediaTypes = [NSArray arrayWithObjects:
(NSString *) kUTTypeImage,
nil];
imagePicker.allowsEditing = NO;
これをポップオーバー コントローラーに追加します。
self.imagePickerPopOver = [[UIPopoverController alloc] initWithContentViewController:imagePicker];
[self.imagePickerPopOver presentPopoverFromRect:CGRectMake(aPosViewA.x, cameraButton_y, 100.0, 30.0) inView:self.detailViewController.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
これらは、ポップオーバーを正しい位置に表示するための UIScrollView のボタン位置の計算です。
presentPopoverFromRect:CGRectMake(aPosViewA.x, cameraButton_y, 100.0, 30.0)
いくつかの組み合わせを試してみたところ、そこに問題があるとは思えません。
フルスクリーン モードで画像をキャプチャしようとしましたが、アプリはランドスケープ モードのみを使用できます。画像がポートレート モードで撮影され、モーダル ビューが閉じられると、アプリもポートレート モードのままになります。モーダル ビューが閉じられた場合に UIImagePickerController がポートレート モードに切り替わるのを防ぐ方法や、アプリを強制的にランドスケープ モードに戻す方法は見つかりませんでした。
アップデート
私は答えをここそしてさらに一歩前進しました。
ピッカーを作成した後、ポップオーバーを表示する前にビューを変換します。
switch ([UIApplication sharedApplication].statusBarOrientation) {
case UIInterfaceOrientationLandscapeLeft:
self.imagePicker.view.transform = CGAffineTransformMakeRotation(M_PI/2);
break;
case UIInterfaceOrientationLandscapeRight:
self.imagePicker.view.transform = CGAffineTransformMakeRotation(-M_PI/2);
break;
default:
break;
}
これは、iPad を回転させない限り機能します。そのために、向き変更イベントを登録しています。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
ピッカービューを変更します。
- (void)orientationChanged:(NSNotification *)notification{
if (self.imagePicker) {
switch ([UIApplication sharedApplication].statusBarOrientation) {
case UIInterfaceOrientationLandscapeLeft:
self.imagePicker.view.transform = CGAffineTransformMakeRotation(M_PI/2);
break;
case UIInterfaceOrientationLandscapeRight:
self.imagePicker.view.transform = CGAffineTransformMakeRotation(-M_PI/2);
break;
default:
break;
}
}
}
残る問題: 冒頭で書いたように、写真が撮影されたときに、それを受け入れるか拒否するかが正しく表示されました。これも変換されてしまいました。何らかの方法で、画像が撮影されたタイミングを把握し、元に戻す必要があります。
また、これは本当に厄介なハックであり、おそらく次の iOS アップデートでは機能しないでしょう。これをよりクリーンな方法で実装する方法を知っている人はいますか?
アップデート2
これはあまりにも厄介でした。私の問題を解決するよりクリーンな解決策を見つけましたが、これは、Apple では推奨されていませんが許可されているポップオーバー コントローラー内のイメージ ピッカーに関する最初の質問に対する答えではありません。
UIImagePickerController を次のようにサブクラス化しました。
@implementation QPImagePickerController
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
}
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscape;
}
@end
ポップオーバーではなく、フルスクリーンでイメージピッカーを使用しています。これまで iOS7 でテスト済みです。
ベストアンサー1
UIImagePickerController には、cameraViewTransform というプロパティがあります。これに CGAffineTransform を適用すると、プレビュー画像は変換されますが、キャプチャされた画像は変換されないため、正しくキャプチャされます。私もあなたが説明したのと同じ問題を抱えており、次のようにカメラ コントローラーを作成してポップオーバーに配置することで解決しました (iOS7 の場合)。
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
[imagePickerController setDelegate:self];
imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
CGFloat scaleFactor=1.3f;
switch ([UIApplication sharedApplication].statusBarOrientation) {
case UIInterfaceOrientationLandscapeLeft:
imagePickerController.cameraViewTransform = CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI * 90 / 180.0), scaleFactor, scaleFactor);
break;
case UIInterfaceOrientationLandscapeRight:
imagePickerController.cameraViewTransform = CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI * -90 / 180.0), scaleFactor, scaleFactor);
break;
case UIInterfaceOrientationPortraitUpsideDown:
imagePickerController.cameraViewTransform = CGAffineTransformMakeRotation(M_PI * 180 / 180.0);
break;
default:
break;
}
__popoverController = [[UIPopoverController alloc] initWithContentViewController:imagePickerController];
[__popoverController presentPopoverFromRect:presentationRect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
また、横向きのときは、通常よりもファインダーいっぱいに表示されるように画像を拡大縮小します。これは私にとってはかなり厄介なことですが、iOS7.1 がリリースされたら削除できるようになると思います。