iOS-嵌套滾動

你是否也遇到過這個效果,嵌套滾動? 如何實現(xiàn)呢

image.gif

\

首先,我們知道,這一定一個嵌套滾動的問題.
基礎(chǔ)的頁面搭建不再贅述,直接闡述解決辦法.

通過手勢穿透,即讓一個滑動手勢既作用于底層的ScrollView又能作用于上層的業(yè)務(wù)tableView,同時控制他們的滾動即可達成目的。
  • 比如說外層是一個TableView,我們讓外層這個TableView實現(xiàn)UIGestureRecognizerDelegate的這個shouldRecognizeSimultaneouslyWith方法,當(dāng)滾動的是tag為100的view時,返回true,也就是這個view也能響應(yīng)到滾動事件
class TKGestureTableView: UITableView, UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        if let otherView = otherGestureRecognizer.view {
            if otherView.tag == 100 {
                return true
            }
        }
        return false
    }
    
}

  • 然后內(nèi)層的tablView設(shè)置一個tag = 100
 lazy var listView:UITableView = {
        let tableView = UITableView()
        tableView.delegate = self
        tableView.dataSource = self
        tableView.rowHeight = UITableView.automaticDimension
        tableView.register(InnerNormalCell.classForCoder(), forCellReuseIdentifier: "InnerNormalCell")
        tableView.estimatedRowHeight = 40
        tableView.tag = 100
        return tableView
    }()
  • 這樣,當(dāng)用戶滑動底部的時候,兩個view的滾動事件是都可以監(jiān)聽到的;然后通過控制兩個內(nèi)外兩個View的滾動事件,完成上面的gif效果
外層的滾動

  var isTopAndCanNotMoveTabViewPre:Bool = false
    var isTopAndCanNotMoveTabView:Bool = false
    var canScroll:Bool = false
    

func scrollViewDidScroll(_ scrollView: UIScrollView) {
        print("out---\(scrollView.contentOffset)")
        ///吸頂效果
        let offsetY = scrollView.contentOffset.y
            let tabOffsetY:CGFloat = CGFloat(Int(listView.rectForRow(at: IndexPath(row: 4, section: 0)).origin.y))
            isTopAndCanNotMoveTabViewPre = isTopAndCanNotMoveTabView
            if offsetY >= tabOffsetY {
                scrollView.contentOffset = CGPoint(x: 0, y: tabOffsetY)
                isTopAndCanNotMoveTabView = true
            }else {
                isTopAndCanNotMoveTabView = false
            }
            if (isTopAndCanNotMoveTabView != isTopAndCanNotMoveTabViewPre){
                if (!isTopAndCanNotMoveTabViewPre && isTopAndCanNotMoveTabView) {
                    //上滑-滑動到頂端
                    print("out---上滑-滑動到頂端--\(scrollView.contentOffset)")
                    NotificationCenter.default.post(name: Notification.Name.goTopNotificationName, object: nil, userInfo: ["canScroll":"1"])
                    canScroll = false
                }
                if(isTopAndCanNotMoveTabViewPre && !isTopAndCanNotMoveTabView){
                    //下滑-離開頂端
                    print("out---下滑-離開頂端--\(scrollView.contentOffset)")
                    if (!canScroll) {
                        scrollView.contentOffset = CGPoint(x: 0, y: tabOffsetY)
                    }
                }
            }
        
    }
外層的監(jiān)聽 及 響應(yīng)
//建立通知中心 監(jiān)聽離開置頂命令
        NotificationCenter.default.addObserver(self, selector: #selector(acceptMsg(notification:)), name: Notification.Name.leaveTopNotificationName, object: nil)
        //建立通知中心 監(jiān)聽進入置頂命令
        NotificationCenter.default.addObserver(self, selector: #selector(acceptMsg(notification:)), name: Notification.Name.goTopNotificationName, object: nil)

/// 接收到通知的回調(diào)
    ///
    /// - Parameter notification:
    @objc func acceptMsg(notification: Notification) {
        let notificationName = notification.name
        if notificationName == Notification.Name.goTopNotificationName {//到達已經(jīng)吸頂部分
            if let canScroll_str = notification.userInfo?["canScroll"] as? String {
                if canScroll_str == "1" {
                    canScroll = false
                }
            }
        }else if notificationName == Notification.Name.leaveTopNotificationName {//離開吸頂部分
            listView.contentOffset = CGPoint.zero
            canScroll = true
        }
    }
    
內(nèi)層的滾動
 func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if (!InnerScrollerViewController.canScroll) {
            scrollView.contentOffset = CGPoint.zero
        }
        let offsetY = scrollView.contentOffset.y
        if (offsetY < 0) {
            print("inner---下拉--\(scrollView.contentOffset)")
            NotificationCenter.default.post(name: Notification.Name.leaveTopNotificationName, object: nil, userInfo: ["canScroll":"1"])
        }else{
            print("inner---上滑--\(scrollView.contentOffset)")
        }
    }
內(nèi)層的監(jiān)聽 及 響應(yīng)
       NotificationCenter.default.addObserver(self, selector: #selector(acceptMsg(notification:)), name: Notification.Name.leaveTopNotificationName, object: nil)
       NotificationCenter.default.addObserver(self, selector: #selector(acceptMsg(notification:)), name: Notification.Name.goTopNotificationName, object: nil)

/// 接收到通知的回調(diào)
   ///
   /// - Parameter notification:
   @objc func acceptMsg(notification: Notification) {
       let notificationName = notification.name
       if notificationName == Notification.Name.goTopNotificationName {
           if let canScroll_str = notification.userInfo?["canScroll"] as? String {
               if canScroll_str == "1" {
                   InnerScrollerViewController.canScroll = true
               }
           }
       }else if notificationName == Notification.Name.leaveTopNotificationName {
           listView.contentOffset = CGPoint.zero
           InnerScrollerViewController.canScroll = false
       }
   }

詳見:
https://github.com/bjduhuan/NestedScrollingTest.git

對您有幫助的話,歡迎點點小心心~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 日常業(yè)務(wù)中,總是會有一個業(yè)務(wù),基本是每個iOS 開發(fā)都會做到的需求,就是頂部一個 header,底部一個 segm...
    簡單coder閱讀 2,943評論 4 14
  • 用兩張圖告訴你,為什么你的 App 會卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 13,898評論 2 59
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時...
    歐辰_OSR閱讀 30,187評論 8 265
  • 用到的組件 1、通過CocoaPods安裝 2、第三方類庫安裝 3、第三方服務(wù) 友盟社會化分享組件 友盟用戶反饋 ...
    SunnyLeong閱讀 15,134評論 1 180
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,619評論 1 32

友情鏈接更多精彩內(nèi)容