界面旋转
本周有需求使某个数据展示界面支持旋转90°,实现横屏展示。产品要求根据按钮点击来实现旋转,并非根据设备的方向自动控制,且界面层级较多,包裹于另外的容器VC中。综合分析后决定使用View的transform实现。
如果单纯考虑旋转界面,实现非常简单,给想要旋转的View的transform属性赋予相应的值就行了。Transform属性是CGAffineTransform结构类型的,CGAffineTransform是Core Graphics中定义的一个结构体,本身定义是
CGAffineTransform:一个用来绘制2D图形的仿射变化矩阵
它使用一个3×3的矩阵表示:
图形使用某个CGAffineTransform来变换,即是使图形中的每个坐标点的值都与CGAffineTransform矩阵相乘,得出的点组成的图形就是变换后的图形。
而在实际使用中,我们一般不会自己定义这种矩阵,而是依次使用系统定义的函数
- CGContextTranslateCTM(移动)
- CGContextScaleCTM(缩放)
- CGContextRotateCTM(旋转)
这些函数是将变换直接作用于自身的第一个入参(CGContextRef类型的参数,指图形上下文)。
回归我们最初旋转View的问题,View的transform属性,即是一个CGAffineTransform结构类型的值,我们需要的是一个可以便捷生成CGAffineTransform结构的方法,这里可以使用
-
CGAffineTransformMakeTranslation(移动)
-
CGAffineTransformMakeScale(缩放)
-
CGAffineTransformMakeRotation(旋转)
对我个人这个需求而言,是先将界面向上平移:CGAffineTransformMakeTranslation(0, 7),再顺时针旋转90°:CGAffineTransformMakeRotation(M_PI_2),可以通过CGAffineTransformConcat方法将两个变化组合起来CGAffineTransformConcat( t1, t2 )。最后将值赋予View的transform属性即可。view.transform = CGAffineTransformConcat( t1, t2 )。
CGAffineTransform rotateTrans = CGAffineTransformMakeRotation(M_PI_2);
CGAffineTransform moveTrans = CGAffineTransformMakeTranslation(0, 7);
self.view.transform = CGAffineTransformConcat(rotateTrans, moveTrans);
以上初步实现对View的整体旋转,但是子View的frame实际上展示是有问题的,尽管子View也转动了90°,但仍然保持了旋转前的frame值,所以要根据旋转后的View的大小重新设置一下子View的frame,这里旋转后的View的宽已经是手机屏幕的长边长度,View的高则是手机屏幕的宽度。
旋转后如果想要恢复旋转前的效果,则处理相应简单,给View的transform属性赋值CGAffineTransformIdentity即可,CGAffineTransformIdentity定义了View本身的变化值,我个人理解为初始值。
self.view.transform = CGAffineTransformIdentity;
当然,子View的frame也要设置回原值。
这样,就通过View的transform属性,简单实现了屏幕旋转的效果。