1

對不起這樣一個長的問題,但覺得我應該傳達我所嘗試過的。處理多個視圖的UIPanGestureRecognizer手勢(一個覆蓋另一個)

我在導航控制器中有一個視圖viewA。然後,我添加一個子視圖viewB(包含UITableView)到viewA並偏移其原點高度,以便它只覆蓋屏幕的一半(另一半溢出屏幕底部)。我希望能夠向上拖動這個viewB,但是當它碰到導航欄的底部時它會停下來,並且在碰到原點偏移點時向下拖動時也會停止。我已經取得了成功。

但是,我希望UITableView交互僅在viewB位於其上部位置時啓用,因此不會響應任何其他位置的手勢。本質上,拖動viewB以使其完全覆蓋viewA應啓用與UITableView的交互。

這裏最棘手的部分是,我希望它做到以下幾點:

  1. 如果viewB處於較高位置,使其覆蓋屏幕,則UITableView內容偏移爲0(即我們在桌子的頂部),並且用戶向下做平移手勢,該手勢不應該與UITableView交互,而應該向下移動viewB
  2. 在上述情況下的任何其他平移手勢應該是與UITableView的交互。
  3. 如果viewB處於其上部位置,使得它覆蓋在屏幕上,所述UITableView內容偏移是NOT在0(即,我們是NOT在表的頂部)和用戶做出平移姿勢向下,該手勢應該與UITableView交互。

我一直非常接近實現這一點,但我不能完全正確。

嘗試到目前爲止

我使用UIPanGestureRecognizer處理視圖的拖動。我曾嘗試將此添加到:

  • viewBUITableView用戶交互最初禁用。這允許我上下拖動viewB而不干擾UITableView。一旦viewB處於其上部位置,我啓用UITableView用戶交互,然後正確地允許我與UITableView交互,而不移動viewB

    然而,通過使UITableView用戶交互,這意味着觸摸從未到達UIPanGestureRecognizer,這意味着我不能檢測用於上述點(1)所述的情況下,因而不能重新禁用UITableView用戶交互作viewB再次移動。

    也許有可能通過覆蓋UITableView使用的手勢識別方法來做到這一點?如果這是可能的,任何人都可以指向正確的方向?

  • UITableView前增加了一個新視圖。我想也許我可以在必要時將觸摸手勢轉發到背後的UITableView,但我仍然沒有找到辦法做到這一點。

    我所能做的就是禁用手勢識別器,該手勢識別器允許我與UITableView進行交互,但之後出現與上述相同的問題。我無法檢測何時重新啓用它。

  • UITableViewviewB之內。這似乎是迄今爲止最有前途的方式。通過設置以下方法的返回值,我可以啓用和禁用對viewBUITableView的識別。

    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool { 
        if pulloverVC.view.frame.origin.y == bottomNavbarY && 
         pulloverVC.tableView?.contentOffset.y == 0 { // need to add gesture direction check to this condition 
         viewBisAtTop = true 
         return false // disable pullover control 
        } 
        return true // enable pullover control 
    } 
    
    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool { 
        if (gestureRecognizer as! UIPanGestureRecognizer).velocityInView(view).y < 0 && viewBisAtTop { // gesture direction check not wanted here 
         return true // enable tableview control 
        } 
        viewBisAtTop = false 
        return false // disable tableview control 
    } 
    

    頂部方法首先調用手勢(我檢查了打印語句)後跟底部方法。通過爲2種方法制作不同的真假組合,我可以在viewBUITableView之間交替進行交互。

    要檢測用戶是否向下滑動,我在識別器上調用velocityInView()(如底部方法所示)。我打算在頂部方法if聲明中進行檢查,但我認爲這會起作用,但是,儘管velocityInView()在底部方法中工作正常,但它不在頂部方法中(速度始終爲0)。

我有這麼蒐羅了一些解決方案,找到的姿態處理該相互覆蓋的看法很多類似的查詢,但這些似乎都關於一個手勢類型,例如在一個視圖上捏和另一種視圖,例如泛,另一方面。在我的情況下,兩種手勢類型都是相同的。

也許有人有一個聰明的想法?或者也許這其實很簡單,我已經使這個非常複雜? xD

回答

1

管理得到這個工作。

在我的問題描述的方法上面,我去掉最上面的一個保存眼前這個(它有一些變化):

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool { 
    if ((gestureRecognizer as! UIPanGestureRecognizer).velocityInView(view).y < 0 
     || pulloverVC.tableView.contentOffset.y > 0) 
     && pulloverVC.view.frame.origin.y == bottomNavbarY { 
      return true // enable tableview control 
    } 
    return false 
} 

if語句檢查的覆蓋UITableView處於其上部位置AND或者用戶不是向下拖動表內容被偏移(我們不在表的頂部)。如果這是真的,那麼我們return true來啓用tableview。

調用此方法後,實現了處理我的平移手勢的標準方法。在這裏我有一個if語句排序檢查相反以上,如果這是真的,它可以防止控制覆蓋viewB移動:

func handlePanGesture(recognizer: UIPanGestureRecognizer) { 

    let gestureIsDraggingFromTopToBottom = (recognizer.velocityInView(view).y > 0) 

    if pulloverVC.view.frame.origin.y != bottomNavbarY || (pulloverVC.view.frame.origin.y == bottomNavbarY && gestureIsDraggingFromTopToBottom && pulloverVC.tableView.contentOffset.y == 0) { 

    ... 

現在,這保持了UITableView互動,除非其父視圖viewB處於正確的位置,並且在此時禁用viewB的移動,以便僅與UITableView互動。

然後,當我們位於表格頂部並向下拖動時,與UITableView的交互被重新禁用,並且與其父視圖viewB的交互被重新啓用。

一個羅嗦的帖子和答案,但如果有人可以理解我在說什麼,希望它會幫助你。

相關問題