<a href="http://www.cnblogs.com/smileEvday/archive/2013/04/23/Rotate1.html">IOS:螢幕旋轉與Transform</a>
iTouch,iPhone,iPad設定都是支援旋轉的,如果我們的程式能夠根據不同的方向做出不同的布局,體驗會更好。
如何設定程式支援旋轉呢,通常我們會在程式的info.plist中進行設定Supported interface orientations,添加我們程式要支援的方向,而且程式裡面每個viewController也有方法
supportedInterfaceOrientations(6.0及以後)
shouldAutorotateToInterfaceOrientation(6.0之前的系統)
通過viewController的這些方法,我們可以做到更小粒度的旋轉控制,如程式中僅僅允許個别界面旋轉。
一、螢幕旋轉背後到底做了什麼呢?
下面我們看個簡單的例子,用xcode建立一個預設的單視圖工程,然後在對應viewController的響應旋轉後的函數中輸出一下目前view的資訊,代碼如下:
SvRotateViewController
檢視代碼我們可以發現,我們的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,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°(逆時針為正,順時針為負),這個時候矩陣應該是(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來完成旋轉支援的,下一篇部落格會介紹如何實作這種消息通知。
注:轉載請注明出處!歡迎大家加我QQ 1592232964,一起讨論共同進步。
部門招人: 進階iOS、Android、前端開發,有意私聊,部落客請你喝️
如果覺得本文幫到了你,記得點贊哦,當然也可以請部落客喝一杯豆漿
微信二維碼
QQ二維碼