iOS7滑動返回

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

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

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

<span style="color: rgb(0, 128, 128);"><span class="number" style="color: rgb(0, 153, 153);">1</span></span> <span class="keyword" style="font-weight: bold;">self</span>.navigationController.interactivePopGestureRecognizer.enabled = <span class="constant">YES</span>;

默認情況下enabled爲YES。

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

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

<span style="color: rgb(0, 128, 128);"><span class="number" style="color: rgb(0, 153, 153);">1</span></span>     UIButton *backButton =<span style="color: rgb(0, 0, 0);"> [UIButton buttonWithType:UIButtonTypeCustom];
</span><span style="color: rgb(0, 128, 128);"><span class="number" style="color: rgb(0, 153, 153);">2</span></span>     <span style="color: rgb(0, 128, 0);"><span class="comment" style="color: rgb(153, 153, 136); font-style: italic;">//</span></span><span class="comment" style="color: rgb(153, 153, 136); font-style: italic;"><span style="color: rgb(0, 128, 0);">some initialize code here...</span></span><span style="color: rgb(0, 128, 0);"></span>
<span style="color: rgb(0, 128, 128);"><span class="number" style="color: rgb(0, 153, 153);">3</span></span>     UIBarButtonItem *barItem =<span style="color: rgb(0, 0, 0);"> [[UIBarButtonItem alloc] initWithCustomView:backButton];
</span><span style="color: rgb(0, 128, 128);"><span class="number" style="color: rgb(0, 153, 153);">4</span></span>     <span style="text-decoration: line-through;"><span class="keyword" style="font-weight: bold;">self</span>.navigationItem.leftBarButtonItem = barItem;</span>    <span style="color: rgb(0, 128, 0);"><span class="comment" style="color: rgb(153, 153, 136); font-style: italic;">//</span></span><span class="comment" style="color: rgb(153, 153, 136); font-style: italic;"><span style="color: rgb(0, 128, 0);">not working</span></span><span style="color: rgb(0, 128, 0);"></span>
<span style="color: rgb(0, 128, 128);"><span class="number" style="color: rgb(0, 153, 153);">5</span></span>     <span class="keyword" style="font-weight: bold;">self</span>.navigationItem.backBarButtonItem = barItem;    <span style="color: rgb(0, 128, 0);"><span class="comment" style="color: rgb(153, 153, 136); font-style: italic;">//</span></span><span class="comment" style="color: rgb(153, 153, 136); font-style: italic;"><span style="color: rgb(0, 128, 0);">serve well</span></span><span style="color: rgb(0, 128, 0);"></span>

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

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

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

<span style="color: rgb(0, 128, 128);"><span class="number" style="color: rgb(0, 153, 153);">1</span></span>   <span class="keyword" style="font-weight: bold;">self</span>.navigationController.interactivePopGestureRecognizer.<span style="color: rgb(0, 0, 255);">delegate</span> = <span class="keyword" style="font-weight: bold;">self</span>;
<span style="color: rgb(0, 128, 128);"> <span class="number" style="color: rgb(0, 153, 153);">1</span></span>   - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *<span style="color: rgb(0, 0, 0);">)gestureRecognizer
</span><span style="color: rgb(0, 128, 128);"> <span class="number" style="color: rgb(0, 153, 153);">2</span></span>   <span style="color: rgb(0, 0, 0);">{
</span><span style="color: rgb(0, 128, 128);"> <span class="number" style="color: rgb(0, 153, 153);">3</span></span>       <span style="color: rgb(0, 0, 255);"><span class="keyword" style="color: rgb(51, 51, 51); font-weight: bold;">if</span></span> (<span class="keyword" style="font-weight: bold;">self</span>.navigationController.viewControllers.count == <span class="number" style="color: rgb(0, 153, 153);">1</span>)<span style="color: rgb(0, 128, 0);"><span class="comment" style="color: rgb(153, 153, 136); font-style: italic;">//</span></span><span class="comment" style="color: rgb(153, 153, 136); font-style: italic;"><span style="color: rgb(0, 128, 0);">關閉主界面的右滑返回</span></span><span style="color: rgb(0, 128, 0);"></span>
<span style="color: rgb(0, 128, 128);"> <span class="number" style="color: rgb(0, 153, 153);">4</span></span> <span style="color: rgb(0, 0, 0);">      {
</span><span style="color: rgb(0, 128, 128);"> <span class="number" style="color: rgb(0, 153, 153);">5</span></span>           <span style="color: rgb(0, 0, 255);"><span class="keyword" style="color: rgb(51, 51, 51); font-weight: bold;">return</span></span><span style="color: rgb(0, 0, 0);"> NO;
</span><span style="color: rgb(0, 128, 128);"> <span class="number" style="color: rgb(0, 153, 153);">6</span></span> <span style="color: rgb(0, 0, 0);">      }
</span><span style="color: rgb(0, 128, 128);"> <span class="number" style="color: rgb(0, 153, 153);">7</span></span>       <span style="color: rgb(0, 0, 255);"><span class="keyword" style="color: rgb(51, 51, 51); font-weight: bold;">else</span></span>
<span style="color: rgb(0, 128, 128);"> <span class="number" style="color: rgb(0, 153, 153);">8</span></span> <span style="color: rgb(0, 0, 0);">      {
</span><span style="color: rgb(0, 128, 128);"> <span class="number" style="color: rgb(0, 153, 153);">9</span></span>           <span style="color: rgb(0, 0, 255);"><span class="keyword" style="color: rgb(51, 51, 51); font-weight: bold;">return</span></span><span style="color: rgb(0, 0, 0);"> YES;
</span><span style="color: rgb(0, 128, 128);"><span class="number" style="color: rgb(0, 153, 153);">10</span></span> <span style="color: rgb(0, 0, 0);">      }
</span><span style="color: rgb(0, 128, 128);"><span class="number" style="color: rgb(0, 153, 153);">11</span></span>   }

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

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

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

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

<span style="color: rgb(0, 128, 128);"><span class="number" style="color: rgb(0, 153, 153);">1</span></span> <span class="keyword" style="font-weight: bold;">self</span>.navigationController.interactivePopGestureRecognizer.<span style="color: rgb(0, 0, 255);">delegate</span> = <span class="keyword" style="font-weight: bold;">self</span>;

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

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

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

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

<span style="color: rgb(0, 128, 128);"><span class="number" style="color: rgb(0, 153, 153);">1</span></span>   self.navigationItem.title = <span style="color: rgb(128, 0, 0);"><span class="string" style="color: rgb(221, 17, 68);">@""</span></span>;

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

帖子鏈接: http://www.tuicool.com/articles/FB3IJ3

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

_UINavigationInteractiveTransition實例,該類聲明如下:

 1   <span class="at_rule">@class</span><span class="at_rule"> UIScreenEdgePanGestureRecognizer</span>;
 2 
 3   <span class="at_rule">@interface</span><span class="at_rule"> _UINavigationInteractiveTransition : _UINavigationInteractiveTransitionBase </span>{
 4       <span class="tag" style="color: rgb(0, 0, 128);">UIScreenEdgePanGestureRecognizer</span> *_<span class="tag" style="color: rgb(0, 0, 128);">edgePanRecognizer</span>;
 5   }
 6 
 7   <span class="at_rule">@<span class="function">property(readonly)</span> UIScreenEdgePanGestureRecognizer * screenEdgePanGestureRecognizer</span>;
 8 
 9   - (<span class="tag" style="color: rgb(0, 0, 128);">void</span>)_<span class="tag" style="color: rgb(0, 0, 128);">configureNavigationGesture</span>;
10   - (<span class="tag" style="color: rgb(0, 0, 128);">BOOL</span>)_<span class="tag" style="color: rgb(0, 0, 128);">gestureRecognizer</span><span class="pseudo">:(id)arg1</span> <span class="tag" style="color: rgb(0, 0, 128);">shouldBeRequiredToFailByGestureRecognizer</span><span class="pseudo">:(id)arg2</span>;
11   - (<span class="tag" style="color: rgb(0, 0, 128);">void</span>)<span class="tag" style="color: rgb(0, 0, 128);">dealloc</span>;
12   - (<span class="tag" style="color: rgb(0, 0, 128);">BOOL</span>)<span class="tag" style="color: rgb(0, 0, 128);">gestureRecognizer</span><span class="pseudo">:(id)arg1</span> <span class="tag" style="color: rgb(0, 0, 128);">shouldReceiveTouch</span><span class="pseudo">:(id)arg2</span>;
13   - (<span class="tag" style="color: rgb(0, 0, 128);">BOOL</span>)<span class="tag" style="color: rgb(0, 0, 128);">gestureRecognizer</span><span class="pseudo">:(id)arg1</span> <span class="tag" style="color: rgb(0, 0, 128);">shouldRecognizeSimultaneouslyWithGestureRecognizer</span><span class="pseudo">:(id)arg2</span>;
14   - (<span class="tag" style="color: rgb(0, 0, 128);">BOOL</span>)<span class="tag" style="color: rgb(0, 0, 128);">gestureRecognizerShouldBegin</span><span class="pseudo">:(id)arg1</span>;
15   - (<span class="tag" style="color: rgb(0, 0, 128);">id</span>)<span class="tag" style="color: rgb(0, 0, 128);">gestureRecognizerView</span>;
16   - (<span class="tag" style="color: rgb(0, 0, 128);">id</span>)<span class="tag" style="color: rgb(0, 0, 128);">initWithViewController</span><span class="pseudo">:(id)arg1</span> <span class="tag" style="color: rgb(0, 0, 128);">animator</span><span class="pseudo">:(id)arg2</span>;
17   - (<span class="tag" style="color: rgb(0, 0, 128);">id</span>)<span class="tag" style="color: rgb(0, 0, 128);">screenEdgePanGestureRecognizer</span>;
18   - (<span class="tag" style="color: rgb(0, 0, 128);">void</span>)<span class="tag" style="color: rgb(0, 0, 128);">setNotInteractiveTransition</span>;
19   - (<span class="tag" style="color: rgb(0, 0, 128);">void</span>)<span class="tag" style="color: rgb(0, 0, 128);">startInteractiveTransition</span>;
20 
21   <span class="at_rule">@end</span>

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

A  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的背景的一種實現方式:

作者的本意似乎並不要要模擬右滑返回,但稍作修改就能在結構比較簡單的應用中使用,以下是鏈接:

https://github.com/vinqon/MultiLayerNavigation

P.S:對於一些特殊的需求,如在有ScrollView的界面上(比如瀏覽照片)模擬右滑返回,當滑動到最左邊時即執行右滑返回,該類無法滿足,待處理【Mark】。

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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章