事情起因是新項目,產品要做雜志翻頁風格,也不不顯示導航、標簽欄、返回鍵,返回由下滑手勢出發,上滑會從底部顯示足跡,也就是說一個頁面有上下左右四個方向的手勢,本來想想覺得沒什么問題,真寫出來問題百出
翻頁風格自然而然想到UIPageViewController,設置style為UIPageViewControllerTransitionStylePageCurl(翻頁style是不帶scrollView的,自然也沒有相應的代理之類的)
本來以為UIPageViewController的翻頁只是簡單的左右滑動,于是我加上項目需要的下滑和上滑手勢。結果我錯了,除了第一頁有效,其他頁都無效。目前我所了解UIPageViewController至少有兩種手勢:點擊tap(點擊邊緣換頁)和拖動pan,并且pan的范圍很廣,完全擋住了滑動手勢。
那么了解到這些,怎樣讓新手勢和UIPageViewController自帶手勢同時相應呢?
查了很多,包括網上也發現有人UIPageViewController和UITableview手勢沖突的。最后發現有一種方法有效:
// 同時響應拖動和滑動手勢
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
? ? ? return YES;
}
這是UIGestureRecognizer手勢的一個代理方法,那么問題來了,既然是代理方法,肯定要遵從代理才有作用,因此我給我添加的兩個新手勢加了代理,為當前的視圖控制器,無效。想了一下是因為PageController的拖動手勢并沒有設置代理為當前視圖控制器,因此用下面方法取到相關手勢,并設置代理:
for (UIGestureRecognizer *gr in _pageViewController.gestureRecognizers) {
? ? ? ? ?if ([gr isKindOfClass:[UIPanGestureRecognizer class]]) {
? ? ? ? ? ? ? ?gr.delegate = self;
? ? ? ? ?}
}
親測有效!當我開心的多翻了兩頁,crash!重新試了幾次,發現是在PageController的第一頁往前滑和最后一頁往后滑會崩,本來以為是沒有對第一頁和最后一頁就行判斷設置,但是檢查了一下發現沒錯。。。糾結一下午~~~~~
后來突然想到,UIPageViewController的手勢代理當然是它自己,我把它的手勢代理改了,那肯定會在某些時候出問題嘛,想通了以后,于是進行調整,給UIPageViewController加了一個分類,添加了兩個方法:(第二個方法是為了去掉pageviewcontroller點擊邊緣換頁的手勢,防止相關邊緣按鈕沖突)
#import "UIPageViewController+FSGestureDeal.h"
@implementation UIPageViewController (FSGestureDeal)
// pageViewontroller同時響應拖動和滑動手勢
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
? ? ? ? return YES;
}
//解決邊緣自動翻頁跟控件沖突的問題
-(BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
? ? ?if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
return NO;
}
return YES;
}
@end
到此,就完美解決了~
更新:最近項目中又遇到UIPageViewController和UITableview手勢沖突(翻頁動畫方式中,垂直方向上的沖突,如果是UITableview左滑刪除手勢沖突,這種方法是解決不了的),解決方式類似,把下面方法替換上面的就可以了:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] &&
[otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
return NO;
}
return YES;
}