Camera Rotation and OverlayView in iOS8 - objective-c

I am experiencing an issue when using the iPad Camera in iOS 8. I've seen some older questions and a thread on the Apple Developer Forums from during the beta but still haven't find a solution.
There seems to be two parts to this issue.
1) The camera itself rotates when the device orientation rotates, eg the world is on its side
2) When opening the camera in Landscape, the overlay does not appear. When opened in Portrait it is fine.
It is an app using iOS7 as the Base SDK, problem only occurs when running the app on a device that has been upgraded to iOS8. The app is not using storyboards, it is using nibs.
I'm hoping to push out a fix for this with Xcode 5.1.1 before moving onto the iOS8 specific fixes and using it as a Base SDK in the next version.
Here is my code to bring up the camera:
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] == YES) {
// Create Camera
imagePicker = [[UIImagePickerController alloc] init];
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.delegate = self;
imagePicker.showsCameraControls = NO;
// Set up custom controls view
[[NSBundle mainBundle] loadNibNamed:#"OverlayView" owner:self options:nil];
self.overlayView.frame = imagePicker.cameraOverlayView.frame;
imagePicker.cameraOverlayView = self.overlayView;
self.overlayView = nil;
// Show Camera
[self presentViewController:imagePicker animated:NO completion:nil];
[imagePicker release];
}
I have also tried
And the Layout of the Toolbar (sitting at the bottom) of the OverlayView:
If I change that to sit "at the top" it appears in both portrait and landscape! So it must have to do with the view/window/something size, though it's strange how its behaviour would change when the layout has stayed the same.
I have tried it with both showsCameraControls = YES and hashing out the OverlayView block, and problem #1 persists so it's not to do with the overlay at app.
I'm hoping someone has found an answer to this, it seems like quite a common problem.
Please let me know if you need any further details.
Edit 1: Fixed the Overlay (Issue #2)
It wasn't applying the orientation to the OverlayView, fixed it like this:
// Grab the window frame and adjust it for orientation - from http://stackoverflow.com/a/15707997/520902
UIView *rootView = [[[UIApplication sharedApplication] keyWindow]
rootViewController].view;
CGRect originalFrame = [[UIScreen mainScreen] bounds];
CGRect screenFrame = [rootView convertRect:originalFrame fromView:nil];
...
self.overlayView.frame = imagePicker.cameraOverlayView.frame;
I suspect that it's related to the camera not realising it's orientated too, will keep searching for a fix for Problem #1.
Edit 2: Update on Issue #1
Looks like the camera rotating might be an Apple issue. On iOS8 if you open up the Contacts app, edit a contact and choose 'Take Photo', the exact same issue occurs - in a default Apple app!
I still can't find a fix so I am just destroying and recreating the imagePicker on each orientation change for now, it's ugly but will suffice until Apple release a fix or a better solution pops up.

Apple fixed this problem in iOS 8.1.

Related

My iOS app Screen is not auto sizing in iOS 5 dimension

The Screen UI is developed for 3:2, but when I run the app in iOS Simulator for iphone 5 and above, I see there is a white patch below in the bottom of the screen. The rest of the screens are appearing correctly.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[self startup];
[window addSubview:loginViewController.view];
//For Eula
NSDictionary *eulaDict = [EULAController getEULADictionary];
if (eulaDict == nil || [ self checkForVersionChange] == TRUE) {
eulaController = [[EULAController alloc] initWithNibName:#"eula"bundle:[NSBundle mainBundle]];
//temp fix as for some reason this is showing up 20 pixels shifted upwards. if this works in your scenario then remove this adjustment
CGRect frame1 = CGRectMake(0,20,320,460);
[eulaController.view setFrame:frame1];
[window addSubview:eulaController.view];
}
[self updateVersionAndBuild];
[window makeKeyAndVisible];
}
Not sure, why its not fitting the entire screen. I didn enable athe AutoLayout option but it didnt help, as during the launch of the app, it stops for iphone 5/6.
Thanks in advance !
I guess you are missing the Default-568h#2x.png default launch image...
If so, just add one to your project and it will work.
You've hardcoded the frame to iPhone 4 size:
CGRect frame1 = CGRectMake(0,20,320,460);
You've said your using autoLayout. I'd remove this and use autoLayout constraints instead and it will scale.

Prevent shutter animation from appearing full screen when using cameraOverlayView [duplicate]

I have a transparent view with a rectangle drawn onto it using CoreGraphics.
When the camera launches the custom overlay view is above the shutter animation.
What you see is the standard camera shutter with the custom rectangle above it.
How do I get it to go in the right place, underneath the shutter animation? I've looked at other sample code but it's for OS 3.1 and doesn't seem to do anything differently.
Here's my code:
-(IBAction)cameraButton{
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerCameraDeviceRear]){
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
//Add the OverlayView with the custom Rectangle
CGRect overlayFrame = CGRectMake(0.0f, 0.0f, 320.0f, 480.0f);
OverlayView *overlayView = [[OverlayView alloc]initWithFrame:overlayFrame];
picker.cameraOverlayView = overlayView;
[overlayView release];
[self presentModalViewController:picker animated:YES];
[picker release];
}
}
On the iPad this problem doesn't exist, and the overlay view is behind the shutter animation by default. But on the iPhone, the overlay appears at front.
I've found a solution that worked for me.
You have to set your overlay view as a subview in this method:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (!viewController)
return;
UIView* controllerViewHolder = viewController.view;
UIView* controllerCameraView = [[controllerViewHolder subviews] objectAtIndex:0];
UIView* controllerPreview = [[controllerCameraView subviews] objectAtIndex:0];
[controllerCameraView insertSubview:self.overlayView aboveSubview:controllerPreview];
}
Hope it helps
Original source:
http://www.alexcurylo.com/blog/2009/06/18/uiimagepickercontroller-in-3-0/
You may not do anything else other than what you're already doing; if iOS decides to put your overlay view over the shutter, you'll just have to live with it (unless you want to risk getting rejected from the app store).
As an imperfect workaround, you could start your overlay with alpha=0 and then set alpha to 1 a second or two later. But there is no set time period that the shutter appears for before 'opening' (I think it depends on how long it takes to initialize the camera hardware), so sometimes your interface might not appear until late and sometimes might appear too early.
As of 4.3.3, the shutter animation is broken because elements are displayed on top, and then snap underneath when the animation starts. I've filed this as a Radar: http://openradar.appspot.com/radar?id=1204401
I answered a similar question here. What worked for me (in iOS 6) was setting the cameraOverlayView in navigationController:willShowViewController:animated.
- (void) navigationController:(UINavigationController*) navigationController willShowViewController:(UIViewController*) viewController animated:(BOOL) animated {
self.imagePickerController.cameraOverlayView = ...; // your camera overlay view
}

UIImagePicker Front Camera strange behavior on orientation in iPad

Scenario
An app that captures an image from Front camera automatically after 3 sec countdown.
Everything is working as expected.
Code
//in viewDidLoad
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
imagePicker = [[UIImagePickerController alloc] init];
self.imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
self.imagePicker.cameraDevice = UIImagePickerControllerCameraDeviceFront;
self.imagePicker.delegate = self;
self.imagePicker.showsCameraControls = NO;
[self.imagePicker.view setFrame:kAppFrame];
[self.view addSubview:self.imagePicker.view];
[self.view bringSubviewToFront:self.imagePicker.view];
}
Problem
I have never told the ipad to use its rear device Still in certain cases the rear camera starts.
Steps to reproduce
Hold the camera in Landscape orientation
Click a photo (Will take you to next screen, pushed in Nav controller)
In the next screen tilt the ipad halfway towards face up orientation
Comeback to camera screen and you see it using rear camera.
This is a very strange behavior I am not even able to understand its cause.
check your code the line self.imagePicker.cameraDevice = UIImagePickerControllerCameraDeviceFront; define that you open your front vamera of device.
Now your second problem: i am not sure but you have to rotate your image 90 degree. It's may be when you get image it's get in portrait mode.
It looks like I have found the solution.
just moving the entire code to viewWillAppear from viewDidLoad method.
It looked like I was relying a lot on view before it appeared with a certain orientation. Putting the code in viewWillAppear guaranteed me that the view is actually ready with its orientation set. I can now put anything on it.
I know this is not the proper answer but this is what I made out of the scenario. Any modifications/correction are most welcome.

UIPopoverController strange behavior

I am using a UIPopoverController and populating it with a MPMediaPickerController to choose songs from iPod library. I have got it working just fine. However, I added a completely unrelated feature ( touch a button and image scale to large size ) and now the UIPopoverController behaves strangely only after using the new feature.
After using the button scale feature, the UIPopoverController appears in a strange manner. It looks like it is animating from a rotated state off the screen and lands in the correct place, but the expected behavior is that it should just appear in the right location.
// code for if the interface is a an iPhone, do not use popup
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
[self presentModalViewController:picker animated:YES];
// code if not iPhone uses popover media picker
else {
UIPopoverController* pop =
[[UIPopoverController alloc] initWithContentViewController:picker];
self.currentPop = pop;
// checks if the iPad is portrait or landscape and displays the popover media picker accordingly
if (vertMode == TRUE)
{
// if in portrait mode
[pop presentPopoverFromRect:CGRectMake(668.0f, 846.0f, 10.0f, 10.0f) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:NO];
// otherwise if in landscape mode
}
else if (vertMode == FALSE)
{
[pop presentPopoverFromRect:CGRectMake(900.0f, 580.0f, 10.0f, 10.0f) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:NO];
}
[pop release];
}
}
OK, well I feel a bit silly answering my own question, but I hope that it may help someone else in the future.
I am not exactly sure why, but in my function for the button that scales the image to a large size, I forgot to add:
[UIView commitAnimations];
the intention of that was to complete the animated movement of the scaling image, I am guessing because I never commit the animation, that it was still in some state of trying to animating things. Then when I called my popup , it made the weird animation occur.
So I fixed this by just adding the above one line!
I feel SO much better figuring this one out! I hope it helps someone else out there.

MPMoviePlayerViewController customization

I'm using MPMoviePlayerViewController - with the player controls set to: MPMovieControlStyleFullscreen
I'm having a problem with some of buttons that are in MPMovieControlStyleFullscreen: forward, reverse, and fullscreen (the one with the arrows pointing at eachother).
I would like to either remove the forward, reverse, and fullscreen buttons or control what they do when the user taps them.
Thank you!
There isn't a way to customize the MPMovieControlStyle values provided by Apple. What you need to do is is turn off the Apple controls (MPMovieControlStyleNone) and then create your own custom controls. Apple is fine with you putting your own UIViews in to the hierarchy here, so you can get started with something like this:
MPMoviePlayerController *moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL: YOUR_URL];
moviePlayer.controlStyle = MPMovieControlStyleNone;
UIView *movieView = moviePlayer.view;
[movieView addSubview: _movieControlsView];
[movieView bringSubviewToFront: _movieControlsView];
Where _movieControlsView was set up earlier in code or in IB.
Aesthetically, you can do what you want, but I would recommend sticking with something that looks like Apple's choices so as not to confuse the user. For the project I just finished, I created a transparent button the exact size of the movie player. Clicking the button fades in a control bar on the bottom with my custom controls. If one of the controls isn't clicked, the control bar fades back out again after a few seconds.
First off, MPMoviePlayerController is a little different than MPMoviePlayer*View*Controller, so some of these answers lead to problems when converting applications that were built in an iOS 4.3+ environment.
I've built some apps using MPMoviePlayerController that worked fine when built in iOS 3.2. When I rebuilt it with XCode 3.2.6, (iOS 4.3), the videos don't even play on the iPhone. I since fixed that by adding the MPMoviePlayerController instance to a subView, then presenting a modal (Player is a UIViewController) with the movplayer in fullScreenMode:
//from didSelectRowAtIndexPath
Vid *selected = [items objectAtIndex:position];
player = [[Player alloc] init];
movplayer = [[MPMoviePlayerController alloc] initWithContentURL:selected.vidURL];
movplayer.view.frame = player.view.bounds;
movplayer.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight |
UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
[player.view addSubview:movplayer.view];
[self presentModalViewController:player animated:YES];
[movplayer setFullscreen:YES animated:NO];
[movplayer play];
[player release];
//movplayer is released inside - (void)exitedFullscreen:(NSNotification*)notification
This was done on account of the UINavigationBar being half cut off when rotating.
When I got to the iPad version of the app the modal option wouldn't work aesthetically. It was also having the UISplitViewController navBar and toolbars half cut off when rotating in full screen mode. So I tried implementing MPMoviePlayerViewController instead of MPMoviePlayerController. With this conversion, XCode gave me errors when trying to set:
movplayer.controlStyle = MPMovieControlStyleEmbedded;
The proper way to do this with a MPMoviePlayerViewController is:
movplayer.moviePlayer.controlStyle = MPMovieControlStyleEmbedded;
When the player is added as a subView, the pinch gestures will toggle the player between fullScreen and the size of your parentView (player.view.bounds) smoothly, as well as preserve the toolbars and navBars native to the parent.
//iPad version with a view (viewForMovie) inside the DetailViewController
movplayer = [[MPMoviePlayerViewController alloc] initWithContentURL:[current vidURL]];
movplayer.moviePlayer.controlStyle = MPMovieControlStyleEmbedded;
movplayer.view.backgroundColor = [UIColor clearColor];
movplayer.view.frame = viewForMovie.bounds;
[viewForMovie addSubview:movplayer.view];
So these two examples show some workarounds for those who want to convert their iPhone or iPad apps to a newer iOS version.
Try setting MPMovieControlStyle of your MPMoviePlayerController object to MPMovieControlStyleNone