最近想把以前一個(gè)項(xiàng)目的側(cè)滑返回?fù)Q成為全屏側(cè)滑有效,而不僅僅是邊界側(cè)滑。
之前一直使用系統(tǒng)提供的方案疫诽,使之實(shí)現(xiàn)邊界側(cè)滑返回。一直使用都沒什么問題笼恰,也算比較好用踊沸。但是如果在大屏幕手機(jī)上,邊界側(cè)滑返回對(duì)于手小的人來(lái)說依然是不方便的社证,以此為基礎(chǔ)我需要找一個(gè)第三方庫(kù)以支持全屏幕任何位置右滑動(dòng)返回上個(gè)界面逼龟。而我的就項(xiàng)目是用了UITabBarController的,需求是UITabBarController的子視圖控制器需要有tabBar追葡,以后它push出來(lái)的界面不需要tabbar腺律。這個(gè)時(shí)候SloppySwiper會(huì)出現(xiàn)tabbar還原位置失誤的問題。如圖:
問題和最終解決后的結(jié)果宜肉。
這個(gè)問題是什么造成的呢匀钧?首先來(lái)看一張圖:
這張圖是我拷貝來(lái)的,但是它很清晰的介紹了UINavigationController谬返,UIViewController 和UITabBarController的關(guān)系之斯。這也是我們搭建這種有tabbar和navigationBar界面的實(shí)際邏輯順序∏猜粒【【【UIViewController】UINavigationController】UITabBarController】:UIViewController 加在 UINavigationController上佑刷,UINavigationController加在UITabBarController。
而SloppySwiper庫(kù)的側(cè)滑返回時(shí)對(duì)于tabbar的處理是將tabbar從原來(lái)的UITabBarController上拿出來(lái)添加到toViewController上酿炸,造成一種然后動(dòng)畫效果完成后再將tabbar放回到UITabBarController上瘫絮。也就是說其實(shí)是一個(gè)障眼法的法子來(lái)實(shí)現(xiàn)tabbar的隱藏和出現(xiàn)。
但是有tabbar的時(shí)候toViewController.view.frame.size.height 是等于【屏幕高度】-【navigationBar高度】-【狀態(tài)欄高度】-【tabbar高度】(6s模擬器下是554)
而返回再添加到UITabBarController的tabar高度y坐標(biāo)就變了填硕,變成了505 =【toViewController.view高度】-【tabbar高度】麦萤。
這個(gè)讓我發(fā)現(xiàn)了問題所在鹿鳖,原來(lái)tabbar最后沒有落在屏幕最下方的位置可能是【toViewController.view高度】造成的。但是這個(gè)猜想到底是否正確呢壮莹?
我們做個(gè)試驗(yàn):我們每次都將要push的時(shí)候?qū)?dāng)前ViewController.view的高度做一個(gè)調(diào)整翅帜,變成【ViewController高度】= 【屏幕高度】-【navigationBar高度】-【狀態(tài)欄高度】,也就是把tabbar占用的【tabbar高度】加上去垛孔。
每次pop快要結(jié)束的時(shí)候?qū)⒁氐降腣iewController.view的高度調(diào)整回來(lái)藕甩,變成【ViewController高度】= 【屏幕高度】-【navigationBar高度】-【狀態(tài)欄高度】-【tabbar高度】,這樣將tabbar占用的【tabbar高度】減去周荐。
這樣做的目的就是為了保證每次push的時(shí)候不管當(dāng)前有沒有tabbar都保證ViewControlle.viewr的高度為沒有tabbar情況下的大小狭莱。這樣保證效果一致。
那么怎么做到push和pop的時(shí)候進(jìn)行ViewController.view高度修改呢概作?我想到了viewWillDisappear和viewDidAppear兩個(gè)方法腋妙,每次界面push的時(shí)候會(huì)調(diào)用viewWillDisappear,每次pop回來(lái)的時(shí)候會(huì)執(zhí)行viewDidAppear讯榕。
當(dāng)然最終結(jié)果是可行的骤素。也達(dá)到了我想要的效果。
執(zhí)行方式如下:
// [self viewWillPush];[self viewWillPopBack];是對(duì)界面內(nèi)其他收到影響的view做調(diào)整愚屁,當(dāng)然也可以用通知等等其他的方法改济竹,我這里就隨意寫一下。
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
//? ? 展示tabBar
UINavigationController *navController = self.navigationController;
BOOL isToViewControllerFirstInNavController = [navController.viewControllers firstObject] == self;
if(self.tabBarController && isToViewControllerFirstInNavController){
self.view.frame = CGRectMake(self.view.frame.origin.x,
self.view.frame.origin.y,
self.view.frame.size.width,
ScreenHeight - self.navigationController.navigationBar.frame.size.height - 20 - self.tabBarController.tabBar.frame.size.height);
[self viewWillPopBack];
}
}
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
UINavigationController *navController = self.navigationController;
BOOL isToViewControllerFirstInNavController = [navController.viewControllers firstObject] == self;
if (self.tabBarController && isToViewControllerFirstInNavController) {
self.view.frame = CGRectMake(self.view.frame.origin.x,
self.view.frame.origin.y,
self.view.frame.size.width,
ScreenHeight - self.navigationController.navigationBar.frame.size.height - 20);
[self viewWillPush];
}
}
最后介紹一下系統(tǒng)的邊界右滑返回是實(shí)現(xiàn)霎槐。
我習(xí)慣在公用父類里寫通用方法送浊,這里的代碼放在繼承了UIControllerView的ModelViewController里。以后的viewController都繼承ModelViewController丘跌。
使用方法:在UITabBarController的所有子viewcontroller里都實(shí)現(xiàn)[self moveFingerToBack];方法即可袭景。
代碼:
#pragma mark 側(cè)滑返回 非根節(jié)點(diǎn)的viewcontroller 不許使用
-(void)moveFingerToBack{
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
self.navigationController.interactivePopGestureRecognizer.delegate = self;
}
#pragma mark interactivePopGestureRecognizer 代理
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
// 注意:只有非根控制器才有滑動(dòng)返回功能,根控制器沒有闭树。
// 判斷導(dǎo)航控制器是否只有一個(gè)子控制器耸棒,如果只有一個(gè)子控制器,肯定是根控制器
if (self.navigationController.childViewControllers.count == 1) {
// 表示用戶在根控制器界面报辱,就不需要觸發(fā)滑動(dòng)手勢(shì)与殃,
return NO;
}
return YES;
}