不好意思,這一篇間隔的時間有點長,最近實在是事情太多,耽擱了,好了,長話短說,下面繼續學習ios。
這次學習的內容是Autorotation和Autosizing,Autorotation就是屏幕內容自動旋轉,因為iphone有重力感應系統(陀螺儀???),屏幕的內容會隨着用戶手握iphone的方式(豎着握Portrait、橫着握Landscape)而改變,這個相信大家都已經有所體會,Autosizing是指當iphone的屏幕旋轉后,屏幕里面控件的大小和位置也會自動改變。好了,下面跟着例子繼續學習。
1)創建一個Single View項目,並命名為Autosize。
2)配置app所支持的旋轉方向
當完成一個項目創建后,默認狀態下,在Project Navigator中,會選中項目的根節點,如下
當根節點選中后,在其右側Summary tab中找到叫做“Supported Device Orientations”(設備所支持的方向)的區域,在這個區域中,就是用來設置iphone所支持的旋轉方向的。
可以看到,一共有4個方向(其實也只有這4個方向),根據進行設置,在我們的這個例子中,就保持默認狀態即可,一般情況下,app很少會去選擇“Upside Down”,一般來說很少有人會倒着拿手機,除了有特殊情況外。
除了上面的方法可以設置app支持的旋轉方向外,還有一個地方可以設置,在Project Navigator中的“Supporting Files”下,選中Autosize-Info.plist。
然后找到“Supported interface Orientations”並展開,會看到3個Item,分別對應剛才圖中選中的三個旋轉方向
如果想要添加一個新的方向,只要鼠標放在某一個Item上,在這個Item的右邊會有一個加號和一個減號,點擊加號增加一個Item,點擊減號刪除一個Item。
可以隨意添加或者刪除里面的Item,然后在回到Summary tab中看,Summary tab中的“Supported Device Orientations”會隨之改變,這兩個地方是保持聯動的,其實xxx-Info.plist和Summary tab是同一個東西,只是顯示的方法不同,Summary tab使用圖形界面控制,xxx-Info.plist使用文字。
3)代碼中判斷app是否支持某種旋轉方向
在BIDViewController.m中,有一個默認的方法叫做shouldAutorotateToInterfaceOrientation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); }
當支持某種旋轉方向時,返回YES,不支持返回NO,ios為4個旋轉方向分別定義了4個常量用來做判斷
UIInterfaceOrientationPortrait
UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
當iphone改變當前的方向時,首先會調用到該方法進行判斷,判斷app是否支持當前的方向,如果支持返回YES,則繼續執行旋轉操作,如果不支持,則返回NO,接下來的操作就不繼續進行了。(但是這里有個問題,到底是以shouldAutorotateToInterfaceOrientation判斷為准還是以Supported Device Orientations中設置的旋轉方向為准的?這個在本篇的最后我會去做一個實驗驗證一下。)
4)添加6個button
選中BIDViewController.xib,如下圖添加6個button並命名,6個button分別位於左上、左中、左下、右上、右中、右下
(2種添加按鈕的方法:一,一個一個從object library拖進來;二,先從object library中拖進來一個,然后按住option鍵,鼠標點擊一個按鈕不放並拖動,就可以復制一個按鈕了。)
5)編譯運行,測試旋轉效果
啟動時的默認效果
旋轉(選擇菜單Hardware->Rotate Left或者command+>)后效果
問題出來了,屏幕旋轉后,按鈕是旋轉了,但是相對位置(相對於屏幕左邊和頂部的距離)沒有改變,因此除了"UL"button之外,其他所有的button的位置都是不對的,更何況LL和LR兩個button不見了!解決這個問題的方法就是是Autosizing。
6)使用Autosize屬性
還是選則BIDViewController.xib,然后選中UL按鈕,使用快捷鍵command+5,打開size inspector(就在attributes inspector的右邊,你也可以直接用鼠標去選)
從上圖中可以看到Autosizing屬性是一個由兩個正方形組成的圖
大的一個正方形表示iphone屏幕的4條邊,中間小的正方形表示對象自己,我們選中的是UL按鈕,則中間小的正方形就表示UL按鈕。然后在小正方形和大正方形之間,有4個“工”,分別表示當前對象距離iphone屏幕4條邊的距離是否發生改變,選中表示固定不變(在我們的這個例子中,需要用這個特性來固定按鈕的相對位置)。小正方形中間的十字表示是否上下、左右進行拉伸(在我們的這個例子中,這個特性按時不用,不過自己可以試試看)。
(在Autosizing的右邊,有一個Example圖,當鼠標移動到Autosizing這塊區域上時,里面會動態呈現當前對象相對位置狀況,方便設置屬性。)
根據上面的描述,我們分別設置6個按鈕的Autosizing如下
(此圖截於pdf,因此不太清晰)
UL:固定左邊和上邊
UR:固定上邊和右邊
L:固定左邊
R:固定右邊
LL:固定左邊和下邊
LR:固定下邊后右邊
7)再次編譯運行,測試旋轉效果
下圖是iphone橫過來時的效果
所有的按鈕都各司其位,達到了我們想要的效果。
8)問題再次出現
我們好不容易將旋轉后按鈕位置的問題搞定,新的問題又出現了,我們將6個按鈕的大小都設置成125*125(同時選中6個按鈕,在Size inspector中設置Width=125,Height=125,然后重新調整6個按鈕的位置),如下
編譯運行,並旋轉屏幕,問題出現了
按鈕疊加在了一起,對於這個問題,我們再怎么調整Autosizing屬性,都是無法解決的,因為按鈕過大,所以在屏幕橫過來的時候,無法很好的擺放其位置,解決這個問題的方法是寫代碼,當iphone旋轉時,改變按鈕位置。
9)創建Outlet
這個工作應該已經很熟悉了,分別為6個按鈕創建Outlet,創建完成后的BIDViewController.h代碼如下
#import <UIKit/UIKit.h> @interface BIDViewController : UIViewController @property (strong, nonatomic) IBOutlet UIButton *buttonUL; @property (strong, nonatomic) IBOutlet UIButton *buttonUR; @property (strong, nonatomic) IBOutlet UIButton *buttonL; @property (strong, nonatomic) IBOutlet UIButton *buttonR; @property (strong, nonatomic) IBOutlet UIButton *buttonLL; @property (strong, nonatomic) IBOutlet UIButton *buttonLR; @end
10)在BIDViewController.m中重載willAnimateRotationToInterfaceOrientation方法
willAnimateRotationToInterfaceOrientation發生在一個旋轉發生之后且旋轉動畫還未發生之前(好吧,旋轉的細節我還不是很清楚,但是可知的是,一定有一個事件是發生在旋轉開始后還未結束前的,且旋轉是有動畫的,而這個事件就是發生在旋轉開始后,且旋轉動畫還未開始之前的那段時間里面),會被自動調用。完整code如下
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { if(UIInterfaceOrientationIsPortrait(toInterfaceOrientation)) { buttonUL.frame = CGRectMake(20, 20, 125, 125); buttonUR.frame = CGRectMake(175, 20, 125, 125); buttonL.frame = CGRectMake(20, 168, 125, 125); buttonR.frame = CGRectMake(175, 168, 125, 125); buttonLL.frame = CGRectMake(20, 315, 125, 125); buttonLR.frame = CGRectMake(175, 315, 125, 125); } else { buttonUL.frame = CGRectMake(20, 20, 125, 125); buttonUR.frame = CGRectMake(20, 155, 125, 125); buttonL.frame = CGRectMake(177, 20, 125, 125); buttonR.frame = CGRectMake(177, 155, 125, 125); buttonLL.frame = CGRectMake(328, 20, 125, 125); buttonLR.frame = CGRectMake(328, 155, 125, 125); } }
稍微解釋一下,frame屬性是用來描述當前視圖在其父視圖中的位置和大小,buttonUL.frame就是用來描述該button在其父視圖(View)中的位置和大小,其中位置是CGPoint,大小是CGSize,他們在ios中的聲明是這樣的
struct CGPoint { CGFloat x; CGFloat y; }; typedef struct CGPoint CGPoint; struct CGSize { CGFloat width; CGFloat height; }; typedef struct CGSize CGSize;
很容易理解。在ios中還有一個類型將CGPoint和CGSize組合在一起,這個就是CGRect
struct CGRect { CGPoint origin; CGSize size; }; typedef struct CGRect CGRect;
上面代碼中的buttonUL.frame = CGRectMake(20, 20, 125, 125)就是用來設定buttonUL在其父視圖(View)中的位置,CGRectMake中前2個參數其實是CGPoint,buttonUL的左上角的起始點,后兩個參數其實是CGRect,設定buttonUL的高和寬。
編譯運行旋轉
當iphone旋轉后,6個按鈕的位置還是擺放的很合適,good!
11)shouldAutorotateToInterfaceOrientation判斷為准還是以Supported Device Orientations判斷為准
本篇文章中所有的開發都已經完成,最后對這個遺留問題做一個實驗,看看到底是以什么為准,打開BIDViewController.m,修改shouldAutorotateToInterfaceOrientation方法如下
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown && interfaceOrientation != UIInterfaceOrientationLandscapeLeft); }
當interfaceOrientation的方向為UIInterfaceOrientationPortraitUpsideDown或者UIInterfaceOrientationLandscapeLeft,app的視圖都不進行改變,然后編譯運行程序,效果如下
視圖沒有變哦,通過實驗發現還是以code為准,這個在以后寫代碼的過程中應該多加留意。
12)總結
這篇內容對iphone的旋轉功能有了一個初步的認識,對iphone旋轉后,界面的布局有了一個淺顯的描述,一般來說有3種方法來改變iphone旋轉后界面需要重新布局的問題:
1、使用Autosizing
2、寫code
3、重新弄個View,替換原先的View(這個方法下一章會學習)
總的來說這次的內容還是很有用的,每個app都會遇到,除非你的app不支持旋轉。