简体   繁体   中英

How do I prevent UIWindow view from autorotating

I have a UIViewController, called OoviumController that responds to device rotations. OoviumController is my app's UIWindow rootViewController. The UIWindow also is it's own view. OoviumController's view is transparent and sits on top of the UIWindow view which should not rotate.

From iOS 2 through iOS 7, this all worked fine. However, I am trying to build my project using XCode 6 for iOS 8 and I have noticed that now in addition to OoviumController's view, the UIWindow view is also rotating, which is causing serious problems in my app.

How do I return the functionality to the way it worked previously? How do I prevent the UIWindow from rotating along with my rootViewController's view?

I have also noticed that the UIWindow documentation no longer lists it as inheriting UIView, even though addSubview seems to still work. Is this a documentation bug or is the public inheritance of UIView being deprecated?

I have not found a quick, easy or elegant solution to this problem. I have however found a tedious brute force solution. I worked on this months ago and actually don't think I'm totally finished. However, I'm going to post the basic frame work for anyone interested.

The basic concept is create two UIWindow objects, one that rotates and one that does not. Then before the rotation starts to flip all the controls from the rotating window to the non-rotating window. After the rotation completes to flip them back:

- (void) hideHovers {
    for (Hover* hover in self.hovers)
        hover.alpha = 0;
}
- (void) showHovers {
    for (Hover* hover in self.hovers)
        hover.alpha = 1;
}

// Public ==========================================================================================
- (void) addHover:(Hover*)hover {
    [[Oovium aetherWindow] addSubview:hover];
    [self.hovers addObject:hover];
}

- (void) beforeRotation {
    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
    for (Hover* hover in self.hovers) {
        hover.orientation = orientation;
        [hover removeFromSuperview];
        [controlWindow_ addSubview:hover];
    }
    controlWindow_.hidden = NO;
    [self showHovers];
    [UIView animateWithDuration:0.5 animations:^{
        [self hideHovers];
    }];
}
- (void) afterRotation {
    for (Hover* hover in self.hovers) {
        hover.transform = CGAffineTransformIdentity;
        [hover removeFromSuperview];
        [[Oovium aetherWindow] addSubview:hover];
        [hover place];
    }
    controlWindow_.hidden = YES;
    [UIView animateWithDuration:0.5 animations:^{
        [self showHovers];
    }];
}

Actually, that is the easy part. The difficult part is handling the transformation of the controls. The code below is not entirely working for all rotations. I will amend it when I complete it, but I'm not sure when I'll be able to get back to it.

//
//  Hover.m
//  Oovium
//
//  Created by Joe Charlier on 2/22/15.
//  Copyright (c) 2015 Aepryus Software. All rights reserved.
//

#import "Controls.h"
#import "Hover.h"
#import "Oovium.h"
#import "Utility.h"

@interface Hover ()

@property (nonatomic) OOAnchor anchor;
@property (nonatomic) CGPoint offset;
@property (nonatomic) CGSize size;

@end

@implementation Hover

// Static ==========================================================================================
static CGPoint points_[5][5];
static CGPoint shift_[5];

+ (void) initialize {
    CGFloat width = [Utility deviceBounds].size.width;
    CGFloat height = [Utility deviceBounds].size.height;

    CGPoint topLeft = CGPointMake(0,0);
    CGPoint topRight = CGPointMake(width,0);
    CGPoint bottomLeft = CGPointMake(0,height);
    CGPoint bottomRight = CGPointMake(width,height);
    CGPoint center = CGPointMake(width/2,height/2);

    points_[UIInterfaceOrientationPortrait][OOAnchorTopLeft] = topLeft;
    points_[UIInterfaceOrientationPortrait][OOAnchorTopRight] = topRight;
    points_[UIInterfaceOrientationPortrait][OOAnchorBottomLeft] = bottomLeft;
    points_[UIInterfaceOrientationPortrait][OOAnchorBottomRight] = bottomRight;
    points_[UIInterfaceOrientationPortrait][OOAnchorCenter] = center;

    points_[UIInterfaceOrientationLandscapeRight][OOAnchorTopLeft] = topRight;
    points_[UIInterfaceOrientationLandscapeRight][OOAnchorTopRight] = bottomRight;
    points_[UIInterfaceOrientationLandscapeRight][OOAnchorBottomLeft] = topLeft;
    points_[UIInterfaceOrientationLandscapeRight][OOAnchorBottomRight] = bottomLeft;
    points_[UIInterfaceOrientationLandscapeRight][OOAnchorCenter] = center;

    points_[UIInterfaceOrientationPortraitUpsideDown][OOAnchorTopLeft] = bottomRight;
    points_[UIInterfaceOrientationPortraitUpsideDown][OOAnchorTopRight] = bottomLeft;
    points_[UIInterfaceOrientationPortraitUpsideDown][OOAnchorBottomLeft] = topRight;
    points_[UIInterfaceOrientationPortraitUpsideDown][OOAnchorBottomRight] = topLeft;
    points_[UIInterfaceOrientationPortraitUpsideDown][OOAnchorCenter] = center;

    points_[UIInterfaceOrientationLandscapeLeft][OOAnchorTopLeft] = bottomLeft;
    points_[UIInterfaceOrientationLandscapeLeft][OOAnchorTopRight] = topLeft;
    points_[UIInterfaceOrientationLandscapeLeft][OOAnchorBottomLeft] = bottomRight;
    points_[UIInterfaceOrientationLandscapeLeft][OOAnchorBottomRight] = topRight;
    points_[UIInterfaceOrientationLandscapeLeft][OOAnchorCenter] = center;

    shift_[OOAnchorTopLeft] = CGPointMake(0, 0);
    shift_[OOAnchorTopRight] = CGPointMake(1, 0);
    shift_[OOAnchorBottomLeft] = CGPointMake(0, 1);
    shift_[OOAnchorBottomRight] = CGPointMake(1, 1);
    shift_[OOAnchorCenter] = CGPointMake(0.5, 0.5);
}
// =================================================================================================

+ (CGRect) placeInRect:(CGRect)rect anchor:(OOAnchor)anchor offset:(CGPoint)offset size:(CGSize)size {
    CGPoint shift = shift_[anchor];
    CGFloat x = shift.x*(rect.size.width-size.width)+offset.x;
    CGFloat y = shift.y*(rect.size.height-size.height)+offset.y;
    return CGRectMake(x, y, size.width, size.height);
}

- (id) initWithAnchor:(OOAnchor)anchor offset:(CGPoint)offset size:(CGSize)size {
    if (self = [super initWithFrame:[Hover placeInRect:[UIScreen mainScreen].bounds anchor:anchor offset:offset size:size]]) {
        self.anchor = anchor;
        self.offset = offset;
        self.size = size;
        self.backgroundColor = [UIColor purpleColor];
    }
    return self;
}

- (void) setOrientation:(UIInterfaceOrientation)orientation {
    _orientation = orientation;

    CGPoint aO = self.frame.origin;
    CGPoint aN = points_[orientation][_anchor];

    double w = self.size.width;
    double h = self.size.height;
    double q = (self.size.height-self.size.width)/2;
    double ox = self.offset.x;
    double oy = self.offset.y;
    double ax = aN.x-aO.x;
    double ay = aN.y-aO.y;

    double dx=0;
    double dy=0;
    if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) {
        dx += q;
        dy += q;
    }
    switch (orientation) {
        case UIInterfaceOrientationPortrait:
            dx = 0;
            dy = 0;
            break;
        case UIInterfaceOrientationPortraitUpsideDown:
            switch (_anchor) {
                case OOAnchorTopLeft:
                    dx += -ax+w+ox;
                    dy += -ay+h+oy;
                    break;
                case OOAnchorTopRight:
                    dx += -ax+ox;
                    dy += -ay+h+oy;
                    break;
                case OOAnchorBottomLeft:
                    dx += -ax+w+ox;
                    dy += -ay+oy;
                    break;
                case OOAnchorBottomRight:
                    dx += -ax+ox;
                    dy += -ay+oy;
                    break;
            }
            break;
        case UIInterfaceOrientationLandscapeRight:
            switch (_anchor) {
                case OOAnchorTopLeft:
                    dx += 0;
                    dy += ax-h-ox;
                    break;
                case OOAnchorTopRight:
                    dx += -ay+w+oy;
                    dy += ax-h+ox;
                    break;
                case OOAnchorBottomLeft:
                    dx += -ay+oy;
                    dy += 0;
                    break;
                case OOAnchorBottomRight:
                    dx += -ay+w-oy;
                    dy += ax-ox;
                    break;
            }
            break;
        case UIInterfaceOrientationLandscapeLeft:
            switch (_anchor) {
                case OOAnchorTopLeft:
                    dx += ay-h-oy;
                    dy += -w;
                    break;
                case OOAnchorTopRight:
                    dx += -w;
                    dy += -ax-w-ox;
                    break;
                case OOAnchorBottomLeft:
                    dx += ay-h+oy;
                    dy += -ay-h;
                    break;
                case OOAnchorBottomRight:
                    dx += ay-w-oy;
                    dy += -ax+w-ox;
                    break;
            }
            break;
    }

    CGFloat angle = 0;
    switch (orientation) {
        case UIInterfaceOrientationPortrait:            angle = 0;          break;
        case UIInterfaceOrientationLandscapeRight:      angle = M_PI_2*3;   break;
        case UIInterfaceOrientationPortraitUpsideDown:  angle = M_PI;       break;
        case UIInterfaceOrientationLandscapeLeft:       angle = M_PI_2;     break;
        case UIInterfaceOrientationUnknown:break;
    }

    [self setTransform:CGAffineTransformConcat(
        CGAffineTransformMakeTranslation(dx,dy),
        CGAffineTransformMakeRotation(angle)
     )];
}

- (void) invoke {
    [[Oovium controls] invoke:self];
}

- (void) place {
    CGSize sz = [UIScreen mainScreen].bounds.size;
    CGPoint shift = shift_[self.anchor];
    CGFloat x = shift.x*(sz.width-self.size.width)+self.offset.x;
    CGFloat y = shift.y*(sz.height-self.size.height)+self.offset.y;
    self.frame = CGRectMake(x, y, self.size.width, self.size.height);
}

@end

I recently felt the urge to block rotations for an additional app window and now found the solution...

Since iOS 6 the UIApplicationDelegate supports the following method:

- (UIInterfaceOrientationMask)application:(UIApplication *)application 
  supportedInterfaceOrientationsForWindow:(UIWindow *)window;

Here you return the allowed orientations for the window and don't have to deal with hacks that revert rotations the system did.

https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623107-application?language=objc

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM