欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

总结iOS App开发中控制屏幕旋转的几种方式

程序员文章站 2023-08-12 15:29:14
在ios6之前的版本中,通常使用 shouldautorotatetointerfaceorientation 来单独控制某个uiviewcontroller的方向,需要哪...

在ios6之前的版本中,通常使用 shouldautorotatetointerfaceorientation 来单独控制某个uiviewcontroller的方向,需要哪个viewcontroller支持旋转,只需要重写shouldautorotatetointerfaceorientation方法。
但是ios 6里屏幕旋转改变了很多,之前的 shouldautorotatetointerfaceorientation 被列为 deprecated 方法,查看uiviewcontroller.h文件也可以看到:

复制代码 代码如下:

// applications should use supportedinterfaceorientations and/or shouldautorotate.. 
- (bool)shouldautorotatetointerfaceorientation:(uiinterfaceorientation)tointerfaceorientation ns_deprecated_ios(2_0, 6_0); 

程序将使用如下2个方法来代替:
复制代码 代码如下:

- (bool)shouldautorotate; 
- (nsuinteger)supportedinterfaceorientations; 

除了重写这个2个方法,ios6之后要旋转还有一些需要注意的地方,下面会细述。另外还有一个硬性条件,需要在info.plist文件里面添加程序支持的所有方向,可以通过以下2种方式添加
1.

总结iOS App开发中控制屏幕旋转的几种方式

2.

总结iOS App开发中控制屏幕旋转的几种方式

另外要兼容ios6之前的系统,要保留原来的 shouldautorotatetointerfaceorientation 方法,还有那些 willrotatetointerfaceorientation 等方法。

自动旋转设置:
控制某个viewcontroller旋转并不是像ios5或者ios4一样在这个viewcontroller里面重写上面那2个方法,而是需要在这个viewcontroller的rootviewcontroller(根视图控制器)里面重写,怎么解释呢?就是最前面的那个viewcontroller,直接跟self.window接触的那个controller,比如以下代码:

复制代码 代码如下:

uiviewcontroller *viewctrl = [[uiviewcontroller alloc] init]; 
uinavigationcontroller *navctrl = [[uinavigationcontroller alloc] initwithrootviewcontroller:viewctrl]; 
if ([window respondstoselector:@selector(setrootviewcontroller:)]) { 
    self.window.rootviewcontroller = navctrl; 
} else { 
    [self.window addsubview:navctrl.view]; 


如果需要设置viewctrl的旋转,那么不能在uiviewcontroller里面重写shouldautorotate和supportedinterfaceorientations方法,而是需要在navctrl里面设置,又因为uinavigationcontroller是系统控件,所以这里需要新建一个uinavigationcontroller的子navigationcontroller的子类,然后在里面实现shouldautorotate和supportedinterfaceorientations方法,比如:
复制代码 代码如下:

-(nsuinteger)supportedinterfaceorientations{ 
    return uiinterfaceorientationmaskallbutupsidedown; 

 
- (bool)shouldautorotate{ 
    return yes; 
}

eg1:如果上面的例子是self.window.rootviewcontroller = viewctrl,而不是navctrl,那么上面的那2个控制旋转的方法就应该写在uiviewcontroller里面!

eg2:如果viewctrl又pushviewcontroller到viewctrl2,需要设置viewctrl2的旋转,怎么办呢? 还是在navctrl里面控制,因为viewctrl和viewctrl2的rootviewcontroller都是navctrl,一般的写法都是

复制代码 代码如下:

uiviewcontroller *viewctrl2 = [[uivewcontroller alloc] init]; 
[self.navigationcontroller.navigationcontroller pushviewcontroller:viewctrl2 animated:yes];

所以要控制一个uinavigationcontroller push到的所有viewcontroller的旋转,那么就得在navctrl里面区分是哪个viewcontroller,以便对他们一一控制!同样如果rootviewcontroller是uitabbarcontroller,那么需要在子类化的uitabbarcontroller里面重写那2个方法,然后分别控制!

但是有时候我初始化uinavigationcontroller的时候,并不知道所有我所有需要push到的viewcontroller,那么这里有一个通用的方法,就是让viewcontroller自己来控制自己,首先在navctrl里面的实现方法改为以下方式:

复制代码 代码如下:

- (bool)shouldautorotate   
{   
    return self.topviewcontroller.shouldautorotate;   
}   
   
- (nsuinteger)supportedinterfaceorientations   
{   
    return self.topviewcontroller.supportedinterfaceorientations;   


全部调用self.topviewcontroller,就是返回当前呈现出来的viewcontroller里面的设置,然后在viewctrl、viewctrl2等等这些viewcontroller里面重写shouldautorotate和supportedinterfaceorientations,以方便设置每个viewcontroller的旋转

eg3:如果viewctrl 是 presentmodalviewcontroller 到 viewctrl3,那么viewctrl3的旋转设置就不在navctrl里面了!如果presentmodalviewcontroller的viewcontroller是navcontroller、tabbarcontroller包装过的viewctrl3,那么就应在新包装的navcontroller、tabbarcontroller里面设置,如果是直接presentmodalviewcontroller到viewctrl3,那么就在viewctrl3里面设置


手动旋转
手动旋转也有2种方式,一种是直接设置 uidevice 的 orientation,但是这种方式不推荐,上传appstore有被拒的风险:

复制代码 代码如下:

if ([[uidevice currentdevice] respondstoselector:@selector(setorientation:)]) { 
    [[uidevice currentdevice] performselector:@selector(setorientation:) withobject:(id)uiinterfaceorientationportrait]; 
}
 
第二种是假旋转,并没有改变 uidevice 的 orientation,而是改变某个view的 transform,利用 cgaffinetransformmakerotation 来达到目的,比如:
复制代码 代码如下:

self.view.transform = cgaffinetransformmakerotation(m_pi/2) 

下面讲解采用第二种方式的各版本手动旋转:
思想是首先设置 statusbarorientation,然后再改变某个view的方向跟 statusbarorientation 一致!

那既然是旋转,最少也得有2个方向,那么还是少不了上面说的那个硬性条件,先在plist里面设置好所有可能需要旋转的方向。既然是手动旋转,那么就要关闭自动旋转:

复制代码 代码如下:

- (bool)shouldautorotate{ 
        return no; 
}
 
手动触发某个按钮,调用方法,这个方法的实现如下:
复制代码 代码如下:

[[uiapplication sharedapplication] setstatusbarorientation:uiinterfaceorientationlandscaperight]; 
self.view.transform = cgaffinetransformmakerotation(m_pi/2); 
self.view.bounds = cgrectmake(0, 0, kscreenheight, 320);
 

注意:
1. 只需要改变self.view.transform,那么self.view的所有subview都会跟着自动变;其次因为方向变了,所以self.view的大小需要重新设置,不要使用self.view.frame,而是用bounds。
2. 如果shouldautorotate 返回yes的话,下面设置setstatusbarorientation 是不管用的!setstatusbarorientation只有在shouldautorotate 返回no的情况下才管用!

强制旋转屏幕
最近接手了一个项目,正常情况下使用查看图片是没问题的。

用到了 mwphotobrowser 这个第三方图片浏览库。
不过发现了一个问题,就是设备横屏modal这mwphotobrowser的时候,发生了图片位置错乱。

实在没办法,所以想到了一个馊主意。

就是modal的时候使用代码把设备强制旋转回去。

复制代码 代码如下:

//uidevice+wj.h
@interface uidevice (wj)
/**
 *  强制旋转设备
 *  @param  旋转方向
 */
+ (void)setorientation:(uiinterfaceorientation)orientation;
@end
//uidevice+wj.m
#import "uidevice+wj.h"
@implementation uidevice (wj)
//调用私有方法实现
+ (void)setorientation:(uiinterfaceorientation)orientation {
    sel selector = nsselectorfromstring(@"setorientation:");
    nsinvocation *invocation = [nsinvocation invocationwithmethodsignature:[self instancemethodsignatureforselector:selector]];
    [invocation setselector:selector];
    [invocation settarget:[self currentdevice]];
    int val = orientation;
    [invocation setargument:&val atindex:2];
    [invocation invoke];
}
@end