打造所有iOS版本皆適用的ActionSheet

之前寫過如何在iOS的ActionSheet加上圖片,雖然很簡單~卻要針對新舊版(以iOS 8劃分)寫二種code,且添加上去的圖片位置很醜XD

既然不好用又醜,乾脆手工打造一個可以適用所有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.2  若未選中任何選項,而是touch半透明灰底背景,必須以往下收闔的動畫效果關閉ActionSheet
     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

沒有留言: