【问题标题】:How do I prevent UIWindow view from autorotating如何防止 UIWindow 视图自动旋转
【发布时间】:2014-11-27 18:17:07
【问题描述】:

我有一个 UIViewController,称为 OoviumController,它响应设备旋转。 OoviumController 是我应用的 UIWindow rootViewController。 UIWindow 也是它自己的视图。 OoviumController 的视图是透明的,位于不应旋转的 UIWindow 视图之上。

从 iOS 2 到 iOS 7,这一切都运行良好。但是,我正在尝试使用适用于 iOS 8 的 XCode 6 构建我的项目,我注意到现在除了 OoviumController 的视图之外,UIWindow 视图也在旋转,这在我的应用程序中造成了严重的问题。

如何将功能恢复到以前的工作方式?如何防止 UIWindow 与我的 rootViewController 的视图一起旋转?

我还注意到 UIWindow 文档不再将其列为继承 UIView,即使 addSubview 似乎仍然有效。这是文档错误还是 UIView 的公共继承已被弃用?

【问题讨论】:

  • 你知道如何实现这个吗?
  • @theReverend 不幸的是,我没有找到一个简单的方法来做到这一点。然而,我创建了一个蛮力机制来处理这个问题,通过在顶部创建第二个 UIWindow 并在旋转期间将控件翻转到那个,然后在旋转完成时翻转回来。我的时间有点紧张,但我会尝试在今晚的答案中发布基础知识。
  • @theReverend 对不起,我忘记了你。我刚刚发布了一些我几个月前工作的代码。在测试它时,我注意到我还没有完全完成我正在做的事情,而且还有一些怪癖。

标签: ios objective-c cocoa-touch uiwindow autorotate


【解决方案1】:

我还没有找到一个快速、简单或优雅的解决方案来解决这个问题。然而,我找到了一个乏味的蛮力解决方案。我几个月前就开始工作了,实际上我认为我还没有完全完成。不过,我会为所有感兴趣的人发布基本框架。

基本概念是创建两个 UIWindow 对象,一个旋转,一个不旋转。然后在旋转开始之前将所有控件从旋转窗口翻转到非旋转窗口。旋转完成后将它们翻转回来:

- (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];
    }];
}

实际上,这很容易。困难的部分是处理控件的转换。下面的代码并不完全适用于所有旋转。完成后我会修改它,但我不确定什么时候可以恢复。

//
//  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

【讨论】:

    【解决方案2】:

    我最近有阻止旋转以获取额外应用程序窗口的冲动,现在找到了解决方案...

    从 iOS 6 开始,UIApplicationDelegate 支持以下方法:

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

    您可以在此处返回允许的窗口方向,而不必处理恢复系统所做旋转的黑客行为。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-31
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多