如何只允许单个UIViewController沿横向和纵向旋转?

2020/11/28 12:12 · ios ·  · 0评论

我的应用仅适用于iphone设备(iphone 4和5),并且仅支持ios 6

我的整个应用仅支持portrait模式。但是有一个名为“ ChatView”的视图,我想同时支持landscapeportrait模式。

我已将所需的设备旋转设置如下:

在此处输入图片说明

我还尝试了以下代码来支持“ ChatView”中的旋转-

-(BOOL)shouldAutorotate
{
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskLandscape;
}

但是它无法旋转该视图。

我为此进行了很多搜索,但找不到我的问题的解决方案。

而且在“ ChatView”中还有一些对象,例如按钮,文本字段,其框架是通过编程方式设置的。所以我想知道是否也必须为横向模式设置所有这些对象的框架?

请帮我。

谢谢.....

我想如果您只想支持一个viewcontroller旋转,那是不可能的,因为应用程序将遵循您在.plist文件中设置的方向您可以采用的替代方法是同时为横向和纵向支持您的应用,将除聊天视图以外的所有ViewController旋转冻结为纵向。

编辑

要进行子类化UINavigationController,请创建一个名称为eg的新文件,CustomNavigationController并将其设为子类UINavigationController

.h文件

#import <UIKit/UIKit.h>

@interface CustomNavigationController : UINavigationController

@end

.m文件

#import "CustomNavigationController.h"

@interface CustomNavigationController ()

@end


@implementation CustomNavigationController

-(BOOL)shouldAutorotate
{
    return NO;
}

-(UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAll;
}


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}

@end

UINavigationController您的主班级xib中的班级设置为CustomNavigationController希望对你有帮助。

很简单,但是效果很好。iOS 7.1和8

AppDelegate.h

@property () BOOL restrictRotation;

AppDelegate.m

-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if(self.restrictRotation)
    return UIInterfaceOrientationMaskPortrait;
else
    return UIInterfaceOrientationMaskAll;
}

ViewController

-(void) restrictRotation:(BOOL) restriction
{
    AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
    appDelegate.restrictRotation = restriction;
}

viewDidLoad

[self restrictRotation:YES]; or NO

您的视图控制器将永远不会旋转到应用程序本身不支持的任何位置。您应该启用所有可能的旋转,然后在不应旋转的视图控制器中放入以下行

- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

在ChatView中,应为:

- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAll;
}

如果您需要在轮换之后更改布局,则应对子视图进行适当的更改

- (void)viewWillLayoutSubviews

使用self.view.bounds检查的电流的大小view,因为self.view.frame旋转后也不会改变。

针对viewcontroller.m您要旋转的特定对象

添加此方法:

- (BOOL)canAutoRotate
{
    return YES;
}

然后在你的 AppDelegate.m

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    UIViewController *currentViewController = [self topViewController];

    if ([currentViewController respondsToSelector:@selector(canAutoRotate)]) {
        NSMethodSignature *signature = [currentViewController methodSignatureForSelector:@selector(canAutoRotate)];

        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];

        [invocation setSelector:@selector(canAutoRotate)];
        [invocation setTarget:currentViewController];

        [invocation invoke];

        BOOL canAutorotate = NO;
        [invocation getReturnValue:&canAutorotate];

        if (canAutorotate) {
            return UIInterfaceOrientationMaskAll;
        }
    }

    return UIInterfaceOrientationMaskPortrait;
}

- (UIViewController *)topViewController
{
    return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}

- (UIViewController *)topViewControllerWithRootViewController:(UIViewController *)rootViewController
{
    if ([rootViewController isKindOfClass:[UITabBarController class]]) {
        UITabBarController* tabBarController = (UITabBarController*)rootViewController;
        return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
    } else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
        UINavigationController* navigationController = (UINavigationController*)rootViewController;
        return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
    } else if (rootViewController.presentedViewController) {
        UIViewController* presentedViewController = rootViewController.presentedViewController;
        return [self topViewControllerWithRootViewController:presentedViewController];
    } else {
        return rootViewController;
    }
}

泰德(Ted)的答案与挪威亚历山大(Alexander of Norway)提到的问题非常吻合。但是我认为问题并没有像亚历山大解释的那样发生,

当当前处于横向(启用所有方向)的ViewController B返回到ViewControllerA。(仅纵向)在用户单击“后退”按钮后,不会调用supportInterfaceOrientationsForWindow,并且ViewController A最终进入横向

实际上,当用户单击后退按钮后,当前处于横向(启用所有方向)的ViewController B返回到ViewController A(仅纵向)时,Appdelegate

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;

正在被呼叫。但是根视图控制器仍然是ViewController B(启用旋转的视图控制器),由于ViewController B仍在返回,因此ViewController A不会恢复为纵向方向

-(BOOL)shouldAutorotate{

    return YES;
}

因此,当您按下返回按钮返回时,ViewController B中的“ shouldAutorotate-> NO”。然后ViewController A将变为纵向。这就是我所做的

@property (nonatomic, assign) BOOL canAutoRotate;

#pragma mark - Public methods
- (BOOL)canAutoRotate
{
    return _canAutoRotate;
}

#pragma mark - Button actions
- (void)backButtonPressed:(UIButton *)sender {
    _canAutoRotate = NO;
   (...)
}

#pragma mark - Init
- (id)init{
    if(self=[super init]) {
        _canAutoRotate = YES;
    }
    return self;
}

Swift 3犹太版本

我将其留在这里只是为了解决有人遇到的问题。

苹果的文档supportedInterfaceOrientations说:

当用户更改设备方向时,系统在填充窗口的根视图控制器或显示在最上方的视图控制器上调用此方法。如果视图控制器支持新的方向,则将窗口和视图控制器旋转到新的方向。仅当视图控制器的shouldAutorotate方法返回true时,才调用此方法。

简而言之,您必须supportedInterfaceOrientations在根视图控制器中重写,以便它返回其顶级子视图控制器的值,否则返回默认值。

您应该做的是检查应用程序是否支持所有模式(转到目标“常规设置”或“ Info.plist”中的“部署信息”),找出根视图控制器的类。它可以是通用的UIViewController,UINavigationController,UITabBarController或某些自定义类。您可以通过以下方式查看:

dump(UIApplication.shared.keyWindow?.rootViewController)

或您喜欢的任何其他方式。

随便吧CustomNavigationController因此,您应该这样重写supportedInterfaceOrientations

class CustomNavigationController: UINavigationController {

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return topViewController?.supportedInterfaceOrientations ?? .allButUpsideDown
    }
}

例如,在仅应支持纵向方向的任何视图控制器中,都可以通过supportedInterfaceOrientations以下方式进行覆盖

class ChildViewController: UIViewController {

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .portrait
    }
}

然后,别忘了检查shouldAutorotate您的根视图控制器,并且最上面显示的视图控制器是否已经返回true如果不是,请将其添加到类定义中:

override var shouldAutorotate: Bool {
    return true
}

否则,supportedInterfaceOrientations将不会被调用。

干得好!

如果您只在一个视图控制器应支持一系列方向而其他视图不支持时需要解决相反的问题,请对每个视图控制器(而不是该视图控制器)进行此更改。

希望这会有所帮助。

我不确定此问题的历史记录(现在= iOS 10时间框架),但是在我于2016年10月发布此问题时缺少了最简单的解决方案

假设您要这样做:

  1. 仅支持iOS 7和更高版本(包括iOS 10)
  2. 一些视图控制器应支持所有方向,其他一些应支持方向的子集。我的意思示例:一个视图控制器应仅支持纵向,而其他所有视图控制器应支持所有方向
  3. 如果所有视图控制器都支持旋转,则它们必须自动旋转(这意味着您不希望在视图控制器中使用可解决此问题的代码)
  4. 支持UINavigationController在XIB / NIB / Storyboards中添加,而无需对其进行任何操作

...然后(IMO),最简单的解决方案是制作一个UINavigationControllerDelegate,而不是UINavigationController的子类(这违反了上面的假设4)。

当我解决了这个,我决定把我的第ViewController一个UINavigationControllerDelegate该视图控制器将自身设置为导航控制器的委托,并返回允许的方向。在我的情况下,默认设置是允许所有方向,最好使用纵向,但在一种特定情况下,仅允许纵向。以下代码来自Swift 3 / XCode 8:

    class iPhoneStartViewController: UIViewController {

        var navInterfaceOrientationMask: UIInterfaceOrientationMask?
        var navInterfaceOrientationPreferred: UIInterfaceOrientation! = .portrait

        override func viewDidLoad() {
            super.viewDidLoad()
            self.navigationController?.delegate = self
        }

        @IBAction func cameraButtonPressed(_ sender: AnyObject) {
            if PermissionsHelper.singleton().photosPermissionGranted() == false {
                self.navInterfaceOrientationMask = nil   // default is: all orientations supported
                self.performSegue(withIdentifier: "segueToPhotoAccess", sender: self)
            } else {
                self.navInterfaceOrientationMask = .portrait // this stops the next view controller from being to rotate away from portrait
                self.performSegue(withIdentifier: "segueToCamera", sender: self)
            }
        }
     }

     // lock orientation to portrait in certain cases only. Default is: all orientations supported
    extension iPhoneStartViewController : UINavigationControllerDelegate {
        public func navigationControllerSupportedInterfaceOrientations(_ navigationController: UINavigationController) -> UIInterfaceOrientationMask {
            if let mask = self.navInterfaceOrientationMask {
                return mask
            } else {
                return .all
            }
        }

        public func navigationControllerPreferredInterfaceOrientationForPresentation(_ navigationController: UINavigationController) -> UIInterfaceOrientation {
            return self.navInterfaceOrientationPreferred
        }
    }

基于@iAnum的答案,我启用了autorotate和UIViewController类检测。

这是因为否则,过渡到“特殊视图控制器”中和从“特殊视图控制器”中移出将无法正确地适应纵向,并且您将陷入不受支持的方向。

我只有一个支持景观的视图,因此我只是在自定义导航视图控制器中对其进行了硬编码:

-(BOOL)shouldAutorotate
{
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations
{
    //Access the current top object.
    UIViewController *viewController = [self.viewControllers lastObject];
    //Is it one of the landscape supported ones?
    if ([viewController isMemberOfClass:[SpecialViewController class]]) {
        return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
    } else
        return UIInterfaceOrientationMaskPortrait;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    //Access the current top object.
    UIViewController *viewController = [self.viewControllers lastObject];
    //Is it one of the landscape supported ones?
    if ([viewController isMemberOfClass:[SpecialViewController class]]) {
        return interfaceOrientation;
    } else
        return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}

弹出此处讨论的VC时出现问题https://stackoverflow.com/a/15057537/1277350,在横向视图中按下该键甚至不会调用定位方法,因此您必须通过显示和消除模态视图。

然后只需记住,如果要触发willShowViewController,则需要设置self.delegate = self并将UINavigationControllerDelegate以及下面的代码添加到自定义导航控制器中。

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationPortrait;
}

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    UIApplication* application = [UIApplication sharedApplication];
    if (application.statusBarOrientation != UIInterfaceOrientationPortrait)
    {
        UIViewController *c = [[UIViewController alloc]init];
        [c.view setBackgroundColor:[UIColor clearColor]];
        [navigationController presentViewController:c animated:NO completion:^{
            [self dismissViewControllerAnimated:YES completion:^{
            }];
        }];
    }
}

制作UINavigationController的子类,如下所示:

MyNavigationController.h

#import <UIKit/UIKit.h>

@interface MyNavigationController : UINavigationController

@end

MyNavigationController.m

#import "MyNavigationController.h"
#import "ServicesVC.h"

@implementation MyNavigationController

-(BOOL)shouldAutorotate{

    return YES;
}

-(NSUInteger)supportedInterfaceOrientations{

    if ([[self.viewControllers lastObject] isKindOfClass:[ServicesVC class]]) {
        return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
    }

    return UIInterfaceOrientationMaskAll;
}

@end

假设您的viewcontroller命名为:ServicesVC

这是Swift中Alexander(https://stackoverflow.com/posts/25507963/revisions的答案

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {

    var currentViewController: UIViewController? = self.topViewController()
    if currentViewController != nil && currentViewController!.canAutoRotate() {
        return Int(UIInterfaceOrientationMask.All.rawValue)
    }
    return Int(UIInterfaceOrientationMask.Portrait.rawValue)


}

func topViewController() -> UIViewController? {
    if UIApplication.sharedApplication().keyWindow != nil
    {
        return self.topViewControllerWithRootViewController(UIApplication.sharedApplication().keyWindow!.rootViewController!)
    }
    return nil
}

func topViewControllerWithRootViewController(rootViewController: UIViewController?) -> UIViewController? {
    if rootViewController == nil {
        return nil
    }
    if rootViewController!.isKindOfClass(UITabBarController) {
        var tabBarController: UITabBarController = (rootViewController as? UITabBarController)!
        return self.topViewControllerWithRootViewController(tabBarController.selectedViewController)
    }
    else {
        if rootViewController!.isKindOfClass(UINavigationController) {
            var navigationController: UINavigationController = (rootViewController as? UINavigationController)!
            return self.topViewControllerWithRootViewController(navigationController.visibleViewController)
        }
        else {
            if (rootViewController!.presentedViewController != nil) {
                var presentedViewController: UIViewController = rootViewController!.presentedViewController!
                return self.topViewControllerWithRootViewController(presentedViewController)
            }
            else {
                return rootViewController
            }
        }
    }
}

此外,您需要在AppDelegate.swift中添加以下代码段:

extension UIViewController {
func canAutoRotate() -> Bool {
    return false
}}

对于要允许所有旋转的ViewController,添加以下函数:

override func canAutoRotate() -> Bool {
    return true
}

我知道这个问题很老,但是需要更新的答案。实现此结果的最简单,最正确的方法是在应用程序设置中启用纵向和横向。然后将此代码添加到您的应用程序委托中:

 func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {

    if let navigationController = self.window?.rootViewController as? UINavigationController {

        if navigationController.visibleViewController is INSERTYOURVIEWCONTROLLERHERE  {
            return UIInterfaceOrientationMask.All
        }

        else {
            return UIInterfaceOrientationMask.Portrait
        }
    }

    return UIInterfaceOrientationMask.Portrait
}

不要忘记用视图控制器替换“ INSERTYOURVIEWCONTROLLERHERE”。

我有同样的情况。因此,我将UINavigationController细分为CustomNavigationController,并在此CustomNavigationController中编写了

#define IOS_OLDER_THAN_6 ( [ [ [ UIDevice currentDevice ] systemVersion ] floatValue ] < 6.0 )
#define IOS_NEWER_OR_EQUAL_TO_6 ( [ [ [ UIDevice currentDevice ] systemVersion ] floatValue ] >= 6.0 )


#pragma mark - Rotation

#ifdef IOS_OLDER_THAN_6
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
      return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
#endif
#ifdef IOS_NEWER_OR_EQUAL_TO_6
-(BOOL)shouldAutorotate {
    return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;;
}
#endif

我使用了这个CustomNavigationController而不是现有的NavigationController。

然后在必须在LandScape Orientation中显示的视图控制器中说LandScapeView,我写道

#pragma mark - Rotation

#ifdef IOS_OLDER_THAN_6

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
    return (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight | toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}

#endif

#ifdef IOS_NEWER_OR_EQUAL_TO_6

-(BOOL)shouldAutorotate {
    return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskLandscapeLeft;
}

#endif

在CustomNavigationController内部,我展示了此视图控制器,而不是将其推入Navigation Stack。因此,LandScapeView出现在LandScape方向中。

LandScapeView *graph = [[LandScapeView alloc]init....];
[self presentViewController:graph animated:YES completion:nil];

我没有在“项目设置”中的“支持的界面方向”中进行任何更改

//将此方法粘贴到应用专用类中

- (UIInterfaceOrientationMask)application:(UIApplication )application supportedInterfaceOrientationsForWindow:(UIWindow )window
{
 if ([self.window.rootViewController.presentedViewController isKindOfClass: [_moviePlayerController class]])
  {
   if (self.window.rootViewController.presentedViewController)
        return UIInterfaceOrientationMaskAll;
    else return UIInterfaceOrientationMaskPortrait;
  }
 else return UIInterfaceOrientationMaskPortrait;
}   

如果该应用程序支持从IOS7IOS9,请使用以下代码进行定向:

#if __IPHONE_OS_VERSION_MAX_ALLOWED < 90000
- (NSUInteger)supportedInterfaceOrientations
#else
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
#endif
{
    if([AppDelegate isPad]) return UIInterfaceOrientationMaskAll;
    else return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}
本文地址:http://ios.askforanswer.com/ruhezhiyunxudangeuiviewcontrolleryanhengxianghezongxiangxuanzhuan.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!