多層UIscrollViewネストスクロール

4448 ワード

前の問題
本論文は主に多層UIscroollViewネストローリングソリューションの学習とSegementSlide実践の探索に基づいている.
テーマ
多層UIScrollViewネストスクロールを実現し、ここでの多層は実は2層であり、2層を超えるUIScrollViewネストスクロールは複雑である.
一般的なソリューション
1、isScrollEnabled属性の制御
scrollViewを通ります.contentOffset.y臨界値と比較し、両者のscrollViewのisScrrollEnabled属性値を変更して目的を達成する.欠点:臨界値にスライドするとスクロールが中断され、scrollViewを切り替えるには2回スライドする必要があります.このようなインタラクションは受け入れにくい.
2、カスタムスライドジェスチャー
カスタムでスライドジェスチャーを実現します.欠点:スライドジェスチャーの複雑さは多様で、処理しにくいのはシステムと同じです.カスタムジェスチャーなので、細部は自分で処理する必要があります.
3、ジェスチャースルー
まずジェスチャーで貫通し,2層scrollViewの同時スクロールを実現する.次に、フラグビット(臨界値)によって、下位レベルのscrollViewスクロールがいつ許可されるか、および上位レベルのscrollViewスクロールがいつ許可されるかを制御する.注意:どのレベルのscrollViewがスクロールできるかは、別のレベルのscrollViewがスクロールできないというわけではありませんが、別のレベルのscrollViewにスクロールできない効果を達成するために一定のオフセットを設定しています.
  • 3.1ジェスチャー
  • を貫通
    //       UIGestureRecognizerDelegate
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
    
  • 3.2制御スライド
  • func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if scrollView == rootScrollView {
            if !canParentViewScroll {
                rootScrollView.contentOffset.y = headerStickyHeight // point A
                canChildViewScroll = true
            } else if scrollView.contentOffset.y >= headerStickyHeight {
                rootScrollView.contentOffset.y = headerStickyHeight
                canParentViewScroll = false
                canChildViewScroll = true
            }
        } else {
            if !canChildViewScroll {
                childScrollView.contentOffset.y = 0 // point B
            } else if scrollView.contentOffset.y <= 0 {
                canChildViewScroll = false
                canParentViewScroll = true
            }
        }
    }
    

    SegementSlideはジェスチャー透過を用いて多層UIscrollViewネストされたスクロールを実現し、実際によく見られる問題を解決した.
  • 異なるtabを切り替えることにより、位置変異の問題
  • が生じる.
    internal func resetChildViewControllerContentOffsetY() {
        guard segementSlideScrollView.contentOffset.y < headerStickyHeight else {
            return
        }
        let collection = waitTobeResetContentOffsetY
        for index in collection {
             guard index != currentIndex,
             let scrollView = dequeueReusableViewController(at: index)?.scrollView else {
                 continue
             }
              waitTobeResetContentOffsetY.remove(index)
              scrollView.contentOffset.y = 0
         }
     }
    

    ソリューション:最下位のscrollViewでスクロールが許可されている場合、上位の他の非表示tabのscrollViewのオフセット量を0に設定します.
  • スライドHeaderView、スライド連動できない
  • internal override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        let view = super.hitTest(point, with: event)
        guard let segementSlideContentView = segementSlideContentView else {
            return view
        }
        guard let selectedIndex = segementSlideContentView.selectedIndex,
              let segementSlideContentScrollViewDelegate = segementSlideContentView.dequeueReusableViewController(at: selectedIndex) else {
            return view
        }
        if view is UIControl {
            return view
        }
        if !(view?.gestureRecognizers?.isEmpty ?? true) {
            return view
        }
        return segementSlideContentScrollViewDelegate.scrollView
    }
    

    ソリューション:HeaderViewのクリックイベントを現在のtabの下のscrollViewに変換し、スライド連動を実現
  • 上層scrollViewの減衰効果を実現し、上層scrollViewのドロップダウン
  • をリフレッシュできるようにする.
    //     
    public enum BouncesType {
       case parent     //   ScrollView     
       case child      //   ScrollView     
    }
    open var bouncesType: BouncesType {
        return .parent
    }
               ,  bouncesType     
    

    解決策:オフセット量をより細かく分割し、臨界点でスライド可能なScrollViewを切り替え、別のScrollViewを固定します.
    もちろん、SegementSlideはより多くのニーズを実現し、具体的には深く学ぶことができます.
    欠点:
  • マルチタブの場合、1つのchildが上部に戻ると、他のchildが上部に戻る.これが「位置突然変異」を解決する上での副作用である.個人的には納得できる.

  • マルチタブの場合、各childは1つのScrollViewを返さなければならず、ScrollViewはViewをいっぱいにしなければならない.そうしないと、スライドした後、ドロップダウンできない.このような状況に直面して、私のやり方:tableViewに戻り、tableViewにコンテンツを追加する
  • 動力が不足しているのは、固定オフセット量が設定されているため、転がりの動力が弱まっているためである.


  • 注意:
  • SegementSlideViewControllerに戻ると、表示されたすべてのchildのviewWillAppear or viewWillDisappearが実行されます.これはSegementSlideの理由ではありません.addChild(_childControl:UIViewControl)を使用しているすべての問題です.だから自分のニーズに応じてviewWillAppear or viewWillDisappearで論理を実現します.

  • 関連リソース
    多層UIscrollViewネストスクロールソリューションSegementSlide