Open Stokestack opened 13 years ago
Works without pain in my projects. Probably the problem is the view stack in your project and a parent view controller prevents the interface rotation?
Based on what I'm seeing in forums, it looks like a major iOS/SDK problem. A great many apps use a tab-bar controller, and rotation doesn't work when your controller stack starts on one of those.
So I implemented the workaround, which was to make my EGOPhotoViewController subclass register for UIDeviceOrientationDidChangeNotification. When I get a notification, I execute all the logic contained in EGOPhotoViewController's rotation-related methods:
willRotateToInterfaceOrientation willAnimateRotationToInterfaceOrientation didRotateFromInterfaceOrientation
Nothing happens. The view doesn't rotate.
Looking at EGOPhotoImageView's layoutViewAnimated method, I can see in the demo project that self.frame.size reflects the new orientation of the device. That's not true in my project; it still shows 320 x 480 in landscape mode. Does anyone know where the view's frame dimensions get changed after rotation? This will help me track down the origin of the failure.
Stokestack, did you fix the issue with autorotation? If yes, please let me know what you did. Regards.
I did. In fact, I tried it in two ways. Initially, I went into every view controller that was in the navigation controller's stack, and implemented shouldAutorotateToInterfaceOrientation. You have to do this because Cocoa will poll every single one of them, and if even one returns NO, the UI won't rotate. This is because if one of them says YES, but the previous one says NO, what will happen when you press the Back button on the rotated screen and go back to one that can't be rotated? This is what Apple wanted to avoid.
I eventually decided that some of our screens didn't look good in landscape. It also introduced a couple of bugs that required more troubleshooting and testing, and it stretched out our custom navbar title in landscape mode. So I wanted only the single-picture screen to rotate, which EGO does not support. I accomplished it by having all the view controllers in my navigation controller's stack return NO to rotation unless the EGO single-photo display was on top.
Here's the code to put in the other view controllers in the navigation stack, to allow rotation only if the single-photo screen is up:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
UIViewController* tabView = theApp.tabBarController.selectedViewController;
if([tabView isKindOfClass:[UINavigationController class]])
{
UINavigationController* navController = (UINavigationController*)tabView;
UIViewController* visibleView = [navController visibleViewController];
if(visibleView)
{
if([visibleView isKindOfClass:[EGOPhotoViewController class]])
{
return (UIInterfaceOrientationIsLandscape(interfaceOrientation) || interfaceOrientation == UIInterfaceOrientationPortrait);
}
else
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
}
else
{
return (UIInterfaceOrientationIsLandscape(interfaceOrientation) || interfaceOrientation == UIInterfaceOrientationPortrait);
}
}
else
{
return interfaceOrientation == UIInterfaceOrientationPortrait;
}
}
But that's not all: Because of the above-mentioned problem (you don't want the user to press Back on a rotated screen and go back to a screen that can't be rotated), I derived a class from EGOPhotoViewController and changed the layout logic in the EGO photo viewer to disable (or eliminate) the Back button when it goes into landscape mode.
Unfortunately, this doesn't work because of a Cocoa bug (Radar 9611632; The Back button reappears after hiding.). So my only choice was to disable the entire navbar when in landscape orientation. Here's how to do it in your EGOPhotoViewController derivative (notice that I've added a bool property, landscapeMode, to the class to keep track of our orientation):
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromOrientation
{
[super didRotateFromInterfaceOrientation:fromOrientation];
if(UIInterfaceOrientationIsLandscape(fromOrientation))
{
// We're now in portrait mode.
self.landscapeMode = NO;
}
else
{
self.landscapeMode = YES;
[self.navigationController setNavigationBarHidden:YES animated:NO];
}
// Revise toolbar items to control the presence of the Delete button.
// It must be removed in landscape mode, to prevent being dumped back into the thumbnail view
// in landscape mode (which we don't currently allow).
[self setToolbarItems:[self photoToolbarItems]];
}
We also need to override this to accomplish the hiding of the navigation bar:
- (void)setBarsHidden:(BOOL)hidden
{
if(hidden)
{
[super hideCaption];
[super setBarsHidden:hidden];
}
else
{
[super showCaption];
[super resetTimerForBars];
[super setStatusBarHidden:NO withAnimation:YES];
if(!self.landscapeMode)
{
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
[self.navigationController setToolbarHidden:NO animated:YES];
}
}
Finally, you may want to override photoToolbarItems, to present different toolbar items if you're in landscape mode.
Hope that helps!
Thanks for this very nice explanation! Now i will try to apply your tip. Thank you very much.
Is anybody having issues with rotating to landscape and then not being able to scroll to certain images? In particular I select a photo to view it as a single photo, when I rotate the landscape I am unable to scroll to other photos.
I fix this by rotating back to portrait and then scrolling as normal.
EGOPhotoViewController's shouldAutorotateToInterfaceOrientation gets called and returns YES, but none of the other rotation-related methods (including willRotateToInterfaceOrientation) gets called.
This could be an iOS SDK problem, but it's a pretty major crippling of the viewer's functionality.