【问题标题】:How to create an App using the Single View App template where the main window does not rotate but the rest does?如何使用单视图应用程序模板创建主窗口不旋转但其余部分旋转的应用程序?
【发布时间】:2017-03-12 19:55:56
【问题描述】:

如何使用 Single View App 模板创建主窗口不旋转但其 rootViewController 和其他所有内容自动旋转的应用程序?

Apple 在CIFunHouse 上做到了这一点,但由于代码在这方面的解释很差,因此不可能知道他们是如何做到的。如果您运行该应用程序,您将看到相机的预览窗口不会自动旋转,因为预览已添加到窗口中,但其他所有内容都会自动旋转。

Apple 在其原生 iPad 相机应用程序中使用了这种技术。

【问题讨论】:

    标签: ios camera avfoundation uiwindow autorotate


    【解决方案1】:

    所以答案不干净,但我可以给你一个修复。在某些时候,主应用程序窗口不能像现在那样自动旋转,但在某些时候它开始根据 rootviewcontroller 旋转。至少这个源代码表明了这一点。我在 iOS 6 结束时开始开发,我认为这个源代码是关于那个时候写的。对于我来说,允许在示例中旋转但预览不旋转的最佳解决方法是添加第二个窗口。将主窗口背景设置为清除。然后将 previewLayer 添加到主窗口后面的第二个窗口。在代码中它看起来像这样。

    AppDelegate 看起来像这样。

    #import <UIKit/UIKit.h>
    #import <CoreMotion/CoreMotion.h>
    
    @interface FHAppDelegate : UIResponder <UIApplicationDelegate>
    {
    @private
      CMMotionManager *_motionManager;
    }
    @property (strong, readonly, nonatomic) CMMotionManager *motionManager;
    //future preview window
    @property (strong, nonatomic) UIWindow *previewWindow;
    @property (assign, readonly, nonatomic) UIDeviceOrientation realDeviceOrientation;
    
    @end
    

    然后在 FHViewController 的 viewDidLoad 中而不是添加到主窗口中,我这样做了,它添加了他们获得主窗口的位置,我将 previewView 添加到那里。

       // we make our video preview view a subview of the window, and send it to the back; this makes FHViewController's view (and its UI elements) on top of the video preview, and also makes video preview unaffected by device rotation
       //nothing special about this viewcontorller except it has
       //-(BOOL)shouldAutorotate{
       //return NO;
       //}
    
        TestViewController *test = [[TestViewController alloc]initWithNibName:@"TestViewController" bundle:nil];
        FHAppDelegate *delegate = ((FHAppDelegate *)[UIApplication sharedApplication].delegate);
        delegate.previewWindow = [[UIWindow alloc]initWithFrame:window.bounds];
        UIWindow *previewWindow = delegate.previewWindow;
        [window setBackgroundColor:[UIColor clearColor]];
    
        previewWindow.rootViewController = test;
        previewWindow.windowLevel = UIWindowLevelNormal - 1;
    
        [previewWindow setBounds:delegate.window.bounds];
    
        [previewWindow makeKeyAndVisible];
        [previewWindow addSubview:_videoPreviewView];
        [previewWindow sendSubviewToBack:_videoPreviewView];
    

    因为 previewWindow 必须有一个 rootviewcontroller 并且它决定了旋转,所以你可以看到我的 testviewcontroller 的自动旋转为 NO。希望这可以帮助。它在 iOS 10 上为我工作。

    编辑:上面示例中的视图不旋转,但旋转时的窗口动画在视觉上很糟糕。它可以通过覆盖来删除 willTransitionToSize

        [UIView setAnimationsEnabled:NO];
    

    完成后

    [UIView setAnimationsEnabled:YES];
    

    GitHub上查看快速版本

    对于 iPad,必须选中全屏。

    【讨论】:

    • 子视图没有旋转。窗口内的容器旋转。你想要的结果是什么。您只是不想看到容器旋转还是希望子视图旋转。您可以清楚地看到标签不旋转标签顶部将是您旋转设备的任何方式
    • 好吧,CIFunHouse 不为我这样做,所以我不知道你编译的版本是什么。我的剪辑子视图并旋转它们。
    • 我认为在过渡期间现在意味着当前 API 添加了一个容器视图来处理过渡。我尝试设置该容器以清除删除剪辑和图层蒙版。我知道容器不包含不旋转的窗口。但是它要么掩盖了下面是我们的非旋转窗口的图层,要么将其覆盖了。
    • 老实说,我唯一没有尝试过的是将非旋转窗口放在容器内并完全相反的方向旋转
    • 再次更新了github。看看吧
    【解决方案2】:

    通过使用导航控制器,您可以创建类似的 Objective-C 类别并在子视图控制器中使用它们

    #import "UINavigationController+Orientation.h"
    
    @implementation UINavigationController (Orientation)
    
    - (NSUInteger)supportedInterfaceOrientations {
        return [self.topViewController supportedInterfaceOrientations];
    }
    
    - (BOOL)shouldAutorotate {
        return YES;
    }
    
    @end
    

    对于斯威夫特

    extension UINavigationController {
    
        open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
            return topViewController?.supportedInterfaceOrientations ?? .portrait
        }
    
        open override var shouldAutorotate: Bool {
            return true
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-21
      • 1970-01-01
      • 2011-06-28
      • 2012-12-27
      • 1970-01-01
      相关资源
      最近更新 更多