Landscape Mode: Flip image when you flip your iPad - objective-c

Apple demonstrated Photo's for the iPad. In their demo, they said you can Flip the iPad and it flips the image.
How is this result achieved?
I've been reading about UIInterfaceOrientation all day and I'm lost
Any help would be appreciated.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
UIInterfaceOrientation orientation = [[UIDevice currentDevice] orientation];
// NSLog(#"orientation: %#", [orientation )
if(orientation==UIInterfaceOrientationPortrait ||orientation==UIInterfaceOrientationPortraitUpsideDown) {
//Code
return NO;
}
if (orientation==UIInterfaceOrientationLandscapeRight ||orientation==UIInterfaceOrientationLandscapeLeft ) {
//Code
return YES;
}
return NO;
}

You implement in your UIViewController subclass:
- (BOOL)shouldAutorotateToDeviceOrientation:... {
Return YES;
}
And most of the time the UIKit manages it all for you.

Related

how to detect the landscape mode on rotation in ios7?

My app displays pdf pages,in portrait mode a single page is getting displayed(default mode is portrait).On rotating to landcscape it should display two pages side by side,
In my ViewController's viewdidloadmethod i have added the following,
- (void)viewDidLoad
{
UIDeviceOrientation deviceOrientation = [[UIDevice currentDevice] orientation];
landscape=UIDeviceOrientationIsLandscape(deviceOrientation);
if(landscape)
{
//logic goes here
}
else
{
logic for portrait goes here
}
}
But it's not working for me,only the portrait logic is getting excecuted.Please help
Orientation changes are handled a bit different way.
Your viewcontroller needs to receive notification, when orientation changes.
Here's the sample code:
#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)
{
isShowingLandscapeView = YES;
// logic for landscape orientation goes here
}
else if (UIDeviceOrientationIsPortrait(deviceOrientation) &&
isShowingLandscapeView)
{
isShowingLandscapeView = NO;
// logic for portrait orientation goes here
}
}
For futher information, check Apple documentation

How to rotate a video embed in UIWebView (for iOS 7 only)?

The app I'm working on is portrait oriented, but when a video is running (it is embed in a webview), I need to re-orient the video in landscape mode. How should I do that? I found a solution, which worked just fine until days ago :). I believe it's because iOS 7 updates, but I'm not sure. So, this is what I previously used, but it is not working anymore because window and class name are always nil.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
id presentedViewController = [window.rootViewController presentedViewController];
NSString *className = presentedViewController ? NSStringFromClass([presentedViewController class]) : nil;
if (window && [className isEqualToString:#"MPInlineVideoFullscreenViewController"]) {
return UIInterfaceOrientationMaskAll;
} else {
return UIInterfaceOrientationMaskPortrait;
}
I found a solution by myself, finally! I implemented the following method in AppDelegate and it worked. My problem was that, at first, I didn't check the right view controller.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
NSString *className = NSStringFromClass([window class]);
if ([((UINavigationController *)window.rootViewController) respondsToSelector:#selector(visibleViewController)]) {
className = NSStringFromClass([((UINavigationController *)window.rootViewController).visibleViewController class]);
}
if ([className isEqualToString:#"MPFullscreenWindow"] || [className isEqualToString:#"MPInlineVideoFullscreenViewController"]) {
return UIInterfaceOrientationMaskAll;
} else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
return UIInterfaceOrientationMaskLandscape;
} else {
return UIInterfaceOrientationMaskPortrait;
}
Here's a solution that will allow rotation on any additional windows presented in the iPhone app (such as a vide player) but remain landscape in an iPad app. Place it in your app delegate.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
return UIInterfaceOrientationMaskLandscape;
} else {
if (window == self.window
|| ![window isMemberOfClass:[UIWindow class]]) {
return UIInterfaceOrientationMaskPortrait;
}
if ([window isEqual:[[UIApplication sharedApplication] windows][1]]) {
// Rotate the secondary window.
return UIInterfaceOrientationMaskAllButUpsideDown;
}
return UIInterfaceOrientationMaskPortrait;
}
So I figured I'd share what my solution was. Actually branching off of the OP question, just modified it. Works for me on iOS 7 and 8.
My approach was different as I have a toggle switch in another view controller that enables portrait or landscape.
Anyways, here it is.
UPDATED:
Ok so the previous method broke the launch screen. Example: If you have your device in landscape, and launched but it's a portrait app, it will rotate, BUT, the window will get cut in half. Pain in the butt esp if you have some nice loading screens going on. Anyways, the replaced code below fixes that AND allows video rotation. Obviously not everybody will be using a rotation switch, just adjust accordingly.
//Allow video only rotation in portrait mode.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
//Switch for Rotation
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
BOOL switchOn = [userDefaults boolForKey:#"Rotation"];
if (switchOn) {
window.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
[window setFrame:[[UIScreen mainScreen] bounds]]; //Add
return UIInterfaceOrientationMaskAllButUpsideDown;
}
else {
id presentedViewController = [window.rootViewController presentedViewController];
NSString *className = presentedViewController ? NSStringFromClass([presentedViewController class]) : nil;
if ((window && [className isEqualToString:#"MPInlineVideoFullscreenViewController"]) ||
[className isEqualToString:#"MPMoviePlayerViewController"] ||
[className isEqualToString:#"AVFullScreenViewController"]) {
window.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
[window setFrame:[[UIScreen mainScreen] bounds]]; //Add
[window makeKeyAndVisible];
return UIInterfaceOrientationMaskAllButUpsideDown;
}
window.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
[window setFrame:[[UIScreen mainScreen] bounds]]; //Add
return UIInterfaceOrientationMaskPortrait;
}
self.window.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
[self.window setFrame:[[UIScreen mainScreen] bounds]]; //Add
[self.window makeKeyAndVisible];
}
UPDATED AGAIN:
So the previous edit I laid out had a weird flicker of the view below the movie player. This seems to have fixed that. Tested on 6+ device, and iOS 7/8 in the simulator.
Hope this helps somebody.
Swift 3, I sorted out on this way (your info.plist / project settings can have ONYL the portrait orientation checked) :
// MARK: - Orientation
extension AppDelegate {
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
// Let webView video to be rotated
if window != self.window {
return window?.rootViewController?.supportedInterfaceOrientations ?? .all;
}
// All other screens are portrait
return .portrait;
}
}
Try It....
-(BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
If you don't want your UIViewController to be able to rotate when the video isn't on the screen. Use this--
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if(webView && webView.superView) return YES;
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
This is very similar to how I solved for iOS 7, but this doesn't work for iOS 8. MPFullscreenWindow is no longer returned and Xcode complains about breaking constraints.
My solution seems to be fairly general, and takes care of some weird behavior on iOS 7 where window sometimes passed in as nil.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
return UIInterfaceOrientationMaskAll;
}
else
{
// when dismissing a view controller, the view controller being returned to isn't in control of the orientiation
// (shouldAutorotate and supportedInterfaceOrientations seem to be called, but they aren't observed then,
// rather only when the device is rotated after that view is fully showing)
// instead, the result of this method only is what's observed
// we could return different values depending on which view controller is frontmost, but currently it seems
// good enough to call supportedInterfaceOrientations of the frontmost view controller and return that
// on ios7, critical calls to this method are often passed window=nil, in that case use self.window instead
UIViewController *frontViewController = window ? window.rootViewController : self.window.rootViewController;
// special case only when transitioning to or from a presented view controller
if (frontViewController.presentedViewController &&
(frontViewController.presentedViewController.isBeingDismissed || frontViewController.presentedViewController.isBeingPresented))
{
if (frontViewController.presentedViewController && !frontViewController.presentedViewController.isBeingDismissed) {
frontViewController = frontViewController.presentedViewController;
}
if ([frontViewController isKindOfClass:[UINavigationController class]]) {
frontViewController = ((UINavigationController *)frontViewController).topViewController;
}
// return whatever the front view controller's supportedInterfaceOrientations returns, since it normally is ignored for some reason
return [frontViewController supportedInterfaceOrientations];
}
else
{
// return this normally, this gets intersected with the result of the front view controller's supportedInterfaceOrientations
return UIInterfaceOrientationMaskAllButUpsideDown;
}
}
}
=> Put below method inside your AppDelegate class, it allow to play video in landscape mode even when device orientation is locked to portrait mode only:
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)windowx
{
if ([[self.window.rootViewController presentedViewController] isKindOfClass:[MPMoviePlayerViewController class]] ||
[[self.window.rootViewController presentedViewController] isKindOfClass:NSClassFromString(#"MPInlineVideoFullscreenViewController")])
{
if ([self.window.rootViewController presentedViewController].isBeingDismissed)
{
return UIInterfaceOrientationMaskPortrait;
}
else
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
}
else
{
return UIInterfaceOrientationMaskPortrait;
}
}

Screen rotation doesn't work on iOS 5 but is working on iOS 6

I'm currently having a problem with the screen rotation on iOS 5. On iOS 6, everything works fine but the rotation doesn't work on iOS 5 even though the notification UIDeviceOrientationDidChangeNotification is called.
I'm using Storyboard and here's how my ViewController is like:
In order to rotate the screen I use the following methods:
CustomTabBarViewController.mm (UITabBarController)
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
if (isLandscapeOK) {
// for iPhone, you could also return UIInterfaceOrientationMaskAllButUpsideDown
return UIInterfaceOrientationMaskAllButUpsideDown;
}
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (isLandscapeOK) {
// for iPhone, you could also return UIInterfaceOrientationMaskAllButUpsideDown
return (interfaceOrientation == UIInterfaceOrientationMaskAllButUpsideDown);
}
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
TabBarItemController.mm (UINavigationView)
-(BOOL)shouldAutorotate
{
return [self.topViewController shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return [self.topViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}
LoyaltyListController.mm (UIViewController)
- (void) didRotate:(NSNotification *)notification
{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if (orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight)
{
self.navigationController.navigationBarHidden = YES;
[self hideTabBar:self.tabBarController];
portraitView.hidden = YES;
landscapeView.hidden = NO;
}
else if (orientation == UIDeviceOrientationPortrait)
{
self.navigationController.navigationBarHidden = NO;
[self showTabBar:self.tabBarController];
portraitView.hidden = NO;
landscapeView.hidden = YES;
[notificationView setFrame:CGRectMake(0, - (notificationView.frame.size.height + 40), notificationView.frame.size.width, notificationView.frame.size.height)];
}
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didRotate:) name:UIDeviceOrientationDidChangeNotification object:nil];
[(CustomTabBarViewController*)[self tabBarController] setLandscapeOK:YES];
}
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationMaskAllButUpsideDown);
}
And here are the screen for iOS 5:
Portrait:
Landscape: (didn't rotate)
Here's what it should look like:
Any idea?
For iOS 5 use - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)
in iOS 6, its deprecated but it wont matter if you use it.
It will only get called in case its iOS 5.0 or below.
Updated:
UIInterfaceOrientationMaskAllButUpsideDown is NOT an UIInterfaceOrientation enum type.
Masking is used in iOS 6 to give a mask value to give a combination of orientations you want to support but in iOS 5.
You will have to check if the interfaceOrientaion is either of
UIInterfaceOrientationLandscapeLeft,UIInterfaceOrientationLandscapeRight, UIInterfaceOrientationPortrait or UIInterfaceOrientationPortraightUpsideDown.
and return YES or NO based on which all orientations you want to support.
In your case Use:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
/* If you are supporting all, simply return YES,
if you aren't supporting any return NO, otherwise Use || and check which ones you wanna return YES for.
In this case you wanna support all except UpsideDown hence use this. */
}
you have to return YES for supporting all orientation iOS 5 and previous and its deprecate in iOS and not get called in iOS 6, you have already implemented iOS6 methods correctly
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}

iOS 6 Orientation with Navigation Controller

I have an app that works fine on ios 5,im trying to upgrade my app to work on ios 6, i had read tons of questions and tutorials about using ios 6 orientation,
my problem is when i call my rootViewController its work fine with me, but when i push any viewController the orientation look so bad because i use the orientation to change the view sizes (my app support any orientation)
here is my code:
AppDelegate:
UINavigationController *nav =[ [UINavigationController alloc] initWithRootViewController:theView] ;
self.window.rootViewController = nav;
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window // iOS 6
{
return UIInterfaceOrientationMaskAll;
}
myFirstViewController:
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskAll;
}
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
[self viewWillAppear:NO];
}
-(BOOL)shouldAutorotate{
return YES;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:NO];
if ( [[UIDevice currentDevice].systemVersion floatValue] >= 6.0){
if (pointRange.location != NSNotFound) {
UIInterfaceOrientation interfaceOrientation = [[UIDevice currentDevice] orientation];
if( (interfaceOrientation >= 3) ) {
width=1024;
self.view.frame=CGRectMake(0, 0, 1024, 768);
}
if ( (interfaceOrientation == 1) || (interfaceOrientation == 2 )) {
width=768;
self.view.frame=CGRectMake(0, 0, 768, 1024);
}}
....etc
and i did the same in my second view, Hope to find why!!
You could always make an extension to the UINavigationController like this
#implementation UINavigationController (RotationFix)
-(NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
-(BOOL)shouldAutorotate
{
return YES;
}
#end
even i suffered for 2 days.. gone through many tutorials, blogs, forums, even apple docs.
So far i came to know, In iOS 6 each template of the app should be handled in a different ways.
So far the discussions were only for view based app, and these changes were not working on navigation based app or tabBar based app.
Finally i got the solution, it like this
Implement a subclass of these two types UITabBarController or UINavigationController.
Got to know from this blog. Thanks to Shabbir for the solution.

iPad/iPhone orientation issue

I realize there a many questions relating to this issue, however i have not found one that solves my issue.
To start, I have set this code in my menu.h
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES; }
The status bar changes with orientation but the views are not rotating or resizing. In order to try to narrow down my issue, I decided to try to switch two views within one .xib based on orientation
- (void)viewDidLoad {
[super viewDidLoad];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:#"UIDeviceOrientationDidChangeNotification" object:nil];
}
-(void) orientationChanged:(NSNotification *)object
{
UIDeviceOrientation deviceOrientation = [[object object] orientation];
if (deviceOrientation == UIDeviceOrientationLandscapeLeft || deviceOrientation == UIDeviceOrientationLandscapeRight)
{
self.view = self.landscapeView;
}
else
{
self.view = self.portraitView;
}
}
In the iOS simulator, the view definitely changes to the specific views. However the landscape view shows up as if it was portrait and sideways.
my landscape view in IB
My landscape view in the iOS simulator after changing orientation
What am I doing wrong here? I can't figure it out, any help would be greatly appreciated. Thank you in advance.
** EDIT: New Code Below **
Okay.. my issue is that the view loads properly in landscape, it's just sideways. So the Landscape view loads, just sideways. My revised code based on #Seega is:
- (void)viewDidLoad {
[super viewDidLoad];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:#"UIDeviceOrientationDidChangeNotification" object:nil];
[[TTNavigator navigator] setCustomTarget:self];
[[TTNavigator navigator] setCustomAction:#selector(photoAction)];
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
if (toInterfaceOrientation == UIDeviceOrientationLandscapeLeft || toInterfaceOrientation == UIDeviceOrientationLandscapeRight)
{
self.view = self.landscapeView;
}
else
{
self.view = self.portraitView;
}
}
-(void) orientationChanged:(NSNotification *)object
{
UIDeviceOrientation deviceOrientation = [[object object] orientation];
if (deviceOrientation == UIDeviceOrientationLandscapeLeft || deviceOrientation == UIDeviceOrientationLandscapeRight)
{
self.view = self.landscapeView;
}
else
{
self.view = self.portraitView;
}
}
I would suggest putting your code in :
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
instead of making a new method. This will get called automatically if the shouldAutorotateToInterfaceOrientation method returns YES for that rotation.
Also there is a difference between UIDeviceOrientation and UIInterfaceOrientation so make sure your referencing the correct one. Your existing code would be changed to the following:
if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
self.view = self.landscapeView;
}
else
{
self.view = self.portraitView;
}
Also you can use a macro to check the interface orientation keeping your code cleaner.
if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation))
{
self.view = self.landscapeView;
}
else
{
self.view = self.portraitView;
}
Can you make sure, you have all the orientation support selected as follows. I tried this, and it seems to be working fine for me.
You should better simply use
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
self.view = self.landscapeView;
}
else
{
self.view = self.portraitView;
}
}
to handle the rotations instead of creating a own one.
And now you can delete all the notification stuff.
Idea!!!
If you are setting up the views in interface builder and then switching the actual view thats being displayed when the view rotates then you need to build that View in that particular orientation, not just size it to fit the orientation.
To check this:
Open your .xib in Interface Builder.
Click on the 'view' under objects so you have the whole view selected.
Look under the 'Simulated Metrics' on the right side of IB. Make sure 'Landscape' is selected in the 'Orientation' drop down.
If your view says 'Portrait' for the view you want to represent your landscapeView then it could be that xcode is rotating your landscape view to portrait and messing with your presentation.
Let me know if this helped.
Hey thank you all for your help. I had a friend help and am not entirely sure was the problem. I can tell you the things I know he did do.
Disabled our ads temporarily
deleted the second view entirely and went with native orientation and resizing
added this to almost every .m file.
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
As well a programmatically changed a few of the other views similar to this
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation == UIDeviceOrientationLandscapeLeft || interfaceOrientation == UIDeviceOrientationLandscapeRight)
{
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)
{
self.Button.frame = CGRectMake(27,96,86,86);
self.Label.frame = CGRectMake(27,162,86,21);
}
else
{
self.Button.frame = CGRectMake(18,100,86,86);
self.Label.frame = CGRectMake(18,164,86,21);
}
}
}
Sorry, I can't fully explain the answer, I do not fully understand everything that was included in the project that affected the orientation. I am still very new to iOS development.