问题
I have a UIView which is supposed to cover the whole device (UIWindow) to support an image zoom in/out effect I'm doing using core animation where a user taps a button on a UITableViewCell and I zoom the associated image.
The zooming is performing flawlessly, what I haven't been able to figure out is why the subview is still in portrait mode even though the device is in landscape. An illustration below:
I do have a navigation controller but this view has been added to the UIWindow directly.
回答1:
You can read about some of the possible causes here:
Technical Q&A QA1688 - Why won't my UIViewController rotate with the device?
In your situation its probably the fact that you are adding the view as another subview to the window. Only the first subview gets the rotation events. What you can do is add it as a subview of the first window subview.
UIWindow* window = [UIApplication sharedApplication].keyWindow;
if (!window)
window = [[UIApplication sharedApplication].windows objectAtIndex:0];
[[[window subviews] objectAtIndex:0] addSubview:myView];
回答2:
The problem
Beginning with iOS 6, only the topmost view controller (alongside the UIApplication object) participates in deciding whether to rotate in response to a change of the device's orientation.
https://developer.apple.com/library/content/qa/qa1688/_index.html
The solution
I have open sourced a pod named AGWindowView.
It will automatically deal with any rotation and framechanges so you won't have to worry about that.
The code
It supports any combination of SDK's and iOS system versions. The relevant code can be found here: https://github.com/hfossli/AGWindowView/blob/master/Source/AGWindowView.m
回答3:
I created a category on UIApplication that has a helper property and method for getting the first subview of the keyWindow. This is the view you want to overlay anyway. Now when you add a view that is managed by a UIViewController to that view, the shouldRotateToInterfaceOrientation: method is called.
UIApplication+WindowOverlay.h
#import <UIKit/UIKit.h>
@interface UIApplication(WindowOverlay)
@property (nonatomic, readonly) UIView *baseWindowView;
-(void)addWindowOverlay:(UIView *)view;
@end
UIApplication+WindowOverlay.m
#import "UIApplication+WindowOverlay.h"
@implementation UIApplication(WindowOverlay)
-(UIView *)baseWindowView{
if (self.keyWindow.subviews.count > 0){
return [self.keyWindow.subviews objectAtIndex:0];
}
return nil;
}
-(void)addWindowOverlay:(UIView *)view{
[self.baseWindowView addSubview:view];
}
@end
and here is how you would use it.
//at the top of the file...or in {yourproject}.pch
#import "UIApplication+WindowOverlay.h
//in a method:
UIView *view = [UIView new];
UIView *window = [UIApplication sharedApplication].baseWindowView;
view.frame = window.bounds;
[window addSubview:view];
//or
[[UIApplication sharedApplication] addWindowOverlay:view];
回答4:
This is because as you mention your view has been added directly to the UIWindow, therefore when the method to rotate is called for the navigation controller nothing happens to the uiview. The UIView would rotate if it was a subview of the view controller view. If for some reason this cannot be done. Then you could override this method:
// This method is called every time the device changes orientation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
}
And every time your orientation changes also change your view orientation.
回答5:
I had a similar problem with views being added directly to a window. Maybe this will help: Automatically Sizing UIView after Adding to Window
回答6:
Another solution how I solved this problem.
Define the current Orientation:
@interface AJImageCollectionViewController (){
UIInterfaceOrientation _currentOrientation;
}
@end
Then check the orientation in the viewWillLayoutSubviews:
- (void)viewWillLayoutSubviews {
[self checkIfOrientationChanged];
}
- (void)checkIfOrientationChanged {
UIInterfaceOrientation newOrientation = [[UIApplication sharedApplication] statusBarOrientation];
BOOL newOrientationIsPortrait = UIInterfaceOrientationIsPortrait(newOrientation);
BOOL oldOrientationIsPortrait = UIInterfaceOrientationIsPortrait(_currentOrientation);
// Check if the orientation is the same as the current
if(newOrientationIsPortrait != oldOrientationIsPortrait){
_currentOrientation = newOrientation;
// Do some stuff with the new orientation
}
}
来源:https://stackoverflow.com/questions/2508630/orientation-in-a-uiview-added-to-a-uiwindow