iOS7滑動返回

NSTopGun發表於2013-11-19

【轉載請註明出處】

iOS 7中在傳統的左上角返回鍵之外,提供了右滑返回上一級介面的手勢。支援此手勢的是UINavigationController中新增的屬性

interactivePopGestureRecognizer,即右滑返回只支援以UINavigationController為容器的ViewController間切換,要想在自定義容器中使用,需要一些額外的工作。

基本地,控制ViewController是否啟用右滑返回,只需要這樣:

1 self.navigationController.interactivePopGestureRecognizer.enabled = YES;

預設情況下enabled為YES。

在實際使用中,遇到了一些問題,整理如下:
1、自定義返回按鈕後,右滑返回失效;

解決方案:比較直觀的辦法是在自定義返回按鈕時,使用backBarButtonItem:

1     UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
2     //some initialize code here...
3     UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
4     self.navigationItem.leftBarButtonItem = barItem;    //not working
5     self.navigationItem.backBarButtonItem = barItem;    //serve well

P.S:關於backBarButtonItem和leftBarButtonItem的區別:

http://www.cocoachina.com/ask/questions/show/97110

但這樣無法支援左上角多個按鈕的情況。考慮到interactivePopGestureRecognizer也有delegate屬性,替換預設的self.navigationController.interactivePopGestureRecognizer.delegate來配置右滑返回的表現也是可行的。在主ViewController中:

1   self.navigationController.interactivePopGestureRecognizer.delegate = self;
 1   - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
 2   {
 3       if (self.navigationController.viewControllers.count == 1)//關閉主介面的右滑返回
 4       {
 5           return NO;
 6       }
 7       else
 8       {
 9           return YES;
10       }
11   }

如此做的好處是可以在主ViewController中配置棧中所有ViewController右滑返回的開啟,而不需要在各個ViewController中分別設定enabled。

值得注意的是:在替換了delegate之後,必須在gestureRecognizerShouldBegin:中設定某ViewController A開啟右滑返回,同時在A中未設定interactivePopGestureRecognizer.enabled = NO,右滑返回才會開啟,即二者中任一為NO,右滑返回都處於關閉狀態。

2、主介面(UINavigationController棧中的第一個ViewController)預設也是開啟右滑返回的。若在主介面上右滑,不會有動作執行。但此時想進入下一級ViewController(如點選tableView中某一行),切換動畫卻沒有出現。切回桌面再進入應用,發現直接進入了下一級ViewController。

解決方案:這個問題是在最初試驗右滑返回的使用方式時出現的。在使用自定義返回按鈕的ViewController中

1 self.navigationController.interactivePopGestureRecognizer.delegate = self;

解決解決問題1的同時,造成了問題2。和1中相似,都是在替換了預設的delegate之後,interactivePopGestureRecognizer就能呼叫自定義的返回方法了。具體原因尚不清楚,待更新【Mark】。

3、在使用右滑返回拖動到一半時,有時會在導航欄上看到三個排成一行的小藍點。

解決方案:原因不明,解決方案不明。

P.S:在一個帖子上看到一個辦法:

1   self.navigationItem.title = @"";

可以隱藏小藍點,但由於小藍點非必現,在不明究竟的情況下很難說是否有效。

帖子連結:http://www.tuicool.com/articles/FB3IJ3

 

 

【其他】

(1)在工程中檢視,self.navigationController.interactivePopGestureRecognizer.delegate實際上是一個

_UINavigationInteractiveTransition例項,該類宣告如下:

 1   @class UIScreenEdgePanGestureRecognizer;
 2 
 3   @interface _UINavigationInteractiveTransition : _UINavigationInteractiveTransitionBase {
 4       UIScreenEdgePanGestureRecognizer *_edgePanRecognizer;
 5   }
 6 
 7   @property(readonly) UIScreenEdgePanGestureRecognizer * screenEdgePanGestureRecognizer;
 8 
 9   - (void)_configureNavigationGesture;
10   - (BOOL)_gestureRecognizer:(id)arg1 shouldBeRequiredToFailByGestureRecognizer:(id)arg2;
11   - (void)dealloc;
12   - (BOOL)gestureRecognizer:(id)arg1 shouldReceiveTouch:(id)arg2;
13   - (BOOL)gestureRecognizer:(id)arg1 shouldRecognizeSimultaneouslyWithGestureRecognizer:(id)arg2;
14   - (BOOL)gestureRecognizerShouldBegin:(id)arg1;
15   - (id)gestureRecognizerView;
16   - (id)initWithViewController:(id)arg1 animator:(id)arg2;
17   - (id)screenEdgePanGestureRecognizer;
18   - (void)setNotInteractiveTransition;
19   - (void)startInteractiveTransition;
20 
21   @end

可以看到,委託的內部,實際上是一個UIScreenEdgePanGestureRecognizer例項在起作用,它是iOS7中引入的一個新類,用於支援某些情況下ViewController間切換的初始化。apple官方文件中對其的描述很少,如下:

UIScreenEdgePanGestureRecognizer looks for panning (dragging) gestures that start near an edge of the screen. The system uses screen edge gestures in some cases to initiate view controller transitions. You can use this class to replicate the same gesture behavior for your own actions.

After creating a screen edge pan gesture recognizer, assign an appropriate value to the edges property before attaching the gesture recognizer to your view. You use this property to specify from which edges the gesture may start. This gesture recognizer ignores any touches beyond the first touch.

要在自定義的ViewController容器中支援右滑返回,可能就需要用到它。

 

(2)目前不少應用還是用的iOS 6.1 SDK,而許多iOS7的使用者對右滑返回的需求非常迫切,因此在iOS 6.1SDK下模擬右滑返回在短時間內是有必要的,以下是一個通過在push時擷取上級ViewController介面為UIImage作為下一級ViewController的背景的一種實現方式:

 

今天看到了作者的一篇說明帖,深感之前的思考太過膚淺,此處將iOS6下滑動返回的實現獨立出來:

http://www.cnblogs.com/lexingyu/p/3434340.html

 

【參考】

1、UIScreenEdgePanGestureRecognizer Class Reference

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIScreenEdgePanGestureRecognizer_class/Reference/Reference.html#//apple_ref/occ/cl/UIScreenEdgePanGestureRecognizer

2、_UINavigationInteractiveTransition.h

https://github.com/nst/iOS-Runtime-Headers/blob/master/Frameworks/UIKit.framework/_UINavigationInteractiveTransition.h

3、自定義返回按鈕時,iOS7手勢返回遇到的問題

http://www.tuicool.com/articles/FB3IJ3

相關文章