iOS应用横竖屏切换

一、概述:
    在iOS应用中,由UIViewController来控制屏幕翻转,根据需要随设备方向自动切换。在iOS6和之前的系统之间,控制方法发生了些变化。

二、视图伸缩属性:

1.UIView类的autoresizingMask属性,用来指定当它的父视图frame发生变化时,自身frame的变化规则。此属性可以在XIB中设置,也可以直接用代码设置,具体用哪个看情况。可用值的具体含义如下:
   (1)UIViewAutoresizingNone:自身frame不随父视图变化;
   (2)UIViewAutoresizingFlexibleLeftMargin:父视图frame发生变化时,自身视图的左边距动态缩小或者拉伸;
   (3)UIViewAutoresizingFlexibleRightMargin:父视图frame发生变化时,自身视图的右边距动态缩小或者拉伸;
   (4)UIViewAutoresizingFlexibleTopMargin:父视图frame发生变化时,自身视图的上边距动态缩小或者拉伸;
   (5)UIViewAutoresizingFlexibleBottomMargin:父视图frame发生变化时,自身视图的下边距动态缩小或者拉伸;
   (6)UIViewAutoresizingFlexibleWidth:父视图frame发生变化时,自身视图宽度随父视图同比例动态缩小或者拉伸;
   (7)UIViewAutoresizingFlexibleHeight:父视图frame发生变化时,自身视图高度随父视图同比例动态缩小或者拉伸;

2.伸缩属性可以多个一起使用,使用位或运算符("|")连接。

3.在屏幕翻转之后,控制器的主视图的frame会发生变化,所以,在屏幕翻转之后的界面调整中,可能会用到这个属性来控制子界面的frame。

三、Info.plist中相关的设置:
Supported interface orientations,对应一个数组,包含应用支持的设备方向。如果代码中实现了没有支持的方向,执行时会报异常。

四、UIViewController中的翻转控制方法(iOS6之前)

1.判断是否支持新方向:
(1)实现视图控制器类的shouldAutorotateToInterfaceOrientation:方法,在此方法中,如果当前设备方向为我们需要支持的方向,则该方法返回YES,否则返回NO。系统会根据此方法返回的BOOL值来决定是不是翻转该控制器的界面。
(2)可用的设备方向值如下:
   UIInterfaceOrientationPortrait:Home键在下方;
   UIInterfaceOrientationPortraitUpsideDown:Home键在上方;
   UIInterfaceOrientationLandscapeLeft:Home键在左方:
   UIInterfaceOrientationLandscapeRight:Home键在右方。
(3)此方法默认实现只支持UIInterfaceOrientationPortrait。

2.翻转通知方法:
   (1)控制器类翻转通知分为两类,一类是一步翻转通知,一类是两步翻转通知。
   (2)控制器默认选择使用一步翻转过程,如果同时重写了两步翻转通知方法,则控制器会自动选择使用两步翻转过程。

3.一步翻转通知方法:
(1)视图控制器类的willRotateToInterfaceOrientation:duration:方法,在控制器视图将要翻转时被调用。
    如果视图翻转时界面变化相对简单,可以在XIB中使用伸缩属性来设置子界面变化。如果在翻转之后界面变化比较复杂,伸缩属性就无能为力了,需要在此方法中用代码动态设置需要调整的子视图的frame。在改变子视图frame时,为了使翻转效果更友好,应该使用动画API,使frame调整过程更优美,动画执行时长使用duration参数对应的值。
(2)视图控制器类的didRotateFromInterfaceOrientation:方法,在控制器视图翻转完毕时调用。
    我们可以在此方法中做一些必要的动作。
    不要在此方法中调整子视图frame,否则子视图的界面frame调整会比主视图慢一小段时间,效果不好。

4.两步翻转通知方法:
(1)视图控制器类的willAnimateFirstHalfOfRotationToInterfaceOrientation:duration:方法,当视图控制器前半部分翻转开始时调用。假如我们想要在翻转前半部分开始时添加额外的动画,可以重写此方法。
(2)视图控制器类的didAnimateFirstHalfOfRotationToInterfaceOrientation: 方法,当控制器前半部分翻转完成时调用。
(3)视图控制器类的willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:方法,当控制器后半部分翻转开始时调用。
(4)两步翻转方法在iOS5版本开始被废弃。

5.具体的执行流程:
(1)一步翻转流程图:
iOS应用横竖屏切换 - 米安格 - 米安格的博客

(2)两步翻转流程图:
iOS应用横竖屏切换 - 米安格 - 米安格的博客

五、iOS6之前使用翻转通知方法碰到的问题

1.情景简述:假如视图A,初始实现是竖屏的,而且支持所有设备方向,然后在进入视图A时,设备是横屏的,如果视图A是主视图,willRotateToInterfaceOrientation:duration:会被调用,但是如果视图A不是主视图,则不会调用,导致进入视图A之后,视图A的子视图还是竖向的状态。但是接下来真实的翻转设备到竖屏,再到横屏,willRotateToInterfaceOrientation:duration:就会被调用了。

2.分析原因:
(1)控制器初始化时,只有主视图能够收到翻转通知。但是真实的翻转设备时,已经初始化的所有视图都能收到翻转通知。主视图包含真实添加到window的控制器视图、通过presentModalViewController弹出的视图,以及导航控制器的第一个视图(之后push进的视图不是主视图)等。
(2)假如我们要写一个用导航控制器组织的App,但是每个界面都需要支持横屏和竖屏,就遇到上面的问题了。

3.解决方法:
(1)原理:重写UIView的layoutSubviews方法,当界面初始化,屏幕旋转导致重绘,都会调用此方法。
(2)实现方法:首先实现UIView的一个子类,比如取名为RotationView,并建立一个代理对象;重写layoutSubviews方法,通过检查状态栏方向是不是和之前记录的方向一致,如果不一致,则调用代理方法;然后将控制器的view属性修改为RotationView,将RotationView的代理设置为控制器本身,在代理方法实现中,根据当前设备方向,重新设置子视图frame。
(3)此方法具有通用性。

4.iOS6及以后,上面提到的问题就不存在了。但是会碰到新的问题,具体介绍下小节介绍。

六、UIViewController中的翻转控制方法(iOS6以以后)

1.视图控制器类的shouldAutorotateToInterfaceOrientation:被废弃,增加了三个新的方法来实现这个方法的功能。
(1)shouldAutorotate:返回BOOL值,告诉控制器要不要支持翻转。
(2)supportedInterfaceOrientations:如果支持翻转,则告诉控制器要支持的设备方向。
    返回值类型为NSUInteger,通过UIInterfaceOrientationMaskXXX值之间的位或运算获得。
    此方法的默认返回值为:iPad--UIInterfaceOrientationMaskAll,iPhone--UIInterfaceOrientationMaskAllButUpsideDown。
(3)preferredInterfaceOrientationForPresentation:通知控制器通过present方法导入的控制器视图支持的方向。
    返回值为类型为UIInterfaceOrientation,也就是说此方法只支持返回一个方向。苹果文档的说明:当你的主界面支持两个及以上的方向,但是希望通过present弹出的界面只支持一个方向,则重写这个方法。如果不重写这个方法,此方法会默认返回状态栏所处的方向。

2.其它翻转控制的方法,两步翻转不能用了,一步翻转和之前一样。

3.supportedInterfaceOrientations的调用时机:
(1)当用户改变设备方向时,系统会调用此方法,但是只针对window的主视图或者推进类视图的顶层视图的控制器,比如导航控制器的非顶层视图的此方法默认是不起作用的。
(2)只有shouldAutorotate返回YES时才会被调用。

4.额外操作:
(1)由于supportedInterfaceOrientations的调用时机发生了变化,所以,如果我们需要让当前显示视图来控制整体方向,需要做一些额外的操作来处理这个问题。
(2)假如window的主视图是UIViewController类,则直接重写上面的方法,返回相应支持的方向即可。
(3)假如window的主视图是导航控制器,则需要重写它,让上面的三个方法返回topViewController对应方法的返回值,即由当前显示的视图来控制整体方向。比较好的实现是使用类别的方式。
(4)加入window的主视图是选项卡控制器,则需要重写它,让上面的三个方法返回selectedViewController对应方法的返回值,即由当前选择视图来控制整体方向,如果selectedViewController为一个导航控制器,则导航控制器又会找到其topViewController返回的值。也就是说,这是一个迭代取值的过程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/500120.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

三维转换矩阵解释

一、图解 二、单位矩阵{1.0f,0.0f,0.0f,0.0f;0.0f,1.0f,0.0f,0.0f;0.0f,0.0f,1.0f,0.0f;0.0f,0.0f,0.0f,1.0f;}

CoreAnimation编程指南(一)概念

一、概述1.核心动画是一套包含图形绘制,投影,动画的Objective–C类集合。它通过开发人员所熟悉的应用程序套件和Cocoa Touch视图架构的抽象分层模式,同时使用先进的合作效果提供了一套流畅的动画。2.动态的动画接口很难创建,但是核…

python实现常见排序算法

python实现常见排序算法 快速排序 思想&#xff1a;取出第一个元素把它放到序列的中间某一个正确位置&#xff0c;以它进行分割成左边和右边&#xff0c;再分别对左边和右边进行取元素分割&#xff08;递归&#xff09; 递归实现 def quicksort(array):if len(array) < …

CoreAnimation编程指南(二)渲染架构

1.虽然核心动画的图层和Cocoa的视图在很大程度上没有一定的相似性&#xff0c;但是他们两者最大的区别是&#xff0c;图层不会直接渲染到屏幕上。2.在模型-视图-控制器&#xff08;model-view-controller&#xff09;概念里面NSView和UIView是典型的视图部分&#xff0c;但是在…

学习递归

算法之递归 递归思想 递归就是函数自己调用自己&#xff0c;会使代码逻辑很清晰&#xff0c;但是Stack Overflow上有说的一句话&#xff1a;“如果使用循环&#xff0c;程序的性能可能更高&#xff1b;如果使用递归&#xff0c;程序可能更容易理解。如何选择要看什么对你来说…

CoreAnimation编程指南(三)几何变换

本章介绍图层的几何组成部分&#xff0c;及他们之间的相互关&#xff0c;同时介绍如何变换矩阵可以产生复杂的视觉效果。一、图层的坐标系1.图层的坐标系在不同平台上面具有差异性。在iOS系统中&#xff0c;默认的坐标系统原点在图层的中心左上角地方&#xff0c;原点向右和向下…

队列和栈

栈 一张图可以简单的说明 为了达到时间复杂度最低&#xff1a;选择的是python列表实现栈&#xff0c;而列表是顺序表 入栈push的时候选择在列表的尾部进行添加元素&#xff0c;出栈在列表尾部弹出 class Stack(object):"""栈"""def __init__(…

CoreAnimation编程指南(四)图层树结构

图层不但给自己提供可视化的内容和管理动画&#xff0c;而且充当了其他图层的容器类&#xff0c;构建图层层次结构。 本章介绍了图层层次结构&#xff0c;以及如何操纵该图层层次结构。一、什么是图层树的层次结构1.图层树是核心动画里面类似Cocoa视图的层次结构。比如一个NSVi…

学习散列表

回顾一下简单查找和二分查找 杂货店商品对应的价格举例&#xff1a; 简单查找就是拿出商品价目本&#xff0c;这个价目本并不是有序的&#xff0c;顾客问苹果多少钱&#xff0c;需要一个一个去查找某一个商品的价格&#xff0c;需要O(n)时间。 同样是一个价目本&#xff0c;但…

CoreAnimation编程指南(五)图层内容

当我们使用Cocoa的视图的时候&#xff0c;我们必须继承NSView或者UIView并且重载函数drawRect:来显示任何内容。但是CALayer实例可以直接使用&#xff0c;而无需继承子类。因为CALayer是一个键-值编码兼容的容器类&#xff0c;你可以在实例里面存储任意值&#xff0c;所以子类实…

SHA算法

回顾散列算法 我的上篇文章&#xff1a;学习散列表 在上篇文章杂货铺的示例中&#xff0c;我们希望散列函数的结果是均匀分布的。散列函数接受一个字符串&#xff0c;并返回一 个索引号。 安全散列算法&#xff08;secure hash algorithm&#xff0c; SHA&#xff09;函数 给…

python实现搜索之二分查找

搜索 搜索是在一个项目集合中找到一个特定项目的算法过程。搜索通常的答案是真的或假的&#xff0c;因为该项目是否存在。 搜索的几种常见方法&#xff1a;顺序查找、二分法查找、二叉树查找、哈希查找 二分法查找 二分查找又称折半查找&#xff0c;优点是比较次数少&#x…

CoreAnimation编程指南(九)图层布局

NSView提供了经典的“stuts and springs”模式&#xff0c;用于视图调整大小的时候把关联到它父图层的视图重新调整位置。图层支持该模式&#xff0c;而且Mac OS X上面的核心动画提供了一个更通用的布局管理器机制&#xff0c;允许开发者自己写他们自己的布局管理器。可以为图层…

数据库优化、数据库基础等常用知识点总结

建表优化 1&#xff09;数据库范式 第一范式&#xff08;1NF&#xff09;&#xff1a;强调的是列的原子性&#xff0c;即列不能够再分成其他几列。 如电话列可进行拆分—家庭电话、公司电话第二范式&#xff08;2NF&#xff09;&#xff1a;首先是 1NF&#xff0c;另外包含两…

一片文章概括大部分python面试基础常考题(部分有详解)

本片文章部分参考地址&#xff1a;https://segmentfault.com/a/1190000018737045 python是动态解释性的强类型定义语言 强类型&#xff1a;不允许不同类型相加。例如&#xff1a;整形字符串会报类型错误。 动态&#xff1a;不使用显示数据类型声明&#xff0c;且确定一个变量…

经典逻辑编程题(本文用python实现)

在一个二维数组中&#xff08;每个一维数组的长度相同&#xff09;&#xff0c;每一行都按照从左到右递增的顺序排序&#xff0c;每一列都按照从上到下递增的顺序排序。请完成一个函数&#xff0c;输入这样的一个二维数组和一个整数&#xff0c;判断数组中是否含有该整数。 思…

CoreData简介

一、概念 1.Core Data 是数据持久化存储的最佳方式 2.数据最终的存储类型可以是&#xff1a;SQLite数据库&#xff0c;XML&#xff0c;二进制&#xff0c;内存里&#xff0c;或自定义数据类型 3.好处&#xff1a;能够合理管理内存&#xff0c;避免使用sql的麻烦&#xff0c;高效…

NSZombieEnabled使用

我们做iOS 程序开发时经常用遇到 EXC_BAD_ACCESS 错误导致 Crash&#xff0c;出现这种错误时一般 Xcode 不会给我们太多的信息来定位错误来源&#xff0c;只是在应用 Delegate 上留下像Thread 1: Program received signal:"EXC_BAD_ACCESS"&#xff0c;让问题无从找起…

通过终端,查看sqlite3的存储文件

在调试应用的时候&#xff0c;可以查看数据库里的数据。 1、定位到模拟器的目录 cd ~/Library/Application\ Support/iPhone\ Simulator 2、查找文件名包含 OrgChart.sqlite的文件&#xff0c;并打印路径 find . -name "OrgChart.sqlite" –print 输出&#xff1a; .…

iOS的事件分发

移动平台上的开发主要关注数据以及数据的处理&#xff0c;事件的处理以及UI。所以事件的分发处理是很重要的一个环节&#xff0c;对于一个平台的优劣来说也是一项重要的参数。如果事件的分发设计的不好&#xff0c;一些复杂的UI场景就会变得很难写甚至没法写。从小屏没有触摸的…