demo地址:https://github.com/al-liu/HCSpringBoard.git
效果圖:
說(shuō)明
項(xiàng)目是個(gè)手機(jī)銀行app谈喳,要求做一個(gè)仿照招商手機(jī)銀行的最愛(ài)菜單功能芯急,沒(méi)有找到合適的輪子,就只能自己寫個(gè)了剂邮。功能是在原有項(xiàng)目上做的(原來(lái)只能添加和刪除),后來(lái)抽出來(lái)一個(gè)demo,因?yàn)檫壿嬢^復(fù)雜火脉,也沒(méi)有花太多時(shí)間休整代碼,復(fù)用程度不夠高,但是按照下面我寫的分析流程來(lái)集成該功能并沒(méi)有什么困難倦挂。
希望朋友們幫我指正代碼問(wèn)題和bug畸颅。
準(zhǔn)備工作
組織菜單數(shù)據(jù)結(jié)構(gòu)在 HCAssistant
類中,配置一個(gè)菜單要顯示的圖片方援,菜單名稱重斑,是否默認(rèn)顯示,是否可刪除肯骇,跳轉(zhuǎn)頁(yè)面等窥浪。
顯示菜單
1,獲取存到 NSUserDefaults
中的最愛(ài)菜單數(shù)據(jù)笛丙,如果沒(méi)有漾脂,從配置中的全部菜單中篩選出默認(rèn)要顯示的數(shù)據(jù),并存起來(lái)胚鸯,有了數(shù)據(jù)之后就使用 HCSpringBoardView
類來(lái)生成菜單骨稿。
2,在 HCSpringBoardView
的初始化方法里姜钳,根據(jù)一頁(yè)有幾行幾列坦冠,確定需要的頁(yè)數(shù),和需要的菜單 frame 并創(chuàng)建 UIScrollView 和 UIPageControl哥桥。在根據(jù)傳進(jìn)來(lái)的模型數(shù)組辙浑,判斷是文件夾 HCFavoriteFolderModel
還是圖標(biāo) HCFavoriteIconModel
分別創(chuàng)建對(duì)應(yīng)的視圖,HCFavoriteFolderView
或 HCFavoriteIconView
并設(shè)置代理拟糕。
這里的適配很簡(jiǎn)陋判呕,不要做參考
模型類 HCFavoriteIconModel
和 HCFavoriteFolderModel
使用 YYModel 做的數(shù)據(jù)模型轉(zhuǎn)換,很好用送滞。
HCFavoriteIconModel
image 侠草,name , targetController等屬性犁嗅。
需要實(shí)現(xiàn)NSCoding
協(xié)議用于序列化边涕。HCFavoriteFolderModel
'folderName' 文件夾名稱,'iconModelsFolderArray' 存該文件夾下的菜單模型褂微,'iconViewsFolderArray' 存該文件夾下的菜單視圖功蜓。
需要實(shí)現(xiàn)NSCoding
協(xié)議用于序列化。
視圖類 HCFavoriteIconView
和 HCFavoriteFolderView
- HCFavoriteIconView
主要的是下面兩個(gè)代理
favoriteIconDelegate
favoriteIconLongGestureDelegate
例如:
@class HCFavoriteIconView;
@protocol HCFavoriteIconDelegate <NSObject>
- (void)deleteIconOfLoveIconView:(HCFavoriteIconView *)iconView;
- (void)pushPageOfLoveIconView:(HCFavoriteIconView *)iconView;
- (void)intoEditingModeOfLoveIconView:(HCFavoriteIconView *)iconView;
@optional
- (void)addIconOfLoveIconView:(HCFavoriteIconView *)iconView;
@end
@protocol HCFavoriteIconLongGestureDelegate <NSObject>
- (void)longGestureStateBegin:(UILongPressGestureRecognizer *)gesture forLoveView:(HCFavoriteIconView *)loveView;
- (void)longGestureStateMove:(UILongPressGestureRecognizer *)gesture forLoveView:(HCFavoriteIconView *)loveView;
- (void)longGestureStateEnd:(UILongPressGestureRecognizer *)gesture forLoveView:(HCFavoriteIconView *)loveView;
- (void)longGestureStateCancel:(UILongPressGestureRecognizer *)gesture forLoveView:(HCFavoriteIconView *)loveView;
@end
定義了刪除蕊梧,進(jìn)入下一頁(yè)霞赫,開(kāi)始編輯,增加和長(zhǎng)按手勢(shì)的協(xié)議肥矢。
- HCFavoriteFolderView
同上有兩個(gè)協(xié)議方法都是把事件代理到 'HCSpringBoardView' 中端衰。
刪除菜單
HCSpringBoardView
里有兩個(gè)屬性_favoriteModelArray 和 _favoriteViewArray 分別管理最愛(ài)菜單的模型和視圖叠洗,刪除就是刪掉對(duì)應(yīng)的元素,并更新視圖旅东,還要更新全部菜單列表灭抑,以至于在添加的時(shí)候不是打勾的狀態(tài),可以重新加進(jìn)來(lái)抵代。
進(jìn)入編輯模式
長(zhǎng)按菜單會(huì)進(jìn)入編輯模式腾节,此時(shí)用該菜單的模型創(chuàng)建一個(gè)拖動(dòng)的視圖,在window上荤牍。
仔細(xì)觀察了招商手機(jī)銀行的最愛(ài)菜單實(shí)現(xiàn)案腺,發(fā)現(xiàn)拖動(dòng)圖標(biāo)速度較快的時(shí)候并不會(huì)做任何處理,所以它是在一定滑動(dòng)速度之下康吵,開(kāi)始檢測(cè)的當(dāng)前拖動(dòng)圖標(biāo)的移動(dòng)點(diǎn)是在其它圖標(biāo)的中間區(qū)域還是四周區(qū)域劈榨,這樣就可以判斷出該圖標(biāo)是要換位置還是合并文件夾。
換位置操作在 longGestureStateMove
方法里晦嵌。
判斷是兩圖標(biāo)合并還是合并到已有文件夾邏輯在 longGestureStateEnd
里同辣。
至于拖動(dòng)文件夾就只有換位置的邏輯,相對(duì)簡(jiǎn)單多了惭载。
現(xiàn)在能合并旱函,看看怎么從文件夾里拖出去?
拖出文件夾
HCFavoriteFolderFloatView
和HCFavoriteFolderMenuView
用于展示文件夾的圖標(biāo)描滔,在文件夾里的排序和刪除邏輯也是和外面的一樣且不能再合并簡(jiǎn)單了很多棒妨。
至于拖出去的邏輯是這樣的,首先在文件夾的編輯模式下伴挚,拖動(dòng)時(shí)也會(huì)在一定速度下檢測(cè)點(diǎn)的位置靶衍,判斷是不是要換位置灾炭,如果拖出了菜單面板茎芋,隱藏當(dāng)前HCFavoriteFolderFloatView
但是并不刪除它(如果刪掉,拖出去的view會(huì)卡在那里蜈出,招商就有個(gè)拖出去卡在左邊的問(wèn)題田弥,很可能和這個(gè)有關(guān)系),此時(shí)長(zhǎng)按手勢(shì)的回調(diào)方法在HCFavoriteFolderMenuView
里铡原,將移動(dòng)事件longGestureStateMove
代理給HCSpringBoardView
(HCFavoriteFolderMenuView
有個(gè)代理要設(shè)置給HCSpringBoardView
)偷厦。在HCSpringBoardView
里重新獲取該點(diǎn),排序合并的邏輯和在外面是一樣的燕刻。
待用戶松開(kāi)手指只泼,調(diào)用longGestureStateEnd
時(shí),一樣處理合并邏輯卵洗,并將重新拖出的菜單設(shè)置代理到HCSpringBoardView
请唱,不要忘了從父視圖刪除掉HCFavoriteFolderFloatView
弥咪,就此操作完成。