ios - 把父容器的平移手勢交給嵌套的UICollectionView




iphone swift (2)

您無法“切換”手勢,因為手勢識別器保持相同的對象,並且其view保持不變 - 這是手勢識別器附加到的視圖。

然而,沒有任何東西阻止你告訴別人怎麼做,以回應一個手勢。 集合視圖是一個滾動視圖,所以你知道它是如何滾動在每一個瞬間,並可以做其他事情並行。

我試圖建立一個複雜的拆分視圖容器控制器,有利於兩個可變高度的容器,每個都有自己的嵌套視圖控制器。 父控制器上有一個全局平移手勢,允許用戶拖動視圖容器中的任何位置,並在視圖之間上下滑動“分隔線”。 它還具有一些智能位置閾值檢測邏輯,可以擴展視圖(或重置分隔位置):

這工作正常。 還有很多代碼來構建這個,我很樂意分享,但是我不認為它是相關的,所以暫時忽略它。

我現在試圖通過在底部視圖中添加一個集合視圖來使事情複雜化:

我已經能夠解決這個問題了,這樣我就可以用一個決定性的平移手勢向上滾動分割視圖,並通過快速輕彈一下手指來滾動收集視圖(一個輕掃手勢,我想這是?),但是這個是一種非常不平凡的體驗:您無法同時平移視圖和滾動集合視圖,並期望用戶始終如一地複制類似但又不同的手勢,以便控制視圖太難以進行交互。

為了試圖解決這個問題,我嘗試了幾個canCancelTouchesInView /協議解決方案,在這些解決方案中我檢測分隔視圖在分割視圖中的位置,並根據底部視圖是否完全展開,在集合視圖中啟用/禁用canCancelTouchesInView和/或isUserInteractionEnable 。 這適用於某一點,但不適用於以下兩種情況:

  1. 當分割視圖分割器處於其默認位置時,如果用戶切換到底部視圖完全展開的位置,則繼續平移,集合視圖應該開始滾動,直到手勢結束。
  2. 當拆分視圖分隔符位於頂部(底部容器視圖已完全展開)且集合視圖不在頂部時,如果用戶平移,集合視圖應該滾動而不是移動分隔視圖分隔符,直到集合視圖到達其頂部位置,此時分割視圖應該返回到其默認位置。

這是一個動畫,說明了這種行為:

考慮到這一點,我開始認為解決這個問題的唯一方法是在split視圖上創建一個委託方法,當底視圖處於最大高度時告訴集合視圖,然後可以攔截父視圖的手勢或轉發屏幕接觸到集合視圖呢? 但是,我不知道該怎麼做。 如果我在一個解決方案正確的軌道上,那麼我的問題就是: 我怎樣才能轉發或平移手勢到一個集合視圖,並使集合視圖交互相同的方式,如果觸摸已被捕獲它在第一個地方? 我可以用touches____做些什麼或touches____方法嗎?

如果我不能這樣做,我還能怎樣解決這個問題呢?

賞金獵人的更新:我已經有一些碎片運氣在集合視圖上創建一個委託方法,並在分割視圖容器上調用它來設置一個屬性shouldScroll ,通過這個屬性,我使用一些平移方向和定位信息來決定是否滾動視圖應該滾動。 然後我在UIGestureRecognizerDelegategestureRecognizer:shouldReceive touch:返回這個值gestureRecognizer:shouldReceive touch: delegate method:

// protocol delegate
protocol GalleryCollectionViewDelegate {
    var shouldScroll: Bool? { get }
}

// shouldScroll property
private var _shouldScroll: Bool? = nil
var shouldScroll: Bool {
    get {
        // Will attempt to retrieve delegate value, or self set value, or return false
        return self.galleryDelegate?.shouldScroll ?? self._shouldScroll ?? false
    }
    set {
        self._shouldScroll = newValue
    }
}

// UIGestureRecognizerDelegate method
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    return shouldScroll
}

// ----------------
// Delegate property/getter called on the split view controller and the logic:
var shouldScroll: Bool? {
    get {
        return panTarget != self
    }
}

var panTarget: UIViewController! {
    get {
        // Use intelligent position detection to determine whether the pan should be
        // captured by the containing splitview or the gallery's collectionview
        switch (viewState.currentPosition,
                viewState.pan?.directionTravelled,
                galleryScene.galleryCollectionView.isScrolled) {
        case (.top, .up?, _), (.top, .down?, true): return galleryScene
        default: return self
        }
    }
}

這適用於開始滾動時,但是一旦集合視圖啟用滾動,效果不佳,因為滾動手勢幾乎總是覆蓋平移手勢。 我想知道是否可以用gestureRecognizer:shouldRecognizeSimultaneouslyWith:但我還沒有。


你應該能夠使用UICollectionViewDelegateFlowLayout通過單個集合視圖來實現你正在尋找的UICollectionViewDelegateFlowLayout 。 如果您需要針對頂視圖的任何特殊滾動行為(如視差),則仍然可以通過實現從UICollectionViewLayout繼承的自定義佈局對像在單個集合視圖中實現該UICollectionViewLayout

使用UICollectionViewDelegateFlowLayout方法比實現自定義佈局更簡單一些,所以如果你想給出一個鏡頭,請嘗試以下操作:

  • 創建您的頂視圖作為UICollectionViewCell的子類,並註冊您的集合視圖。

  • 使用func register(_ viewClass: AnyClass?, forSupplementaryViewOfKind elementKind: String, withReuseIdentifier identifier: String)將您的“divider”視圖創建為UICollectionViewCell的子類,並將其註冊為collection視圖作為補充視圖。

  • 讓您的集合視圖控制器符合UICollectionViewDelegateFlowLayout ,創建一個佈局對像作為UICollectionViewFlowLayout一個實例,將您的集合視圖控制器作為您的流佈局實例的委託,並使用您的流佈局初始化您的集合視圖。

  • 實現optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize在collecton視圖控制器中返回每個不同視圖的所需大小。







uipangesturerecognizer