【转】IOS屏幕旋转与View的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的信息,旋转一圈我们可以看到如下输出:

设备的初始方向是UIInterfaceOrientationPortrait的,然后顺时针依次经过LandscapeLeft,PortraitUpsideDown,LandscapeRight,最后再回到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,d为零的时候,x' = x + tx,y' = y + ty;即tx,ty分别代表x,y方向上的平移距离。
3)前面两种情况就可以实现缩放和平移了,那么旋转如何表示呢?
假设不做平移和缩放操作,那么从原坐标系中的一点(x,y)旋转α°以后到了新的坐标系中的一点(x',y'),那么旋转矩阵如下:

展开以后就是x' = xcosα - ysinα,y' = xsinα + ycosα;
实际应用中,我们将这些变化综合起来,即可完成所有二维的矩阵变化。现在我们在回过头来看看前面设备旋转时的输出,当设备位于Portrait的时候由于矩阵是标准矩阵,所以没有进行打印。当转到UIInterfaceOrientationLandscapeLeft方向的时候,我们的设备是顺时针转了90°,这个时候矩阵应该是(cos90°,sin90°,-sin90°,cos90°,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屏幕旋转与View的transform属性之间的关系,比较底层的更多相关文章
- iOS屏幕旋转 浅析
一.两种orientation 了解屏幕旋转首先需要区分两种orientation 1.device orientation 设备的物理方向,由类型UIDeviceOrientation表示,当前设备 ...
- IOS屏幕旋转思路和实践
这段时间同事在做一个直播项目,项目有个需求:一个界面需要手动设置屏幕的方向,设置好之后方向不能变化.完成这个需求花了特别大的精力,归因是网上关于屏幕旋转的知识比较凌乱,解决问题花费不少时间,最后决定把 ...
- ios 屏幕旋转的问题
在ios6之前我们旋转屏幕只需要实现shouldAutorotateToInterfaceOrientation就行了 - (BOOL)shouldAutorotateToInterfaceOrien ...
- iOS 屏幕旋转 nav+tabbar+present(网页) 2016
如题,最近一个app架构为 nav + tabbar ,需求是 在点击tabbar中的一个菜单项时,弹出网页,该网页需要横屏显示,其他页面不变 都保持竖屏. XCode Version 7.2.1 ...
- iOS屏幕旋转
三种方法 需求:全局主要是竖屏 个别界面需要横屏
- 《View Programming Guide for iOS》之frame、bounds和center之间的关系
The frame property contains the frame rectangle, which specifies the size and location of the view i ...
- 李洪强iOS开发之OC[018]对象和方法之间的关系
// // main.m // 18 - 对象和方法之间的关系 // // Created by vic fan on 16/7/14. // Copyright © 2016年 李洪强. A ...
- 【转】IOS设备旋转的内部处理流程以及一些【优化建议】
加速计是整个IOS屏幕旋转的基础,依赖加速计,设备才可以判断出当前的设备方向,IOS系统共定义了以下七种设备方向: typedef NS_ENUM(NSInteger, UIDeviceOrienta ...
- ios View之间的切换 屏幕旋转
6.3 View之间的切换 在上面的练习中我们通过移动组件的位置和调整组件的大小来处理横向与纵向的界面布局.但是在界面中有很多组件的时候,对每个组件都进行这样的操作确实是一个麻烦的事情.下面我们看看 ...
随机推荐
- Maven进价:Maven构建系列文章
Maven:基于Java平台的项目构建.依赖管理和项目信息管理. 1.构建 Maven标准化了构建过程 构建过程:编译.运行单元测试.生成文档.打包和部署 避免重复:设计.编码.文档.构建 2.依赖管 ...
- 整合ssh model $$_javassist_13 cannot be cast to javassist.util.proxy.Proxy
经goole stackoverflow 发现是 javassit 包冲突 项目使用的是maven 检查依赖包
- UBUNTU上的GIT SERVER
Git是一个开源的版本控制系统,由Linus Torvalds主导,用于支持Linux内核开发.每一个Git工作目录,都是一个完整的代码库,包含所有的提交历史.有能力跟踪所有的代码版本,而不会去依赖于 ...
- gcview使用
1.下载适用的版本 https://github.com/chewiebug/GCViewer Supported verbose:gc formats are: Oracle JDK 1.8 -Xl ...
- TF-IDF 简介
假设我们手头有大量的文档(或网页), 通常我们会比较关心以下几个问题: 1. 每一个文档的关键词(或主题词)包括哪些? 2. 给定一个(或一组)关键词,与这个(或组)词最相关的文档是哪一个? 3. ...
- iOS-微信支付(订单号重复的问题)
1. 官方文档中说过同一笔交易不能多次提交,出现这个错误让核实商户订单号是否重复提交,但是有些情况下是需要重复提交的,比如:用户微信支付的时候没有付款,直接取消了,那么订单如果已经创建了,在订单中心就 ...
- UWP开发入门(十九)——10分钟学会在VS2015中使用Git
写程序必然需要版本控制,哪怕是个人项目也是必须的.我们在开发UWP APP的时候,VS2015默认提供了对微软TFS和Git的支持.考虑到现在Git很火,作为微软系的程序员也不得不学一点防身,以免被开 ...
- json,serialize,msgpack比较
速度 在redis中存入同样的压缩数据,取操作执行两个操作: 1 从redis中取 2 解压 3 统一json压缩后放出 ab测试: [yejianfeng@openstack ~/httpd/u ...
- javascript之IE版本检测
近年来随着操作系统的升级以及各种新技术的开发普及,抛弃低版本IE已经是大势所趋,这对于前端人员来时是个好消息,可以不用花费太多的时间来做低版本的兼容,很多站点采用给予低版本IE以提示的方式(恩,很友好 ...
- LeetCode - 41. First Missing Positive
41. First Missing Positive Problem's Link ---------------------------------------------------------- ...