之前寫過了一篇關(guān)于 導(dǎo)航欄平滑過渡的實現(xiàn) 的文章鼓拧,主要實現(xiàn)的功能是在控制器轉(zhuǎn)場的過程當(dāng)中為導(dǎo)航欄實現(xiàn)平滑過渡的效果喻括∽尜欤回到控制器轉(zhuǎn)場本身來說,它還存在著以下幾個痛點:
想通過手勢就可以輕松搞定向左或是向右滑動的 push 操作畴蒲。
想通過手勢就可以完成相反方向的 pop 操作。
可以靈活的控制轉(zhuǎn)場的功能。
源碼結(jié)構(gòu)
根據(jù)上述的幾個點實現(xiàn)了一個簡單的開源框架: XANavBarTransition 烦粒。在原有導(dǎo)航欄平滑過渡的基礎(chǔ)上,加上了一些轉(zhuǎn)場方面的功能并且最大程度的降低了對程序的入侵代赁。下面來簡單討論一下設(shè)計的思路扰她。
設(shè)計思路
在設(shè)計之初,我想是通過全局的方式來控制導(dǎo)航控制器的轉(zhuǎn)場芭碍,后來在實現(xiàn)的過程中發(fā)現(xiàn)這種方式并不能讓我很好的去管理控制器與控制器之間的轉(zhuǎn)場調(diào)度徒役。這也是我在做 XANavBarTransition 框架時遇到的一個比較難處理的問題。最后拍板:將導(dǎo)航控制器棧中每一個控制器的交互轉(zhuǎn)場配合導(dǎo)航欄平滑過渡作為獨立的轉(zhuǎn)場方案(控制器管理著轉(zhuǎn)場會話的創(chuàng)建以及銷毀)窖壕,導(dǎo)航控制器仍然控制并且管理全局性的屬性和方法忧勿。
上面提到的轉(zhuǎn)場方案其實就是在控制器創(chuàng)建的時候用戶要選擇是進行向左還是向右的 push 操作,無論是哪種方式瞻讽,對應(yīng)相反的方向就是 pop 操作鸳吸。所有在控制器棧里的控制器皆是如此。同時還要確定定制化的功能速勇,比如:某個頁面我想有 push 功能晌砾、某個頁面我只想要有 pop 功能等等。
push 與 pop 的操作都是由內(nèi)部的具體的轉(zhuǎn)場對象來進行管理的烦磁,該對象會隨著控制器的顯示而創(chuàng)建贡羔,消失而銷毀廉白。所以它在每次創(chuàng)建的時候會根據(jù)轉(zhuǎn)場方案來進行相應(yīng)的子類化。
在最開始的時候是想通過系統(tǒng)自帶的 pop 功能來完成乖寒,后來發(fā)現(xiàn)對其控制力不足猴蹂。push 與 pop 具體的實現(xiàn)思路其實很簡單都是通過對控制器添加手勢,根據(jù)轉(zhuǎn)場的方案和滑動方向來確定是 push 操作還是 pop 操作,并驅(qū)動相應(yīng)的交互式的轉(zhuǎn)場動畫楣嘁。
下面是一段手勢識別的代碼:
- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer{
if(gestureRecognizer == self.interactivePan){
CGPoint point = [gestureRecognizer translationInView:nil];
CGPoint velocity = [gestureRecognizer velocityInView:nil];
if (fabs(velocity.y) > fabs(velocity.x)) {//垂直方向不處理
return NO;
}
if(self.nc.xa_isTransitioning){
return NO;
}
if([self getPushCondition:point]){//push
self.nextVC = [self.transitionDelegate xa_nextViewControllerInTransitionMode:self.transitionMode];//是否為有效的push控制器
if(self.nextVC == nil ||
[self.nc.childViewControllers containsObject:self.nextVC]){
return NO;
}
return self.pushTransitionEnable;
}else if([self getPopCondition:point]){//pop
if(self.nc.viewControllers.count <= 1){//棧底控制器不處理
return NO;
}
return self.popTransitionEnable;
}
return NO;
}
return YES;
}
狀態(tài)控制
XANavBarTransition 框架中主要有以下幾個狀態(tài)的控制磅轻。
每一個控制器都擁有能否 pop 的能力,這個功能會在手勢識別階段完成。
可以控制當(dāng)前導(dǎo)航控制器下的所有控制器的轉(zhuǎn)場功能逐虚。這個功能會在創(chuàng)建轉(zhuǎn)場會話和設(shè)置屬性的階段完成聋溜。
代理回調(diào): XANavigationControllerObserver 對象負責(zé)監(jiān)聽 <UINavigationControllerDelegate> 代理方法。如果App外部有需要監(jiān)聽,可以將實現(xiàn)了 <UINavigationControllerDelegate> 協(xié)議的代理設(shè)置到導(dǎo)航控制器的 xa_delegate屬性當(dāng)中,內(nèi)部會做轉(zhuǎn)遞叭爱。
結(jié)尾
如果大家在框架的使用中有什么問題歡迎給我提 issues 或者 @關(guān)于嵐撮躁。