Orientation in a UIView added to a UIWindow

心已入冬 提交于 2019-12-27 16:23:19

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!