First - I read all similar topics and non of them work for me.
I have few View Controllers. And I change them by that code:
- (void)flipToAzbukaMenu {
AzbukaMenuController *aAzbukaMenu = [[AzbukaMenuController alloc] initWithNibName:#"AzbukaMenu" bundle:nil];
[self setAzbukaMenuController:aAzbukaMenu];
[aAzbukaMenu release];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:2.0];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:window cache:NO];
[viewController.view removeFromSuperview];
[azbukaArcadeController.view removeFromSuperview];
[self.window addSubview:[azbukaMenuController view]];
[UIView commitAnimations];
}
Also I have proper key in plist that allows me to start the application in landscape mode. When the app starts it has proper orientation (landscape), but when I change my view it becomes portrait and becomes again landscape only after rotating device 270 degree (not 90 lol). How do I force the app to show all views in landscape mode?
UPD:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if ((interfaceOrientation==UIInterfaceOrientationPortrait)||(interfaceOrientation==UIInterfaceOrientationPortraitUpsideDown))
{
return NO;
}
if ((interfaceOrientation==UIInterfaceOrientationLandscapeLeft)||(interfaceOrientation==UIInterfaceOrientationLandscapeRight))
{
return YES;
} else {
return YES;
}
}
There are two landscape modes and two portrait modes. One is landscape left, the other is landscape right. For instance, if you flip to one of the portrait modes (let's say, with home button on the bottom) from landscape left, you are going to get a 270 degree rotation.
As for how to force your views to stay in landscape (pick one of the two modes), just do something like:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
This will always cause that view to be displayed in landscape left orientation.
Related
I am trying to make an app with UIScrollView (pagingEnabled) that should adapt on the device's interface orientation.
to do this, i made two UIScrollViews loaded with UIImageviews and UIButtons inside and animations (CA). one for portrait and the other one for landscape (you'll see it in my code).
now my problem is whenever i rotate the device, yes! it respond to the orientation change but it goes back to the first page.
ok picture this... you are already on the 10th page of the scrollView in portrait then when you switched to landscape it is on the first page again.
i hope explained it clearly.
and... it crashes on iPad when i rotate it.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown || interfaceOrientation == UIInterfaceOrientationLandscapeRight || interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
if(toInterfaceOrientation == UIInterfaceOrientationPortrait || toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown){
//self.view = portraitView;
[self changeTheViewToPortrait:YES andDuration:duration];
}
else if(toInterfaceOrientation == UIInterfaceOrientationLandscapeRight || toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft){
//self.view = landscapeView;
[self changeTheViewToPortrait:NO andDuration:duration];
}
}
- (void) changeTheViewToPortrait:(BOOL)portrait andDuration:(NSTimeInterval)duration{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
if(portrait){
//change the view and subview frames for the portrait view
[self forPortrait];
[self removeMainSVLContents];
}
else{
//change the view and subview frames for the landscape view
[self forLandscape];
[self removeMainSVPContents];
}
[UIView commitAnimations];
}
What's inside "forPortrait" is the same as in "forLandscape" they just have different frames and it has different images too that will fit the screen on portrait and landscape.
at the time of the animation use **scrollRectToVisible:animated:** method to show or stay on the desire place of scroll view
may this will be useful to you.
here is my code:
if ([[UIApplication sharedApplication] statusBarOrientation] != UIInterfaceOrientationLandscapeLeft) {
[appDelegate makeTabBarHidden:TRUE];
self.navigationController.navigationBarHidden = YES;
[UIView beginAnimations:#"newAlbum" context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(addResultGraph)];
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft animated:YES];
// Then rotate the view and re-align it:
CGAffineTransform landscapeTransform = CGAffineTransformMakeRotation( 90.0 * M_PI / -180.0 );
landscapeTransform = CGAffineTransformTranslate( landscapeTransform, +90.0, +90.0 );
[self.navigationController.view setTransform:landscapeTransform];
[UIView commitAnimations];
}
and with this, from a portrait mode, the new viewcontroller is shown in landscapeleft mode, and everything is ok, but my problem is: if I rotate the device from landscape mode in portrait, the statusbar appears in portrait mode and the viewcontroller remains in landscape mode....
how can I solve this?
thanks in advance!
You may re-implement shouldAutorotateToInterfaceOrientation method and do something like
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
This way you enable only left orientation and, if you rotate your device to portrait, the interface won't rotate
I'm using willRotateToInterfaceOrientation to swap views when my iPad rotates. If I have a modal view or an alert view open when my device rotates and swaps views, the view swaps and the alert disappears and does not reappear, even if the alert is "presented" again later.
Edit:
I've narrowed this problem a bit. When a modal view is presented with UIModalPresentationFullScreen, the modal view "survives" rotations.
What can I do to fix this?
Here is my implementation of willRotateToInterfaceOrientation:
- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
//
// Load an alternate view depending on the orientation
//
if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
[UIView beginAnimations:#"" context:nil];
[self setView:theLandscapeView];
self.view.bounds = CGRectMake(0, 0, 1024, 768);
self.view.transform = CGAffineTransformMakeRotation(kDegreesToRadians * (-90));
[UIView commitAnimations];
}else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
[UIView beginAnimations:#"" context:nil];
[self setView:theLandscapeView];
self.view.bounds = CGRectMake(0, 0, 1024, 768);
self.view.transform = CGAffineTransformMakeRotation(kDegreesToRadians * (90));
[UIView commitAnimations];
}else if (toInterfaceOrientation == UIInterfaceOrientationPortrait) {
[UIView beginAnimations:#"" context:nil];
[self setView:thePortraitView];
self.view.transform = CGAffineTransformMakeRotation(kDegreesToRadians * (0));
self.view.bounds = CGRectMake(0, 0, 768, 1024);
[UIView commitAnimations];
}else if (toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
[UIView beginAnimations:#"" context:nil];
[self setView:thePortraitView];
self.view.transform = CGAffineTransformMakeRotation(kDegreesToRadians * (180));
self.view.bounds = CGRectMake(0, 0, 768, 1024);
[UIView commitAnimations];
}
}
If I were solving this problem, I would do one of the following
Add the alternate views to a parent view, and not change the view property
Create a design for the views that does not require a full view swap, but rearranges or hides subelements of the view.
Present any modal from the root ViewController of the hierarchy
I would work very hard not to swap out the view entirely for the sake of orientation. It seems like something that will continue to present problems even after you have solved this one.
If you swap views, you should also swap modal views I think.
For example, if you present popover controller - it'll automatically dismissed and then appeared with UI rotation.
Here's an idea: keep you main view constant, but change the subview to your portrait or landscape view. something like:
- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
// Remove the current subview from the main view
if (self.view.subviews.count) {
[self.view.subviews objectAtIndex:0] removeFromSuperview];
}
// Use your if-else block, but change [self setView:] for [self.view addSubview:]
}
So now when you create your modal, it will be linked to your controller, which now has a constant main view.
Note that I didn't test this, as I'm getting my head back into coding after two weeks off...
Good luck!
Hey all. I have a fairly simple question. I am developing a "rich" iPad app, and I have two background images specifically designed for landscape and portrait. I'd like this ImageView to automatically change depending on the devices orientation. (like pretty much all of Apples iPad apps).
Can anyone point me in the right direction? I'm assuming it would be something I do on viewDidLoad..
The best thing you can do is to change the frames of your subview frames according to your interface orientations. You can do it like:
#pragma mark -
#pragma mark InterfaceOrientationMethods
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (UIInterfaceOrientationIsPortrait(interfaceOrientation) || UIInterfaceOrientationIsLandscape(interfaceOrientation));
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
if(UIInterfaceOrientationIsPortrait(toInterfaceOrientation)){
//self.view = portraitView;
[self changeTheViewToPortrait:YES andDuration:duration];
}
else if(UIInterfaceOrientationIsLandscape(toInterfaceOrientation)){
//self.view = landscapeView;
[self changeTheViewToPortrait:NO andDuration:duration];
}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------
- (void) changeTheViewToPortrait:(BOOL)portrait andDuration:(NSTimeInterval)duration{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
if(portrait){
//change the view and subview frames for the portrait view
}
else{
//change the view and subview frames for the landscape view
}
[UIView commitAnimations];
}
Hope this helps.
I actually figured out a very simple alternative way around this. Since I am just changing the background image, adding this..
`
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation duration:(NSTimeInterval)duration {
if (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation ==
UIInterfaceOrientationPortraitUpsideDown) {
[brownBackground setImage:[UIImage imageNamed:#"Portrait_Background.png"]];
} else {
[brownBackground setImage:[UIImage imageNamed:#"Landscape_Background.png"]];
}
}
`
Changes the background of a declared UIImageView based on orientation. Only downside is, the current background image is not visible in Interface builder as it is handled with code.
One small addition to Madhup's approach, which is great. I found I needed to add this to viewDidLoad to set initial background image for portrait or landscape:
// set background image
if (self.interfaceOrientation == UIInterfaceOrientationPortrait || self.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"portraitBG.png"]];
} else {
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"landscapeBG.png"]];
}
thanks again Madhup
You can encapsulate this entirely in your UIView by watching whether bounds.width > bounds.height
This may be desirable if you're writing a small, self aware control.
class MyView: UIView {
override func layoutSubviews() {
super.layoutSubviews()
if bounds.height > bounds.width {
println("PORTRAIT. some bounds-impacting event happened")
} else {
println("LANDSCAPE")
}
}
}
Okay, I've got my normal app which is in portrait mode. I can force my app to go to landscape mode for a view (using navigationcontroller and viewcontroller) like this:
- (void)viewWillAppear:(BOOL)animated {
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
}
But then when I go back to the main menu (tableview) it goes straight back to portrait. I try this code:
- (void)viewWillAppear:(BOOL)animated {
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait];
}
But that doesn't work..
Any ideas?
Take a look at the function shouldAutorotateToInterfaceOrientation: in the UIViewController class. This function returns YES if the orientations are supported by your UIView. If you return YES only to the landscape orientation, the iPhone will automatically be put in that orientation.
The following code should do it. Put it in the UIViewController that controls the view that you want to put in landscape mode.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationLandscape);
}
To get this to work, I added this to the rootviewcontroller:
- (void)viewWillAppear:(BOOL)animated {
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait];
}
This seems to be working now.
Here's what I'm doing to do this:
first, put this define at the top of your file, right under your #imports:
#define degreesToRadian(x) (M_PI * (x) / 180.0)
then, in the viewWillAppear: method
[[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO];
if (self.interfaceOrientation == UIInterfaceOrientationPortrait) {
self.view.transform = CGAffineTransformIdentity;
self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
self.view.bounds = CGRectMake(0.0, 0.0, 480, 320);
}
if you want that to be animated, then you can wrap the whole thing in an animation block, like so:
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:1.25];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO];
if (self.interfaceOrientation == UIInterfaceOrientationPortrait) {
self.view.transform = CGAffineTransformIdentity;
self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
self.view.bounds = CGRectMake(0.0, 0.0, 480, 320);
}
[UIView commitAnimations];
Then, in your portrait mode controller, you can do the reverse - check to see if its currently in landscape, and if so, rotate it back to Portrait.
You need to edit your Info.plist file to add the UIInterfaceOrientation key with the appropriate value (UIInterfaceOrientationLandscapeRight or UIInterfaceOrientationLandscapeLeft).
You can't use this private API.
There is a solution to do that : it's to use a view controller and adding its view to the window. then in that controller you force landscape in the shouldAutorotate... methode. It works fine, but be sure it's necessary for your project to use that, because it's not very smart to force the user to turn his iPhone. By the way, here is an example code if you need it.
http://www.geckogeek.fr/iphone-forcer-le-mode-landscape-ou-portrait-en-cours-dexecution.html