文档章节

IOS旋转-第二弹

小春0618
 小春0618
发布于 2014/05/08 14:06
字数 1637
阅读 152
收藏 3

IOS:屏幕旋转与Transform

 

  iTouch,iPhone,iPad设置都是支持旋转的,如果我们的程序能够根据不同的方向做出不同的布局,体验会更好。

  如何设置程序支持旋转呢,通常我们会在程序的info.plist中进行设置Supported interface orientations,添加我们程序要支持的方向,而且程序里面每个viewController也有方法

  supportedInterfaceOrientations(6.0及以后)

  shouldAutorotateToInterfaceOrientation(6.0之前的系统)

  通过viewController的这些方法,我们可以做到更小粒度的旋转控制,如程序中仅仅允许个别界面旋转。

 

一、屏幕旋转背后到底做了什么呢?

  下面我们看个简单的例子,用xcode新建一个默认的单视图工程,然后在对应viewController的响应旋转后的函数中输出一下当前view的信息,代码如下:

////  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的信息,旋转一圈我们可以看到如下输出:

  设备的初始方向是UIInterfaceOrientationPortrait的,然后顺时针依次经过LandscapeLeftPortraitUpsideDownLandscapeRight,最后再回到UIInterfaceOrientationPortrait方向。仔细看的话我们会发现在旋转的过程中,除了frame之外,Transform也在一直变化。观察frame发现,它的变化应该是由于系统的状态栏引起的。于是将系统状态栏隐藏掉,在输出发现frame果然不再变化。因此我们可以怀疑屏幕旋转是通过变化Transform实现的。

 

二、什么是Transform

  Transform(变化矩阵)是一种3×3的矩阵,如下图所示:

  通过这个矩阵我们可以对一个坐标系统进行缩放,平移,旋转以及这两者的任意组着操作。而且矩阵的操作不具备交换律,即矩阵的操作的顺序不同会导致不同的结果。UIView有个transform的属性,通过设置该属性,我们可以实现调整该view在其superView中的大小和位置。

  矩阵实现坐标变化背后的数学知识:

  设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'),那么旋转矩阵如下:

  

  展开以后就是x' = xcosα - ysinα,y' = xsinα + ycosα;

 

  实际应用中,我们将这些变化综合起来,即可完成所有二维的矩阵变化。现在我们在回过头来看看前面设备旋转时的输出,当设备位于Portrait的时候由于矩阵是标准矩阵,所以没有进行打印。当转到UIInterfaceOrientationLandscapeLeft方向的时候,我们的设备是顺时针转了90&deg;(逆时针为正,顺时针为负),这个时候矩阵应该是(cos-90&deg;,sin-90&deg;,-sin-90&deg;,cos-90&deg;,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的矩阵变化实现,当设备监测到旋转的时候,会通知当前程序,当前程序再通知程序中的windowwindow会通知它的rootViewController的,rootViewController对其viewtransform进行设置,最终完成旋转。

  如果我们直接将一个view添加到window上,系统将不会帮助我们完成旋操作,这个时候我们就需要自己设置该viewtransform来实现旋转了。这种情况虽然比较少,但是也存在的,例如现在很多App做的利用状态栏进行消息提示的功能就是利用自己创建window并且自己设置transform来完成旋转支持的,下一篇博客会介绍如何实现这种消息通知。

上述内容引自:http://www.cnblogs.com/smileEvday/archive/2013/04/23/3038887.html


**************************** 我是分割线 ******************************

旋转矩阵一些基础知识,当时也是看到矩阵,脑子有点懵了,感觉大学学过的矩阵知识已经被遗忘的差不多了,因此将研究过程要点简单录一下

首先是高中的一些正余弦相关的公式

cos(A+B) = cosAcosB - sinAsinB

cos(A-B) = cosAcosB + sinAsinB

sin(A+B) = sinAcosB + cosAsinB

sin(A-B) = sinAcosB - cosAsinB

下面简单描述下在直角坐标系中单点1(x,y)逆时针旋转A角度后到点2(x',y'),二维旋转矩阵为:

 cosA   sinA

-sinA   cosA

这里仅证明点1、2都在第一象限的情况,其余情况大同小异;

证明过程:假设点1与X轴的夹角为B,点1到原点的距离为z,则x'=cos(A+B)z = z(cosAcosB - sinAsinB) ,由于cosB*z = x,sinB*z = y,则x' = cosAx-sinAy,

同理可证y' = sinAx+cosAy,由矩阵乘法可知:

(x',y') = (x,y) 乘以上述矩阵;


© 著作权归作者所有

共有 人打赏支持
小春0618
粉丝 8
博文 40
码字总数 10552
作品 0
海淀
程序员
加载中

评论(1)

南方小伙
南方小伙
学习
移动端iOS PWA存在的“坑”

最近,我在开发PWA时,发现iOS端存在诡异的问题。 一、症状 竖屏时,内容显示正常,状态栏为显示状态 第一次横屏(-90°或90°)----- 内容显示正常,状态栏被隐藏 从90°旋转至-90°,或从-...

ceshu
08/02
0
0
iOS 6.0旋转兼容的那点事

这两天问答系统里,问ios横竖屏切换、还有状态栏旋转的问题有点多,来些小心得,希望遇到的人少走弯路; 先贴官方说明: iOS 6.0 Release Notes: Autorotation is changing in iOS 6. In iOS...

董桉远
2013/04/07
0
1
iOS Simulator功能介绍关于Xamarin IOS开发

iOS Simulator功能介绍关于Xamarin IOS开发 iOS Simulator功能介绍 在图1.38所示的运行效果中,所见到的类似于手机的模型就是iOS Simulator。在没有iPhone或iPad设备时,可以使用iOS Simulat...

大学霸
2015/04/17
0
0
iOS 11开发教程(四)iOS11模拟器介绍一

iOS11模拟器介绍 在图1.6或者1.7中所看到的类似于手机的模型就是iOS模拟器。iOS模拟器是在没有iPhone或iPad设备时,对程序进行检测的设备。iOS模拟器可以模仿真实的iPhone或iPad等设备的一些...

大学霸
2017/10/24
0
0
iO6 Programming pushing the limits 阅读笔记

目录 第一部分 iOS6新内容 第二部分 从每天工具中获取更多(介绍日常使用控件和框架的潜力) 第三部分 完成任务的正确工具(介绍不是那么常用的控件和框架) 第四部分 发挥到极限(深入理解i...

云飞扬v5
2015/11/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

困扰当前数据中心管理的三大难题

导读 当企业发展到一定程度,或者之前的机房不能满足现在的数据中心使用时,企业会对数据中心进行迁移。那么在数据中心进行迁移的时候会遇到哪些风险呢?针对这些风险我们应该做出怎样的措施来...

问题终结者
4分钟前
0
0
设计模式:工厂方法模式(工厂模式)

工厂方法模式才是真正的工厂模式,前面讲到的静态工厂模式实际上不能说是一种真正意义上的设计模式,只是一种变成习惯。 工厂方法的类图: 这里面涉及到四个种类: 1、抽象产品: Product 2、...

京一
21分钟前
0
0
区块链和数据库,技术到底有何区别?

关于数据库和区块链,总会有很多的困惑。区块链其实是一种数据库,因为他是数字账本,并且在区块的数据结构上存储信息。数据库中存储信息的结构被称为表格。但是,区块链是数据库,数据库可不...

HiBlock
28分钟前
0
0
react native 开发碰到的问题

react-navigation v2 问题 问题: static navigationOptions = ({navigation, navigationOptions}) => ({ headerTitle: ( <Text style={{color:"#fff"}}>我的</Text> ), headerRight: ( <View......

罗培海
35分钟前
0
0
Mac Docker安装流程

久仰Docker大名已久,于是今天趁着有空,尝试了一下Docker 先是从docker的官网上下载下来mac版本的docker安装包,安装很简易,就直接拖图标就好了。 https://www.docker.com/products/docker...

writeademo
43分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部