既然不好用又醜,乾脆手工打造一個可以適用所有iOS版本又漂亮的ActionSheet吧
(8之後已改用UIAlertController,為了方便本文統一稱呼ActionSheet)
如果對專案實作方式沒有興趣,只想使用~請到我的GitHub吧 :)
How To Customize ?
準備要打造的ActionSheet,希望能符合下列需求
1. 選項要可以帶文字&圖片
2. 樣式編排要仿照目前最新版iOS 8,樣式要相同有幾點要注意
2.1 要有Title
2.2 除了ActionSheet以外,整個背景都要帶半透明灰底
2.3 ActionSheet要整個展開,不可出現TableView的scroll形式
3. 行為模式也要仿照,要做到相同效果有幾點要注意
3.1 ActionSheet要以"滑出"的效果出現
3.1 ActionSheet要以"滑出"的效果出現
3.2 若未選中任何選項,而是touch半透明灰底背景,必須以往下收闔的動畫效果關閉ActionSheet
3.3 ActionSheet被選中的選項要能觸發事件。觸發要透過delegate傳遞到前端,不可寫出高耦合性的view
3.3 ActionSheet被選中的選項要能觸發事件。觸發要透過delegate傳遞到前端,不可寫出高耦合性的view
接下來的實作,會產生三個一組的h、m、xib檔案,這一組以後就是可以重複使用且適用所有版本的ActionSheet
● xib file
觀察前述需求,xib需要灰背景、放選項清單的TableView、能偵測灰背景被按到的gesture
View:選上圖的View,設定Background(需求2.2)
TableView:設定delegate與dataSources(藍框),建立table的連結至h檔的"*actionView"(紅框)
Gesture:將gesture連結至前面設灰背景的View(需求3.2)
● h file
h檔程式碼如下
首先看Line17~25
Line 17:用來當作ActionSheet列表的Table要塞資料,且按下不同item要觸發事件,故此處需實作UITableViewDelegate, UITableViewDataSource
Line 18:method 'setData' 是為了賦予TableView資料,也就是ActionSheet所呈現的選項
Line 19:method 'setTitle' 用來設定ActionSheet標題
Line 21:property '*actionView' 是透過IB(Interface Builder)設定的TableView連結
Line 22:property '*actionItems' 用來存放'setData'傳進來的值
Line 24:property 'delegateOfAction' 是為了委派,簡單來說其他外部class想要透過CustomActionSheet去幫他做事,甚至取得後續資訊,那麼就要將自己指定為 'delegateOfAction' 這個動態型別(如何指定會在之後談到)
ps:如果delegate的概念對你來說太吃力,請參考這篇iOS學習_實作自己的delegate來傳值
再來看Line12~15
Line 14:剛剛提到透過委派(delegate)可以請別人做事,甚至傳遞資訊 。本文的ActionSheet會將被選中item資訊返回,所以定義一個回傳資料id或index的method 'actionSelected:(NSString*) itemIdOrIndex'
● m file
1. 實作View的進場效果,與按下View觸發gesture event後的退場效果(需求3.1 & 3.2)
gesture當然是透過委派
viewWillAppear作二件事:註冊gesture,讓畫面進場(參考稍後的 'slideIn' method)
撰寫進場/退場method,特別注意的是退場method 'slideOut' 會用在二個情境,按下灰背景View與選中TableView選項
2. 塞資料
指派TableView資料(Line 74~76)與Title資料(Line 78~80)
3. 為滿足需求2.3,必須動態指定TableView高度,且Title(需求2.1)我打算用TableView Header來實踐(Header高度也必須算進去)。以下一併實現需求2.1 & 2.3
在viewDidLayoutSubViews呼叫method 'adjustHeight' 依照資料筆數計算高度並指定給TableView
計算時依據是否有Title(Line 127)決定高度是否要加上Header高度
4. 實作UITableViewDataSource二個required method
5. 實作TableView項目被選中
TableView被選中(也就是user認為的ActionSheet)除了讓整個View退場,還要透過h檔宣告的 'actionSelected:(NSString*) itemIdOrIndex' method將選中的資訊回傳(Line 65~72)
以上,已成功實作適用所有iOS版本的ActionSheet,接著會用一個空白頁面示範如何透過NavigationBar叫出ActionSheet...
How To Use ?
想要使用CustomActionSheet的Class必須遵循下列事項
1. 宣告實作CustomActionSheetDelegate (h file)
2. 完成method 'actionSelected:(NSString*) itemIdOrIndex' (m file)
3. 藉由addSubview將CustomActionSheet.xib附加於畫面上 (m file)
● xib file
本文叫出CustomActionSheet是透過NavigationBar,故畫面上對擺放何種UI Element無特殊需求
● h file
宣告實作CustomActionSheetDelegate
● m file
宣告等一下要使用的property
m檔其他程式碼如下
Line 23:initial
Line 27~30:NavigationBar呼叫method 'showCustomActionsheet'把畫面叫出來
Line 33~41:CustomActionsheet需要的資料與設定都在此完成
Line 83~107:撰寫CustomActionSheetDelegate下的 'actionSelected:(NSString*) itemIdOrIndex' method
Done !
按下NavigationBar,畫面出現帶灰底背景的CustomActionSheet
選擇第三個選項TXT,因為有委派機制~所以可以在主畫面抓到被選中的id為3
參考資料
Implementing a Custom UIActionSheet
Display a custom UIView like a UIActionSheet
觀察前述需求,xib需要灰背景、放選項清單的TableView、能偵測灰背景被按到的gesture
View:選上圖的View,設定Background(需求2.2)
TableView:設定delegate與dataSources(藍框),建立table的連結至h檔的"*actionView"(紅框)
Gesture:將gesture連結至前面設灰背景的View(需求3.2)
● h file
h檔程式碼如下
首先看Line17~25
Line 17:用來當作ActionSheet列表的Table要塞資料,且按下不同item要觸發事件,故此處需實作UITableViewDelegate, UITableViewDataSource
Line 18:method 'setData' 是為了賦予TableView資料,也就是ActionSheet所呈現的選項
Line 19:method 'setTitle' 用來設定ActionSheet標題
Line 21:property '*actionView' 是透過IB(Interface Builder)設定的TableView連結
Line 22:property '*actionItems' 用來存放'setData'傳進來的值
Line 24:property 'delegateOfAction' 是為了委派,簡單來說其他外部class想要透過CustomActionSheet去幫他做事,甚至取得後續資訊,那麼就要將自己指定為 'delegateOfAction' 這個動態型別(如何指定會在之後談到)
ps:如果delegate的概念對你來說太吃力,請參考這篇iOS學習_實作自己的delegate來傳值
再來看Line12~15
Line 14:剛剛提到透過委派(delegate)可以請別人做事,甚至傳遞資訊 。本文的ActionSheet會將被選中item資訊返回,所以定義一個回傳資料id或index的method 'actionSelected:(NSString*) itemIdOrIndex'
● m file
1. 實作View的進場效果,與按下View觸發gesture event後的退場效果(需求3.1 & 3.2)
gesture當然是透過委派
viewWillAppear作二件事:註冊gesture,讓畫面進場(參考稍後的 'slideIn' method)
撰寫進場/退場method,特別注意的是退場method 'slideOut' 會用在二個情境,按下灰背景View與選中TableView選項
2. 塞資料
指派TableView資料(Line 74~76)與Title資料(Line 78~80)
3. 為滿足需求2.3,必須動態指定TableView高度,且Title(需求2.1)我打算用TableView Header來實踐(Header高度也必須算進去)。以下一併實現需求2.1 & 2.3
在viewDidLayoutSubViews呼叫method 'adjustHeight' 依照資料筆數計算高度並指定給TableView
計算時依據是否有Title(Line 127)決定高度是否要加上Header高度
4. 實作UITableViewDataSource二個required method
5. 實作TableView項目被選中
TableView被選中(也就是user認為的ActionSheet)除了讓整個View退場,還要透過h檔宣告的 'actionSelected:(NSString*) itemIdOrIndex' method將選中的資訊回傳(Line 65~72)
以上,已成功實作適用所有iOS版本的ActionSheet,接著會用一個空白頁面示範如何透過NavigationBar叫出ActionSheet...
How To Use ?
想要使用CustomActionSheet的Class必須遵循下列事項
1. 宣告實作CustomActionSheetDelegate (h file)
2. 完成method 'actionSelected:(NSString*) itemIdOrIndex' (m file)
3. 藉由addSubview將CustomActionSheet.xib附加於畫面上 (m file)
● xib file
本文叫出CustomActionSheet是透過NavigationBar,故畫面上對擺放何種UI Element無特殊需求
● h file
宣告實作CustomActionSheetDelegate
● m file
宣告等一下要使用的property
m檔其他程式碼如下
Line 23:initial
Line 27~30:NavigationBar呼叫method 'showCustomActionsheet'把畫面叫出來
Line 33~41:CustomActionsheet需要的資料與設定都在此完成
Line 83~107:撰寫CustomActionSheetDelegate下的 'actionSelected:(NSString*) itemIdOrIndex' method
Done !
按下NavigationBar,畫面出現帶灰底背景的CustomActionSheet
選擇第三個選項TXT,因為有委派機制~所以可以在主畫面抓到被選中的id為3
參考資料
Implementing a Custom UIActionSheet
Display a custom UIView like a UIActionSheet