简体   繁体   English

强制改变方向有时不起作用

[英]Forced orientation change does not work sometimes

When a certain button is pressed in my app, the view should change orientation from portrait to landscape. 当我的应用程序中按下某个按钮时,视图应将方向从纵向更改为横向。 When the user comes back, the view controller should change back to portrait. 当用户回来时,视图控制器应改回肖像。 But sometimes the orientation doesn't change or the wrong view frame is used. 但是有时方向不会改变,或者使用了错误的视框。

Here is my code 这是我的代码

-(void)btnSignClicked:(CustomSignButton *)btn {
    isSignButtonClicked = true;
    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_0) {
        NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
        [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    }
    else
    {
        [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:YES];
    }
    selectedWaiverId = btn.customTag;

    SignatureView *obj = [[SignatureView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) delegate:self]; // Most of time got size (568,320) but some time i got (320,568), Don't know why
    [self.view addSubview:obj];
}

#pragma mark - SIGNATUREVIEW DELEGATE
-(void)removeSignatureView:(SignatureView *)signatureView {
    isSignButtonClicked = false;

    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_0)
    {
        NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
        [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; // Some time not changed the orientation are view remaining in landscape 
    }
    else
    {
        [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:YES];
    }

    [signatureView removeFromSuperview];
    signatureView = nil;

}
#pragma mark
#pragma mark - Rotate screen
-(UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    if (isSignButtonClicked == true)
    {
        return UIInterfaceOrientationMaskLandscapeRight|UIInterfaceOrientationMaskLandscape;
    }
    else
    {
        return UIInterfaceOrientationMaskPortrait;
    }
}
- (BOOL)shouldAutorotate
{
    return YES;
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    if (isSignButtonClicked == true)
    {
        return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
    }
    else
    {
        return (interfaceOrientation == UIInterfaceOrientationPortrait);
    }

}

UPDATE 更新

Sometimes viewWillTransitionToSize method is not called so I also integrate this notification 有时未调用viewWillTransitionToSize方法,因此我也集成了此通知

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];

But sometimes this also does not work. 但是有时这也不起作用。

Add in AppDelegate.m file or any base controller file 添加AppDelegate.m文件或​​任何基本控制器文件

 @implementation UINavigationController (Orientation)


- (UIInterfaceOrientationMask) supportedInterfaceOrientations
{

    return [(UIViewController*)[[self viewControllers] lastObject] supportedInterfaceOrientations];

}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [(UIViewController*)[[self viewControllers] lastObject] preferredInterfaceOrientationForPresentation];
}

- (BOOL) shouldAutorotate
{
    return [(UIViewController*)[[self viewControllers] lastObject] shouldAutorotate];
}

@end

Now put your ViewController object in UINavigationController object and push the view controller. 现在,将ViewController对象放入UINavigationController对象中,然后推入视图控制器。

EX. 例如

UINavigationController *obj=[[UINavigationController  alloc] initWithRootViewController:_yourViewCtrlObj];

[self presentViewController:obj.....]; 

or
[self.navigationController pushViewController:obj animated:YES];

Set your desired orientation in all view controller. 在所有视图控制器中设置所需的方向。

If your app uses UINavigationViewController then create a custom class for UINAvigationController Like: 如果您的应用程序使用UINavigationViewController,则为UINAvigationController创建一个自定义类,如下所示:

//CustomNavViewController.h //CustomNavViewController.h

#import <UIKit/UIKit.h>
@interface CustomNavViewController : UINavigationController <UINavigationControllerDelegate>

@end

//CustomNavViewController.m //CustomNavViewController.m

#import "CustomNavViewController.h"
@interface CustomNavViewController ()
@end

@implementation CustomNavViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (BOOL)shouldAutorotate {
return [self.visibleViewController shouldAutorotate];
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return [self.visibleViewController supportedInterfaceOrientations];
}
@end

And Now in your AppDelegate declare a property Like: 现在在您的AppDelegate中声明一个属性,例如:

//AppDelegate.h //AppDelegate.h

 @property (assign, nonatomic) BOOL shouldRotate;

//AppDelegate.m //AppDelegate.m

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if (self.shouldRotate) {
    return  UIInterfaceOrientationMaskLandscapeLeft|UIInterfaceOrientationMaskLandscapeRight;
}
return UIInterfaceOrientationMaskPortrait;
}

Now you can call orientation methods to ViewController which required fix orientation Like: 现在,您可以向ViewController调用方向方法,该方法需要固定方向,例如:

//YourViewController.m //YourViewController.m

-(BOOL)shouldAutorotate{
return NO;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
     return UIInterfaceOrientationMaskLandscape;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return UIInterfaceOrientationLandscapeLeft;
}

Now here is the trick set AppDelegate shouldRotate property to true and false for desired orientation 现在,这是将技巧设置AppDelegate shouldRotate属性设置为true和false以获得所需的方向

if you are using Default Presentation for ViewController then 如果您对ViewController使用默认表示,则

AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
[appDelegate setShouldRotate:true];// Remember first update the value then present the ViewController
[self presentViewController:yourViewController animated:YES completion:nil];

Same as when you dismiss 与解雇时相同

 AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
[appDelegate setShouldRotate:false];
[self dismissViewControllerAnimated:YES completion:nil];

If you are using storyBoards then add CustomNavViewController directly on Identity Inspector Custom class section 如果您使用的是StoryBoards,则直接在Identity Inspector“自定义类”部分中添加CustomNavViewController

customNav And after that follow above steps. 然后执行上述步骤。 Hope it's working 希望它能正常工作

When you say "When the user comes back, the view controller should change back to portrait", do you mean that the user is hitting the back button on a navigation controller? 当您说“当用户回来时,视图控制器应该变回纵向”,这是否意味着用户正在点击导航控制器上的“后退”按钮? If so, I saw this issue before and posted a solution that worked for me in another SO post: A: Locking device orientation on a view fails when going back in NavBar . 如果是这样,我之前就看过这个问题,并在另一篇SO文章中发布了对我有用的解决方案: 答:在NavBar中返回时,在视图上锁定设备方向失败 I remember the transition being rough but it worked. 我记得过渡很艰难,但确实行得通。

I also wrote a blog post a while back that looks at some other situations around view controller orientation locking. 不久前,我还写了一篇博客文章 ,探讨了有关视图控制器方向锁定的其他情况。

See this link , in particular, I think you should check the conditions of your view controllers, that they meet Apple recommendations 请参阅此链接 ,特别是,我认为您应该检查视图控制器的条件,以确保它们符合Apple的建议。

eg check supportedInterfaceOrientations method of the top-most full-screen view controller 例如,检查最顶部的全屏视图控制器的supportedInterfaceOrientations方法

Try adding all your rotation changing code inside this block 尝试在此块中添加所有旋转更改代码

dispatch_async(dispatch_get_main_queue(), 
{
     //changing orientation code + isSignButtonClicked = true (or false) 
});

You need not use shouldAutorotate and shouldAutorotateToInterfaceOrientation . 您不需要使用shouldAutorotateshouldAutorotateToInterfaceOrientation

As for the view frames getting wrong, you need to use autolayout constraints for each and every view you are using in this viewController even if you are creating views programmativally 对于错误的视图框架,即使您以编程方式创建视图,也需要为在此viewController中使用的每个视图使用自动布局约束

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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