iOS屏幕旋转与锁屏的示例代码

2025-05-29 0 88

在做视频开发时遇到屏幕旋转问题,其中涉及到 statusbar、 uinavigationcontroller、uitabbarcontroller 、uiviewcontroller

在设备锁屏下的整体效果图

iOS屏幕旋转与锁屏的示例代码

ios-旋转.gif

主要涉及以下4点:

  • 横竖屏的旋转
  • 屏幕旋转相应改变视图位置
  • 旋转时状态栏的隐藏与显示
  • 锁屏

1、横竖屏旋转

第1步:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50
-(uiinterfaceorientationmask)application:(uiapplication *)application supportedinterfaceorientationsforwindow:(uiwindow *)window {

// nslog(@"0000000---------%@",nsstringfromclass([[self topviewcontroller] class]));

// if ([nsstringfromclass([[self topviewcontroller] class]) isequaltostring:@"firstviewcontroller"]) {

// //横屏

// return uiinterfaceorientationmasklandscaperight;

// }

// //竖屏

// return uiinterfaceorientationmaskportrait;

nsuinteger orientations = uiinterfaceorientationmaskallbutupsidedown;

if(self.window.rootviewcontroller){

//取出当前显示的控制器

uiviewcontroller *presentedviewcontroller = [self topviewcontrollerwithrootviewcontroller:self.window.rootviewcontroller];

//按当前控制器支持的方向确定旋转方向(将旋转方向重新交给每个控制器自己控制)

nslog(@"%s, line = %d",__function__,__line__);

orientations = [presentedviewcontroller supportedinterfaceorientations];

}

return orientations;

}

//获取界面最上层的控制器

//- (uiviewcontroller*)topviewcontroller {

// nslog(@"%s, line = %d",__function__,__line__);

// return [self topviewcontrollerwithrootviewcontroller:[uiapplication sharedapplication].keywindow.rootviewcontroller];

//}

//一层一层的进行查找判断

- (uiviewcontroller*)topviewcontrollerwithrootviewcontroller:(uiviewcontroller*)rootviewcontroller {

nslog(@"%s, line = %d",__function__,__line__);

if ([rootviewcontroller iskindofclass:[uitabbarcontroller class]]) {

uitabbarcontroller* tabbarcontroller = (uitabbarcontroller*)rootviewcontroller;

nslog(@"tabbar:%@",nsstringfromclass([tabbarcontroller.selectedviewcontroller class]));

return [self topviewcontrollerwithrootviewcontroller:tabbarcontroller.selectedviewcontroller];

} else if ([rootviewcontroller iskindofclass:[uinavigationcontroller class]]) {

uinavigationcontroller* nav = (uinavigationcontroller*)rootviewcontroller;

nslog(@"nav:%@",nsstringfromclass([nav.visibleviewcontroller class]));

return [self topviewcontrollerwithrootviewcontroller:nav.visibleviewcontroller];

} else if (rootviewcontroller.presentedviewcontroller) {

nslog(@"present:%@",nsstringfromclass([rootviewcontroller.presentationcontroller class]));

uiviewcontroller* presentedviewcontroller = rootviewcontroller.presentedviewcontroller;

return [self topviewcontrollerwithrootviewcontroller:presentedviewcontroller];

} else {

nslog(@"root:%@",rootviewcontroller);

return rootviewcontroller;

}

}

代码中通过 -(uiinterfaceorientationmask)application:(uiapplication *)application supportedinterfaceorientationsforwindow:(uiwindow *)window 方法将控制器交给自己控制,该方法默认值为 info.plist 中配置的 supported interface orientations 项的值。

第2步:在各控制器设置支持的方向

?

1

2

3

4

5

6

7

8

9
//是否允许旋转(默认允许)

- (bool)shouldautorotate {

return yes;

}

- (uiinterfaceorientationmask)supportedinterfaceorientations{

//允许旋转的方向

return uiinterfaceorientationmaskall;

}

其中 - supportedinterfaceorientations 方法在 ipad 中默认取值为 uiinterfaceorientationmaskall ,即默认支持所有屏幕方向;而 iphone 跟 ipod touch 的默认取值为 uiinterfaceorientationmaskallbutupsidedown ,即支持除竖屏向下以外的三个方向。

在设备屏幕旋转时,系统会调用 - shouldautorotate 方法检查当前界面是否支持旋转,只有 - shouldautorotate 返回 yes 的时候, - supportedinterfaceorientations 方法才会被调用,以确定是否需要旋转界面。

这个是 tabbarcontroller 中设置的,它会影响关联的 uiviewcontroller 的支持方向,需要在 uiviewcontroller 中进一步设置

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27
//此方法来控制能否横竖屏 控制锁屏

- (uiinterfaceorientationmask)supportedinterfaceorientations {

nslog(@"%s, line = %d",__function__,__line__);

uiinterfaceorientationmask inter;

if (_lockscreen) {

switch (_lockorientation) {

case 1:

inter = uiinterfaceorientationmaskportrait;

break;

case 2:

inter = uiinterfaceorientationmaskportraitupsidedown;

break;

case 3:

inter = uiinterfaceorientationmasklandscaperight;

break;

case 4:

inter = uiinterfaceorientationmasklandscapeleft;

break;

default:inter = uiinterfaceorientationmaskall;

break;

}

} else {

inter = uiinterfaceorientationmaskall;

}

//支持全部方向

return inter;

}

第3步:强制转换控制器方向

?

1

2

3

4

5

6

7

8

9

10

11

12

13
- (void)setinterorientation:(uiinterfaceorientation)orientation {

if ([[uidevice currentdevice] respondstoselector:@selector(setorientation:)]) {

sel selector = nsselectorfromstring(@"setorientation:");

nsinvocation *invocation = [nsinvocation invocationwithmethodsignature:[uidevice instancemethodsignatureforselector:selector]];

[invocation setselector:selector];

[invocation settarget:[uidevice currentdevice]];

int val = orientation;

// 从2开始是因为0 1 两个参数已经被selector和target占用

[invocation setargument:&val atindex:2];

[invocation invoke];

}

}

这样就可以完成横竖屏的切换。

2、屏幕旋转相应改变视图位置

这里先扩展 uideviceorientation & uiinterfaceorientation 的知识

uideviceorientation 设备的物理方向

uideviceorientation 即我们手持的移动设备的 orientation ,是一个三围空间,有六个方向,通过 [uidevice currentdevice].orientation 获取当前设备的方向。

?

1

2

3

4

5

6

7

8

9
typedef ns_enum(nsinteger, uideviceorientation) {

uideviceorientationunknown,

uideviceorientationportrait,

uideviceorientationportraitupsidedown, // device oriented vertically, home button on the top 竖屏向下,即头在下,home 键在上

uideviceorientationlandscapeleft, // device oriented horizontally, home button on the right 横屏头在左,home键在右

uideviceorientationlandscaperight, // device oriented horizontally, home button on the left 横屏头在右,home键在左

uideviceorientationfaceup, // device oriented flat, face up

uideviceorientationfacedown // device oriented flat, face down

} ;

uiinterfaceorientation 界面的显示方向

uiinterfaceorientation 即我们看到的视图的 orientation ,可以理解为 statusbar 所在的方向,是一个二维空间,有四个方向, 通过 [uiapplication sharedapplication].statusbarorientation 即状态栏的方向获取当前界面方向。

?

1

2

3

4

5

6

7

8

9
// note that uiinterfaceorientationlandscapeleft is equal to uideviceorientationlandscaperight (and vice versa).

// this is because rotating the device to the left requires rotating the content to the right.

typedef ns_enum(nsinteger, uiinterfaceorientation) {

uiinterfaceorientationunknown = uideviceorientationunknown,

uiinterfaceorientationportrait = uideviceorientationportrait,

uiinterfaceorientationportraitupsidedown = uideviceorientationportraitupsidedown,

uiinterfaceorientationlandscapeleft = uideviceorientationlandscaperight,

uiinterfaceorientationlandscaperight = uideviceorientationlandscapeleft

}

uiinterfaceorientationmask 支持的方向

?

1

2

3

4

5

6

7

8

9

10
// ios 6 之后用于控制界面的枚举值

typedef ns_options(nsuinteger, uiinterfaceorientationmask) {

uiinterfaceorientationmaskportrait = (1 << uiinterfaceorientationportrait),

uiinterfaceorientationmasklandscapeleft = (1 << uiinterfaceorientationlandscapeleft),

uiinterfaceorientationmasklandscaperight = (1 << uiinterfaceorientationlandscaperight),

uiinterfaceorientationmaskportraitupsidedown = (1 << uiinterfaceorientationportraitupsidedown),

uiinterfaceorientationmasklandscape = (uiinterfaceorientationmasklandscapeleft | uiinterfaceorientationmasklandscaperight),

uiinterfaceorientationmaskall = (uiinterfaceorientationmaskportrait | uiinterfaceorientationmasklandscapeleft | uiinterfaceorientationmasklandscaperight | uiinterfaceorientationmaskportraitupsidedown),

uiinterfaceorientationmaskallbutupsidedown = (uiinterfaceorientationmaskportrait | uiinterfaceorientationmasklandscapeleft | uiinterfaceorientationmasklandscaperight),

}

由上可以发现:

ios 6 及之后版本使用的 uiinterfaceorientationmask 类型来控制屏幕屏幕方向,该类型也新增加了几个枚举取值,可用一个枚举取值来代表多个屏幕方向,使用起来更方便。

注意在 uiinterfaceorientation 中有注释

note that uiinterfaceorientationlandscapeleft is equal to uideviceorientationlandscaperight (and vice versa).

this is because rotating the device to the left requires rotating the content to the right,大意是界面的左转相当于设备的右转,如果设备向左转时就需要内容(即界面)向右转。即:

uiinterfaceorientationlandscapeleft = uideviceorientationlandscaperight
uiinterfaceorientationlandscaperight = uideviceorientationlandscapeleft

下面还会举例说明。

其实 uideviceorientationuiinterfaceorientation 是两个互不相干的属性,通常情况下会一起出现,在这里正好利用此特性在屏幕旋转后进行重新布局。

第1步:监听 uideviceorientationdidchangenotification 状态

?

1

2

3

4

5

6

7

8
//监听设备旋转 改变 视图 对应位置

[[nsnotificationcenter defaultcenter] addobserver:self selector:@selector(deviceorientationdidchange) name:uideviceorientationdidchangenotification object:nil];

//用来控制横竖屏时调整视图位置

- (void)deviceorientationdidchange

{

[self isportrait];

}

第2步:重新布局

?

1

2

3

4

5

6

7

8
if (_interorientation == uiinterfaceorientationportrait || _interorientation == uiinterfaceorientationportraitupsidedown) {

self.top.constant = 145;

self.bottom.constant = 210;

} else if (_interorientation == uiinterfaceorientationlandscaperight || _interorientation == uiinterfaceorientationlandscapeleft) {

self.top.constant = 40;

self.bottom.constant = 50;

}

例如:竖屏转横屏

界面竖屏 uiinterfaceorientationportrait ->横屏 uiinterfaceorientationlandscaperight ,设备方向 uideviceorientationportrait -> uideviceorientationlandscapeleft ,在设备发生变化这个过程触发 uideviceorientationdidchangenotification 监听,然后进行重新布局。

3、旋转时状态栏的隐藏与显示

这里只记述旋转时状态栏的变化,由竖屏想横屏变化时状态栏会消失。

?

1

2

3

4

5
//在需要的`uiviewcontroller`设置是否隐藏

- (bool)prefersstatusbarhidden {

nslog(@"%s, line = %d",__function__,__line__);

return no;

}

4、锁屏

锁屏时,不管系统锁屏是否关闭、push 或 present 返回后,界面依然保持不变。

第1步:设置锁屏

?

1

2

3

4

5

6

7

8

9

10

11

12
- (ibaction)lockaction:(uibutton *)sender {

if (_lockscreen) {

_lockscreen = no;

[sender settitle:@"锁定屏幕" forstate:uicontrolstatenormal];

} else {

_lockscreen = yes;

[sender settitle:@"解开屏幕" forstate:uicontrolstatenormal];

}

_lockorientation = _interorientation;

}

第2步:绕过强转

?

1

2

3

4

5

6

7

8
- (void)interfaceorientation:(uiinterfaceorientation)orientation

{

[self isportrait];

//锁屏情况下 不旋转

if (!_lockscreen) {

[self setinterorientation:orientation];

}

第3步:针对 push 或 present 返回后

?

1

2

3

4

5

6

7

8

9
- (void)viewwillappear:(bool)animated {

if (_lockscreen) {

//记录返回时的界面状态

[self setinterorientation:_lockorientation];

} else {

[self isportrait];

}

}

5、 针对特定 uiviewcontroller 方向的支持

?

1

2

3

4

5

6

7

8

9
-(uiinterfaceorientationmask)application:(uiapplication *)application supportedinterfaceorientationsforwindow:(uiwindow *)window {

if ([nsstringfromclass([[self topviewcontroller] class]) isequaltostring:@"firstviewcontroller"]) {

//横屏

return uiinterfaceorientationmasklandscaperight;

}

//竖屏

return uiinterfaceorientationmaskportrait;

}

最后的献上 github 代码,还有2个小的 bug ,有兴趣的朋友欢迎来探讨。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持快网idc。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 iOS屏幕旋转与锁屏的示例代码 https://www.kuaiidc.com/89216.html

相关文章

发表评论
暂无评论