服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - IOS - iOS开发中使用屏幕旋转功能的相关方法

iOS开发中使用屏幕旋转功能的相关方法

2020-12-24 15:26一片枫叶 IOS

这篇文章主要介绍了iOS开发中使用屏幕旋转功能的相关方法,包括Transform变化矩阵原理的讲解,需要的朋友可以参考下

加速计是整个ios屏幕旋转的基础,依赖加速计,设备才可以判断出当前的设备方向,ios系统共定义了以下七种设备方向:
 

复制代码 代码如下:


typedef ns_enum(nsinteger, uideviceorientation) {

 

    uideviceorientationunknown,

    uideviceorientationportrait,            // device oriented vertically, home button on the bottom

    uideviceorientationportraitupsidedown,  // device oriented vertically, home button on the top

    uideviceorientationlandscapeleft,       // device oriented horizontally, home button on the right

    uideviceorientationlandscaperight,      // device oriented horizontally, home button on the left

    uideviceorientationfaceup,              // device oriented flat, face up

    uideviceorientationfacedown             // device oriented flat, face down

};


 
   以及如下四种界面方向:
 

复制代码 代码如下:


typedef ns_enum(nsinteger, uiinterfaceorientation) {

 

    uiinterfaceorientationportrait           = uideviceorientationportrait,

    uiinterfaceorientationportraitupsidedown = uideviceorientationportraitupsidedown,

    uiinterfaceorientationlandscapeleft      = uideviceorientationlandscaperight,

    uiinterfaceorientationlandscaperight     = uideviceorientationlandscapeleft

};

 

 
 
一、uikit处理屏幕旋转的流程 
 
  当加速计检测到方向变化的时候,会发出 uideviceorientationdidchangenotification 通知,这样任何关心方向变化的view都可以通过注册该通知,在设备方向变化的时候做出相应的响应。上一篇博客中,我们已经提到了在屏幕旋转的时候,uikit帮助我们做了很多事情,方便我们完成屏幕旋转。
 
  uikit的相应屏幕旋转的流程如下:
 
1、设备旋转的时候,uikit接收到旋转事件。
 
2、uikit通过appdelegate通知当前程序的window。
 
3、window会知会它的rootviewcontroller,判断该view controller所支持的旋转方向,完成旋转。
 
4、如果存在弹出的view controller的话,系统则会根据弹出的view controller,来判断是否要进行旋转。
 
 
 
二、uiviewcontroller实现屏幕旋转
 
  在响应设备旋转时,我们可以通过uiviewcontroller的方法实现更细粒度的控制,当view controller接收到window传来的方向变化的时候,流程如下:
 
1、首先判断当前viewcontroller是否支持旋转到目标方向,如果支持的话进入流程2,否则此次旋转流程直接结束。
 
2、调用 willrotatetointerfaceorientation:duration: 方法,通知view controller将要旋转到目标方向。如果该viewcontroller是一个container view controller的话,它会继续调用其content view controller的该方法。这个时候我们也可以暂时将一些view隐藏掉,等旋转结束以后在现实出来。
 
3、window调整显示的view controller的bounds,由于view controller的bounds发生变化,将会触发 viewwilllayoutsubviews 方法。这个时候self.interfaceorientation和statusbarorientation方向还是原来的方向。
 
4、接着当前view controller的 willanimaterotationtointerfaceorientation:duration: 方法将会被调用。系统将会把该方法中执行的所有属性变化放到动animation block中。
 
5、执行方向旋转的动画。
 
6、最后调用 didrotatefrominterfaceorientation: 方法,通知view controller旋转动画执行完毕。这个时候我们可以将第二部隐藏的view再显示出来。
 
  整个响应过程如下图所示:
iOS开发中使用屏幕旋转功能的相关方法
以上就是uikit下一个完整的屏幕旋转流程,我们只需要按照提示做出相应的处理就可以完美的支持屏幕旋转。
 
 
 
三、注意事项和建议
 
  1)注意事项
 
  当我们的view controller隐藏的时候,设备方向也可能发生变化。例如view controller a弹出一个全屏的view controller b的时候,由于a完全不可见,所以就接收不到屏幕旋转消息。这个时候如果屏幕方向发生变化,再dismiss b的时候,a的方向就会不正确。我们可以通过在view controller a的viewwillappear中更新方向来修正这个问题。
 
  2)屏幕旋转时的一些建议
 •在旋转过程中,暂时界面操作的响应。
 •旋转前后,尽量当前显示的位置不变。
 •对于view层级比较复杂的时候,为了提高效率在旋转开始前使用截图替换当前的view层级,旋转结束后再将原view层级替换回来。
 •在旋转后最好强制reload tableview,保证在方向变化以后,新的row能够充满全屏。例如对于有些照片展示界面,竖屏只显示一列,但是横屏的时候显示列表界面,这个时候一个界面就会显示更多的元素,此时reload内容就是很有必要的。

ios:屏幕旋转与transform
itouch,iphone,ipad设置都是支持旋转的,如果我们的程序能够根据不同的方向做出不同的布局,体验会更好。
 
  如何设置程序支持旋转呢,通常我们会在程序的info.plist中进行设置supported interface orientations,添加我们程序要支持的方向,而且程序里面每个viewcontroller也有方法
 
  supportedinterfaceorientations(6.0及以后)
 
  shouldautorotatetointerfaceorientation(6.0之前的系统)
 
  通过viewcontroller的这些方法,我们可以做到更小粒度的旋转控制,如程序中仅仅允许个别界面旋转。

 
 
 
一、屏幕旋转背后到底做了什么呢?
 
  下面我们看个简单的例子,用xcode新建一个默认的单视图工程,然后在对应viewcontroller的响应旋转后的函数中输出一下当前view的信息,代码如下:
 

复制代码 代码如下:


svrotateviewcontroller

 

//
//  svrotateviewcontroller.m
//  svrotatebytransform
//
//  created by  maple on 4/21/13.
//  copyright (c) 2013 maple. all rights reserved.
//

#import "svrotateviewcontroller.h"

@interface svrotateviewcontroller ()

@end

@implementation svrotateviewcontroller

- (void)viewdidload
{
    [super viewdidload];
    // do any additional setup after loading the view, typically from a nib.
   
    self.view.backgroundcolor = [uicolor graycolor];
}

- (void)didreceivememorywarning
{
    [super didreceivememorywarning];
    // dispose of any resources that can be recreated.
}

- (bool)shouldautorotatetointerfaceorientation:(uiinterfaceorientation)interfaceorientation
{
    return yes;
}

- (bool)shouldautorotate
{
    return yes;
}

- (nsuinteger)supportedinterfaceorientations
{
    return uiinterfaceorientationmaskall;
}

- (void)willrotatetointerfaceorientation:(uiinterfaceorientation)tointerfaceorientation duration:(nstimeinterval)duration
{
    nslog(@"uiviewcontroller will rotate to orientation: %d", tointerfaceorientation);
}

- (void)didrotatefrominterfaceorientation:(uiinterfaceorientation)frominterfaceorientation
{
    nslog(@"did rotated to new orientation, view information %@", self.view);
}

@end

 

  查看代码我们可以发现,我们的viewcontroller支持四个方向,然后在旋转完成的didrotatefrominterfaceorientation函数中打印了self.view的信息,旋转一圈我们可以看到如下输出:
iOS开发中使用屏幕旋转功能的相关方法
二、什么是transform
 
  transform(变化矩阵)是一种3×3的矩阵,如下图所示:
iOS开发中使用屏幕旋转功能的相关方法
通过这个矩阵我们可以对一个坐标系统进行缩放,平移,旋转以及这两者的任意组着操作。而且矩阵的操作不具备交换律,即矩阵的操作的顺序不同会导致不同的结果。uiview有个transform的属性,通过设置该属性,我们可以实现调整该view在其superview中的大小和位置。
 
  矩阵实现坐标变化背后的数学知识:
iOS开发中使用屏幕旋转功能的相关方法
设x,y分别代表在原坐标系统中的位置,x',y'代表通过矩阵变化以后在新的系统中的位置。其中式1就是矩阵变化的公式,对式1进行展开以后就可以得到式2。从式2我们可以清楚的看到(x,y)到(x',y')的变化关系。
 
  1)当c,b,tx,ty都为零时,x' = ax,y' = by;即a,d就分别代表代表x,y方向上放大的比例;当a,d都为1时,x' = x,y' = y;这个时候这个矩阵也就是传说中的cgaffinetransformidentity(标准矩阵)。
 
  2)当a,d为1,c,b为零的时候,x' = x + tx,y' = y + ty;即tx,ty分别代表x,y方向上的平移距离。
 
  3)前面两种情况就可以实现缩放和平移了,那么旋转如何表示呢?
 
  假设不做平移和缩放操作,那么从原坐标系中的一点(x,y)旋转α°以后到了新的坐标系中的一点(x',y'),那么旋转矩阵如下:
iOS开发中使用屏幕旋转功能的相关方法
展开以后就是x' = xcosα - ysinα,y' = xsinα + ycosα;
 
 
 
  实际应用中,我们将这些变化综合起来,即可完成所有二维的矩阵变化。现在我们在回过头来看看前面设备旋转时的输出,当设备位于portrait的时候由于矩阵是标准矩阵,所以没有进行打印。当转到uiinterfaceorientationlandscapeleft方向的时候,我们的设备是顺时针转了90°(逆时针为正,顺时针为负),这个时候矩阵应该是(cos-90°,sin-90°,-sin-90°,cos-90°,tx,ty),由于未进行平移操作所以tx,ty都为0,刚好可以跟我们控制台输出:"<uiview: 0x8075390; frame = (0 0; 320 480); transform = [0, -1, 1, 0, 0, 0]; autoresize = w+h; layer = <calayer: 0x8074980>>"一致。观察其他两个方向的输出,发现结果均和分析一致。
 
  由此可以发现屏幕旋转其实就是通过view的矩阵变化实现,当设备监测到旋转的时候,会通知当前程序,当前程序再通知程序中的window,window会通知它的rootviewcontroller的,rootviewcontroller对其view的transform进行设置,最终完成旋转。
 
  如果我们直接将一个view添加到window上,系统将不会帮助我们完成旋操作,这个时候我们就需要自己设置该view的transform来实现旋转了。这种情况虽然比较少,但是也存在的,例如现在很多app做的利用状态栏进行消息提示的功能就是利用自己创建window并且自己设置transform来完成旋转支持的,下一篇博客会介绍如何实现这种消息通知。

延伸 · 阅读

精彩推荐
  • IOS解析iOS开发中的FirstResponder第一响应对象

    解析iOS开发中的FirstResponder第一响应对象

    这篇文章主要介绍了解析iOS开发中的FirstResponder第一响应对象,包括View的FirstResponder的释放问题,需要的朋友可以参考下...

    一片枫叶4662020-12-25
  • IOSIOS 屏幕适配方案实现缩放window的示例代码

    IOS 屏幕适配方案实现缩放window的示例代码

    这篇文章主要介绍了IOS 屏幕适配方案实现缩放window的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    xiari5772021-06-01
  • IOS关于iOS自适应cell行高的那些事儿

    关于iOS自适应cell行高的那些事儿

    这篇文章主要给大家介绍了关于iOS自适应cell行高的那些事儿,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    daisy6092021-05-17
  • IOSiOS通过逆向理解Block的内存模型

    iOS通过逆向理解Block的内存模型

    自从对 iOS 的逆向初窥门径后,我也经常通过它来分析一些比较大的应用,参考一下这些应用中某些功能的实现。这个探索的过程乐趣多多,不仅能满足自...

    Swiftyper12832021-03-03
  • IOSIOS开发之字典转字符串的实例详解

    IOS开发之字典转字符串的实例详解

    这篇文章主要介绍了IOS开发之字典转字符串的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握这样的方法,需要的朋友可以参考下...

    苦练内功5832021-04-01
  • IOSiOS 雷达效果实例详解

    iOS 雷达效果实例详解

    这篇文章主要介绍了iOS 雷达效果实例详解的相关资料,需要的朋友可以参考下...

    SimpleWorld11022021-01-28
  • IOSiOS中tableview 两级cell的展开与收回的示例代码

    iOS中tableview 两级cell的展开与收回的示例代码

    本篇文章主要介绍了iOS中tableview 两级cell的展开与收回的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    J_Kang3862021-04-22
  • IOSiOS布局渲染之UIView方法的调用时机详解

    iOS布局渲染之UIView方法的调用时机详解

    在你刚开始开发 iOS 应用时,最难避免或者是调试的就是和布局相关的问题,下面这篇文章主要给大家介绍了关于iOS布局渲染之UIView方法调用时机的相关资料...

    windtersharp7642021-05-04