ios: allow landscape orientation on webview - ios

my project support portrait and landscape orientations on the device orientation on the general information.
also, most of the viewcontrollers has a superclass named paren view controller in which i implemented methods to show the view only in portrait this method is -shouldautorotate returning NO. This specific controller containing the webview as a one of many views should be in portrait to, so i implemented that method too but i need the video to be in landscape also at the moment it is playing when the done button on the player is tapped and the video disappear the main view has to be on portrait, in other words i need the video to be in landscape and in portrait orientation.
when i return YES from the shouldautorotate method the view containing the webview and the video can rotate which is what i don't want to happen.
Any help to solve this?

You can handle the rotation manually by adding observer.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(orientationDidChange:)
name:UIDeviceOrientationDidChangeNotification object:nil];
}
- (void)orientationDidChange:(NSNotification*)notification
{
/// handle rotation for your views
}

Related

UIViewController device rotation delegate methods are not getting called in iOS8

I have been working an iOS 7 app to make it compatible for ios 8 (beta 5). In this application, UIViewController (vc1) presents another UIViewController (vc2). vc1 supports both Portrait and Landscape orientations; vc2 supports only Portrait orientation. When vc2 is presented, it asks vc1: shouldAutorotateToInterfaceOrientation: and this returns YES.
In iOS8 (Beta 5) willRotateToInterfaceOrientation: and didRotateFromInterfaceOrientation: are not getting called as well as the new iOS 8 API method viewWillTransitionToSize. But, this works fine in iOS7.
I know willAnimateRotationToInterfaceOrientation and didRotateFromInterfaceOrientation are deprecated in iOS 8, but even iOS 8 delegate methods are not getting called. Every time when launched vc2 from vc1 always screens loads in portrait mode only even though I mentioned supported interface orientation as landscape left.
Any ideas... is it a bug in iOS8?
Well, I didn't figure out your problem best but as soon I have a bunch of lines working fine with rotation in iOS 8.1 I will present them to you. They are just taken and a little bit of edited from the Apple API Reference.
Simply I put this in every VC and i just edit the code when needed. For example I have an app that have initial view controller in portrait and then VC changes ( segue is done ) to a LandscapeVC with different features.
This is the portrait view methods leading to a rotation in LandscapeView.
bool isShowingLandscapeView = false;
- (void)awakeFromNib
{
isShowingLandscapeView = NO;
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
}
- (void)orientationChanged:(NSNotification *)notification
{
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) &&
!isShowingLandscapeView)
{
isShowingLandscapeView = YES;
[self performSegueWithIdentifier:#"toLandscape" sender:self];
}
I hope I made it simple for understanding. Don't hesitate to improve my answer, we all learn in this life !

willAnimateRotationToInterfaceOrientation not called on ios6/7

I have an old app, that still lives on iTunes, written in iOS 5. I would like to update it to run on ios 6 and 7. Everything has been fine so far, and I have updated my code to use ARC. However when trying to maintain the same autorotation philosophy I keep hitting a brick wall. I have already checked relative topics within SO like:
Forcing landscape and autorotate in iOS 7,
Autorotate in iOS 6 has strange behaviour
and following a similar topic I have found this:
iOS 6 Autorotation Problems and Help
which lead me to do the following:
I have set the rootViewController within my AppDelegate like so:
self.preloadingViewController = [[PreloadingViewController alloc] initWithNibName:#"PreloadingViewController" bundle:nil];
self.window.rootViewController = self.preloadingViewController;
I have placed:
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
within my AppDelegate. I have overriden shouldAutorotate and supportedInterfaceOrientations within the SuperViewController (parent in inheritance terms) of all of my app's UIViewControllers (including PreloadingViewController mentioned above):
- (BOOL)shouldAutorotate{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
and in every child UIViewController, I override
- (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
with code to layout ui elements in the desirable manner for portrait and landscape orientations.
Finally my app's plist file under
Supported interface orientations
contains:
Portrait (bottom home button), Landscape (left home button), Landscape
(right home button)
all the orientations I want to support.
Still, even though supportedInterfaceOrientations and shouldAutorotate are being called for every orientation change on my rootViewController, willAnimateRotationToInterfaceOrientation is never being called. I have even overriden shouldAutomaticallyForwardRotationMethods in my SuperViewController to return YES, but to no avail.
What am I doing wrong here? Any ideas? I have even considered that the old ios5 - style xibs cause the issue but I do not think this is the case.
Thanks in advance.
In iOS 6 the way willAnimateRotationToInterfaceOrientation is called changed.
Use:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
// Something
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
// Something
}
in your rootController.
EDIT:
New main.m
#import <UIKit/UIKit.h>
#import "yourAppDelegate.h"
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([yourAppDelegate class]));
}
}
Since my rootViewController was the only one getting its shouldAutorotate and supportedInterfaceOrientations methods called, I decided to register every other view controller to get notified of any UIDeviceOrientationDidChangeNotification.
[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
- (void)orientationChanged:(NSNotification *)notification
{
NSLog(#"Orientation changed!");
[self layoutForOrientation:[[UIDevice currentDevice] orientation]];
}
Within my layoutForOrientation: method I handled the uiview's controls orientation.
However, although I did receive UIDeviceOrientationDidChangeNotification notifications normally, my view orientation would not actually change to match the current orientation, i.e. if the new orientation was say, UIInterfaceOrientationLandscapeRight, the view orientation would remain in UIInterfaceOrientationPortrait and its children views would get rotated by 90 degrees. This did certainly not look right. After pulling a lot of hair out, I decided to abandon this route.
Instead, I have set my rootViewController to be a UINavigationController and have it push successive UIViewControllers on top of it. Since I did not want a navigation bar visible in my app I have set the navigation controller's navigationBarHidden property set to YES. This way the method willAnimateRotationToInterfaceOrientation is getting called on every UIViewController that is currently at the top of the navigationCotroller's stack of controllers, and its corresponding view and view controls rotate correctly for the desired orientations.
This works because most of my view controllers supported interface orientations match the mask: UIInterfaceOrientationMaskAllButUpsideDown, the default behaviour for iPhone. Should I needed to support different orientations, I would have to subclass the UINavigationController and override supportedInterfaceOrientations and shouldAutorotate to enable the desired orientations support for the navigation stack's top view controller, as per Apple's example project: AlternateViews.
Implement this method, return YES for what you need.
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation

When using different view controllers (portrait and landscape) to handle orientation changes, is a segue the most appropriate way to handle this?

I have been looking into ways of setting up separate landscape and portrait view controllers to handle a changing orientation. The code posted below is from Apple stating how to do this. I noticed they use performSegueWithIdentifier. It seems odd that a segue is being used.
In order to create a segue on the storyboard I'm assuming I must create a hidden button and drag the connection from the portrait to the landscape view controller. I can then set the segue identifier to "DisplayAlternateView". What is the default segue animation? Or is the default to turn the animation off?
Also why is this code in the awakeFromNib method? Shouldn't it be in viewDidLoad? Is awakeFromNib called before viewDidLoad?
Also I'm assuming I must have a different target action for every scene of my storyboard. If I have portrait view A, B and C with a corresponding landscape view A, B and C, should I have the following changes to the Apple code
on my A view:
selector:#selector(orientationChangedA:)
then on my B
selector:#selector(orientationChangedB:)
then on my C
selector:#selector(orientationChangedC:)
This way each method can perform it's own segue.
I feel like I might be over complicating things here. Are the separate segues causing me to do extra work or is this how how orientation switching to separate view controllers normally handled?
Here is the code from Apple saying how to handle orientation changes with different view controllers:
#implementation PortraitViewController
- (void)awakeFromNib
{
isShowingLandscapeView = NO;
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
}
- (void)orientationChanged:(NSNotification *)notification
{
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) &&
!isShowingLandscapeView)
{
[self performSegueWithIdentifier:#"DisplayAlternateView" sender:self];
isShowingLandscapeView = YES;
}
else if (UIDeviceOrientationIsPortrait(deviceOrientation) &&
isShowingLandscapeView)
{
[self dismissViewControllerAnimated:YES completion:nil];
isShowingLandscapeView = NO;
}
}

willRotateToInterfaceOrientation not being called from presented viewcontroller

I have uiviewcontroller on ipad with this configuration:
shouldAutorotate (true)
supportedInterfaceOrientations (UIInterfaceOrientationMaskAll)
and inside willRotateToInterfaceOrientation i perform some trick to adjust my interface.
From a child of this controller I show a QuickLookController with this -poor- code.
[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:previewController animated:YES completion:nil];
But if I rotate my ipad the method willRotateToInterfaceOrientation not being called, So I cannot do the trick to adjust the interface.
Someone can explain me or given me some advices? thanks
Reason :
There may be many possibilities to this problem.
1) If your view's viewController is a subView of some other rootViewController which is not a navigationController, then there might be chances that rotation call is not propagating to the subView's controller.
2) Somewhere I read that if Super methods are not called properly where it is needed then it might be the cause of rotation problem, which means that all ViewControllers in view stack which are related to the autorotation must call the super methods in method implementations (i.e. calling [super viewDidLoad] from the ViewController's viewDidLoad).
You can use below trick to handle orientation changes.
Register a notifier in viewWillAppear.
-(void)viewWillAppear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];}
The orientation change will notify the below function.
- (void)orientationChanged:(NSNotification *)notification{
[self handleOrientation:[[UIApplication sharedApplication] statusBarOrientation]];}
which will call the below method where you can handle the orientation changes.
- (void) handleOrientation:(UIInterfaceOrientation) orientation {
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
{
//handle the portrait view
}
else if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
{
//handle the landscape view
}
}
I found a paragraph on apple documentation:
If your view controller’s contents are not onscreen when a rotation occurs, then it does not see the list of rotation messages. For example, consider the following sequence of events:
Your view controller presents another view controller’s contents full screen.
The user rotates the device so that the user interface orientation changes.
Your app dismisses the presented view controller.
In this example, the presenting view controller was not visible when the rotation occurred, so it does not receive any rotation events. Instead, when it reappears, its views are simply resized and positioned using the normal view layout process. If your layout code needs to know the current orientation of the device, it can read the app object’s statusBarOrientation property to determine the current orientation.
that say exactly what is my problem, so i add some logic inside
-(void)viewWillAppear:(BOOL)animated
to adjust my layout if something is'n in the right place.
Ensure your view controller is added as a child of the root view controller, then the messages are passed down.
[rootViewController addChildViewController:viewController];

iPad:Lock UIView orientation into Landscape mode only

This requirement is for iPad.
I have an UIView which used as Camera overlay view when launching video recording. It set in UIImagePickerController as below.
[self presentModalViewController:pickerController animated:NO];
pickerController.cameraOverlayView =myOwnOverlay;
This is my requirement that i have to provide my own overlay in UIImagePickerController when calling camera for video recording.
I want to lock my own camera overlay UIView into LANDSCAPE mode only, so that allow user can record video in Landscape mode only and not in Portrait mode, this is also my project requirement.
I know about shouldAutorotateToInterfaceOrientation which is used for UIViewController. I used "[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];" it, it locks to Landscape mode when i launch this camera own overlay UIView, but when i rotate the device, UIView also rotates to Portrait. I don't want Portrait mode at all. I tried to handle this issue like below, but its not working for UIView. Then i saw this is possible in UIviewController, but not in UIView. But i must to have UIView for this camera launch operation.
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation==UIInterfaceOrientationLandscapeRight || interfaceOrientation==UIInterfaceOrientationLandscapeLeft);
}
Please suggest me how can i provide solution for orientation lock for my UIView?
Thank you!
Doubt over allowing from APPLE but If you want the UIImagePickerController to start(and stay) in Landscape orientation use following code.
//Initialize picker
UIImagePickerController * picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
//set Device to Landscape. This will give you a warning. I ignored it.
//warning: 'UIDevice' may not respond to '-setOrientation:'
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
//Set Notifications so that when user rotates phone, the orientation is reset to landscape.
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
//Refer to the method didRotate:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didRotate:)
name:#"UIDeviceOrientationDidChangeNotification" object:nil];
//Set the picker source as the camera
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
//Bring in the picker view
[self presentModalViewController:picker animated:YES];
The method didRotate:
- (void) didRotate:(NSNotification *)notification
{
//Maintain the camera in Landscape orientation
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
}
Credit for This code belongs to UIImagePickerController in Landscape
Try this:
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
BOOL isLandscapeRight = (UIInterfaceOrientationLandscapeRight == interfaceOrientation);
return isLandscapeRight;
}
And Also Have to set Your Applications info.plist's interface orientation to Landscape (right home button)
There is a simple solution to this
In the info.plist file edit the entry supported interface orientation ipad.

Resources