標籤:ios開發
有時我們在做拖動功能的時候會用到UIPanGestureRecognizer手勢,例如之前封裝過的一個側滑導覽列:
ios開發——仿新版QQ側滑導覽列的實現
今天在用這個導覽列的時候發現一個問題,UIPanGestureRecognizer是任何滑動手勢都會辨別,它不像UISwipeGestureRecognizer一樣有方向,這樣就會導致如果導覽列的MainView不是UIScrollView或者UITableView的話上下滑動會出現視圖消失的錯誤,這是因為上下滑動也會觸發手勢的回應程式法。
因此我們需要在手勢回應程式法中自己判斷方向並作出調整。
一些不怎麼可行的方法:
由於在寫的時候寫上了三種狀態,Begin,Changed,Ended,若僅僅是對Pan手勢判定方向,那麼調用translationInView:方法並判斷其x、y的正負即可,但是在這裡如果只是簡單的在Changed中判定位移並return的話會出現操作不流暢,滑到中間如果上移手勢的話就不能再拉了。
只是簡單地這樣處理使用者體驗並不好
而如果在Begin中return是沒有用的,因為當你滑動的時候依舊會調用這個回應程式法並調到Changed狀態的代碼塊中執行,在Begin中禁用手勢的話更糟,一旦上下滑動,你的手勢就永久失靈了,我想不到能在哪裡讓手勢重新生效。
我的解決方案:
static BOOL canMoveView = YES;
在回應程式法的開頭加上這一句,在之後的操作中就用這個方法決定是否可以拉出,注意必須是static的,因為這個方法會在拉的過程中被反覆調用,static將該變數放到靜態儲存區,只初始化一次,在每次調用該方法時canMoveView都保留著上次調用函數後的結果。
接著在Begin塊中進行判斷
if (recognizer.state == UIGestureRecognizerStateBegan) { //0 或者 self.leftOffsetX 或者 self.rightOffsetX currentOffsetX = _mainView.transform.tx; if ([recognizer translationInView:_mainView].y != 0) { canMoveView = NO; return; } }如果使用者是上下滑動的,那麼置該標識符為NO,這樣在Changed塊中就可以根據這個標識符的值來做出響應的響應,而且由於只有在begin中才進行判斷,所以當使用者已經開始拉導覽列的時候,即時上下滑動手指也不影響流暢性了。
if (recognizer.state == UIGestureRecognizerStateChanged) { if (!canMoveView) { return; }<span style="white-space:pre"></span>//下略
當然,為了保證上下滑動後,下一次還能拉出這個導覽列,還得在Ended塊中置該值為YES,表明不管這次滑動是否有效,下一次滑動預設都為有效。
if (recognizer.state == UIGestureRecognizerStateEnded) { //...... canMoveView = YES;}
這樣就能在不影響使用者體驗的情況下禁止Pan手勢的上下滑動了。
ios開發——UIPanGestureRecognizer判定方向