I am developing a iphone/ipad app.
Problem is that when i change the orientation of ipad portrait to Landscape, back button of navigation controller stops working.
It"s work fine when orientation not changed.
i am using this code
- (BOOL) isPad{
#ifdef UI_USER_INTERFACE_IDIOM
return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
#else
return NO;
#endif
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
if ([self isPad]) {
return YES;
}
else
{
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
}
What"s the wrong with this code?
This will work :
-(void)viewWillAppear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedRotate:) name:UIDeviceOrientationDidChangeNotification object:nil];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
}
-(void)viewWillDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
}
Now implement the following method :
-(void)checkOrientation
{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if (orientation == UIDeviceOrientationLandscapeLeft||orientation==UIDeviceOrientationLandscapeRight)
{
// Set x coorinate of views you want to change
}
else
{
// Set x coordinates of views to initial x xoordinates.
}
}
Create recievedRotate :
- (void)receivedRotate:(NSNotification *)notification
{
[self checkOrientation];
}
In viewDidLoad :
-(void)viewDidLoad
{
// Code
[self checkOrientation];
}
My guess is that your button is out of the view's frame and thus won't receive touch events. I think something is wrong with the way your app redraws on orientation change.
Related
I am referring to DMD Panorama app.
As you can see there is a Yin-yang symbol at the top section of this image.
Once we rotate our device, the two symbols come closer, like below:
Can you please let me know how do I detect rotation of the device so that when device is rotated, these two images come closer?
I appreciate your response.
Add a notifier in the viewWillAppear function
-(void)viewWillAppear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];}
The orientation change notifies this function
- (void)orientationChanged:(NSNotification *)notification{
[self adjustViewsForOrientation:[[UIApplication sharedApplication] statusBarOrientation]];}
which in-turn calls this function where the moviePlayerController frame is orientation is handled
- (void) adjustViewsForOrientation:(UIInterfaceOrientation) orientation {
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
{
//load the portrait view
}
else if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
{
//load the landscape view
}}
in viewDidDisappear remove the notification
-(void)viewDidDisappear:(BOOL)animated{
[[NSNotificationCenter defaultCenter]removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];}
first you register for notification
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(detectDeviceOrientation) name:UIDeviceOrientationDidChangeNotification object:nil];
then add this method
-(void) detectDeviceOrientation
{
if (([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft) ||
([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight))
{
// Landscape mode
} else if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationPortrait)
{
// portrait mode
}
}
Try doing the following when the application loads or when your view loads:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]
addObserver:self selector:#selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:[UIDevice currentDevice]];
Then add the following method:
- (void) orientationChanged:(NSNotification *)note
{
UIDevice * device = note.object;
switch(device.orientation)
{
case UIDeviceOrientationPortrait:
/* set frames for images */
break;
case UIDeviceOrientationPortraitUpsideDown:
/* set frames for images */
break;
default:
break;
};
}
The above will allow you to register for orientation changes of the device without enabling the autorotate of your view.
I want to keep my view landscape. For that i am using this code but BAD_ACCESS is coming.
Here I am writing this code for camera overlayView.
-(void)viewDidLoad
{
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeLeft];
//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];
[super viewDidLoad];
}
- (void) didRotate:(NSNotification *)notification
{
//Maintain the camera in Landscape orientation
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeLeft];
}
Why it is giving BAD ACCESS ?
To keep your view landscape, just return NO in your shouldAutorotateToInterfaceOrientation: method for portrait orientations, like tihs :
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
I have an interface that I want to startup in landscape orientation. After startup when the user rotates the device to portrait I am displaying a day view calendar. When returning to landscape orientation the calendar is dismissed. Everything works great in every orientation with my application user interface displaying properly in landscape orientation and the calendar displaying properly in portrait orientation.
The problem is if the user is holding the iPhone in landscape orientation on startup. No matter what I do I cannot get it to startup with my user interface in landscape mode. My UIDeviceOrientationDidChangeNotification method fires twice, the first time [UIDevice currentDevice].orientation is landscape, the second in it is portrait. The end result is the the user interface rotates to portrait mode and displays the day view. Not what I want. I want the user interface to stay in landscape orientation until the user physically rotates the device from landscape to portrait.
I don't understand why it fires with a landscape [UIDevice currentDevice].orientation when the user is holding the device in portrait orientation.
Here is what my code looks like in the viewController...
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if ((interfaceOrientation == UIDeviceOrientationPortrait)|| (interfaceOrientation == UIDeviceOrientationPortraitUpsideDown)) {
return NO;
}
return YES;
}
- (void)viewDidLoad {
[super viewDidLoad];
showingCalendar = NO;
initializing=YES;
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didRotate:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
}
-(void)didRotate:(NSNotification *)notification {
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if ((deviceOrientation == UIDeviceOrientationPortrait) || (deviceOrientation == UIDeviceOrientationPortraitUpsideDown)) {
if ((!showingCalendar) && (!initializing)) {
showingCalendar = YES;
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:YES];
GCCalendarPortraitView *calendar = [[[GCCalendarPortraitView alloc] init] autorelease];
navigationController = [[UINavigationController alloc] initWithRootViewController:calendar];
[self presentModalViewController:navigationController animated:YES];
}
}else if ((deviceOrientation == UIDeviceOrientationLandscapeRight) || (deviceOrientation == UIDeviceOrientationLandscapeLeft)) {
if (showingCalendar) {
showingCalendar = NO;
if (deviceOrientation == UIDeviceOrientationLandscapeRight){
[self dismissModalViewControllerAnimated:YES];
}else if (deviceOrientation == UIDeviceOrientationLandscapeLeft){
[self dismissModalViewControllerAnimated:YES];
}
}else {
initializing = NO;
}
}
}
I found a workaround to my problem. In viewDidLoad I started a scheduledTimerWithTimeInterval and moved beginGeneratingDeviceOrientationNotifications to the selector method.
Now the notification never fires more than once. The user gets landscape at startup no matter which way the device is being held and after startup all the rotations work perfectly.
Here is my modified code. Everything else stayed the same...
- (void)viewDidLoad {
[super viewDidLoad];
showingCalendar = NO;
initializing=YES;
timer = [NSTimer scheduledTimerWithTimeInterval:.55 target:self selector:#selector(startOrientationNotifications) userInfo:nil repeats: NO];
}
-(void)startOrientationNotifications {
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didRotate:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
}
i wouldn't generate a beginGeneratingDeviceOrientationNotifications,
a simple way could be to use a BOOL to check when portrait is allowed in
shouldAutorotateToInterfaceOrientation
something like this:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if ((interfaceOrientation == UIDeviceOrientationPortrait)|| (interfaceOrientation == UIDeviceOrientationPortraitUpsideDown)) {
return portraitIsAllowed;
}
return YES;
}
then just change it when needed in other methods .
And keep in mind that shouldAutorotateToInterfaceOrientation is called every time user rotate device AND also when you load (instantiate) your controller the first time
What would be the correct way to achieve an effect similar to the one in the standard iPod app of the iPhone - when the device is rotated to landscape mode, the view changes to cover flow, but the type of transition is fade and not the rotating screen?
This is how I am loading the modal view:
- (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
carouselView.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:carouselView animated:YES];
}
}
Thanks!
Andrius
I later found that it is more stable to use this solution:
In the parent view controller (in my case it is tab view controller) viewdidload method add this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didRotate:) name:#"UIDeviceOrientationDidChangeNotification" object:nil];
and then add this method:
- (void) didRotate:(NSNotification *)notification {
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if (UIInterfaceOrientationIsLandscape(orientation) && !self.modalViewController) {
[self presentModalViewController:carouselView animated:YES];
[Globals sharedGlobals].startedAtLandscape = YES;
}
if (UIInterfaceOrientationIsPortrait(orientation) && self.modalViewController) {
[self dismissModalViewControllerAnimated:YES];
[Globals sharedGlobals].startedAtLandscape = NO;
}
}
And finally if you want to prevent the rotation animation, modify this method like this:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if(UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
return NO;
}
return YES;
}
I had a table populated with rows and each row contain image, title and a button.
When user change the orientation of the iPad button should be rearrange according to the orientation of iPad. Please advice me how to rearrange the object in uitableview cell.
Thanks in advance.
This will work :
-(void)viewWillAppear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedRotate:) name:UIDeviceOrientationDidChangeNotification object:nil];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
}
-(void)viewWillDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
}
Now implement the following method :
-(void)checkOrientation
{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if (orientation == UIDeviceOrientationLandscapeLeft||orientation==UIDeviceOrientationLandscapeRight)
{
[tblView reloadData];
// Set x coorinate of views you want to change
}
else
{
[tblView reloadData];
// Set x coordinates of views to initial x xoordinates.
}
}
Create recievedRotate :
- (void)receivedRotate:(NSNotification *)notification
{
[self checkOrientation];
}
In viewDidLoad :
-(void)viewDidLoad
{
[self checkOrientation];
}