tableView嵌套tableView的功能實(shí)現(xiàn)

前言

以前公司做過一個(gè)tableView嵌套tableView滾動(dòng)的功能實(shí)現(xiàn)。今天特意重新的整理了一下這個(gè)功能的實(shí)現(xiàn)。

功能需求說明:

  • 頂部是一個(gè)banner圖片
  • 側(cè)邊欄
  • 內(nèi)容tableView
    具體的實(shí)現(xiàn)效果圖如下:
    功能需求.gif

    這個(gè)功能一開始的實(shí)現(xiàn)的方式是采用的ScrollView嵌套TableView實(shí)現(xiàn)的。又重新的寫了一下這個(gè)功能模塊。這次采用的是tableView嵌套tableView實(shí)現(xiàn)的此功能。
    特別說明
    文章中實(shí)現(xiàn)的功能和此功能略有差異,但實(shí)現(xiàn)的思路是一樣的

具體實(shí)現(xiàn)

在說明實(shí)現(xiàn)方法之前先上一下現(xiàn)在的效果圖

效果圖.gif

功能實(shí)現(xiàn)部分
1.創(chuàng)建一個(gè)主控制器MainController

  • 給當(dāng)前視圖添加一個(gè)是否可以滾動(dòng)的參數(shù)canScroll。關(guān)于這個(gè)參數(shù)的使用后面再做說明
  • 控制器創(chuàng)建一個(gè)tableView
  • 給tableView實(shí)現(xiàn)相關(guān)的代理方法
  • tableViewCell的數(shù)量為1
  • 給tableView設(shè)置headerView
  • tableView設(shè)置SectionHeaderView。這個(gè)地方的headerView是為了滿足多個(gè)標(biāo)題而準(zhǔn)備的。如果不需要這個(gè)標(biāo)題只需要一個(gè)banner的話完全可以使用ScrollView+tableView來實(shí)現(xiàn)這個(gè)功能就可以了。
    特別注意:
    關(guān)于Cell高度的設(shè)置應(yīng)該是一個(gè)屏幕的高度 - SectionHeaderView的高度?;蛘哒f是你當(dāng)前tableView的高度 -SectionHeaderView的高度。當(dāng)前tableView的ContentSize的大小應(yīng)該是tableHeaderView的高度+tableView的高度 - SectionHeaderView的高度

2.自定義tableViewCell
我這里要實(shí)現(xiàn)左右滑動(dòng)切換tableView所以用到了一個(gè)ScrollView。如果沒有多個(gè)標(biāo)題的需求的話是不需要這個(gè)ScrollView的

  • 創(chuàng)建一個(gè)ScrollView
  • ScrollView的高度值和你當(dāng)前Cell的高度一致,寬度根據(jù)你的標(biāo)題個(gè)數(shù)設(shè)置。我這里是兩個(gè)標(biāo)題所以我的寬度應(yīng)該是屏幕寬*2
  • 創(chuàng)建兩個(gè)tableView添加到ScrollView上面去。tableView的高度和ScrollView高度一致。寬度是屏幕寬

至此頁(yè)面的樣式寫完了。
這個(gè)時(shí)候運(yùn)行程序的時(shí)候會(huì)發(fā)現(xiàn)上面的tableView和下面的tableView的滾動(dòng)存在沖突

3.解決tableView嵌套滾動(dòng)沖突的問題

  • 自定義一個(gè)新的tableView
  • tableView實(shí)現(xiàn)UIGestureRecognizerDelegate
  • tableView實(shí)現(xiàn)UIGestureRecognizerDelegate中的這個(gè)方法gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool
  • 判斷方法中gestureRecognizerotherGestureRecognizer是否為UIPanGestureRecognizer 是的話返回true,不是的話返回false。這個(gè)地方其實(shí)也可以直接返回True
    代碼如下
import UIKit

class BaseTableView: UITableView , UIGestureRecognizerDelegate {

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return gestureRecognizer.isKind(of: UIPanGestureRecognizer.self) && otherGestureRecognizer.isKind(of: UIPanGestureRecognizer.self)
    }
}

4.實(shí)現(xiàn)絲滑滾動(dòng)

我相信很多第一次接觸這個(gè)功能的時(shí)候,很多人想到的方法是利用tableView的ScrollEnable屬性來解決滾動(dòng)沖突的問題。千萬不要這樣做。千萬不要這樣做。千萬不要這樣做。一旦你這么做了的話,后果就是當(dāng)你發(fā)現(xiàn)要切換兩個(gè)視圖的ScrollEnable屬性的時(shí)候會(huì)出現(xiàn)明顯的卡頓情況。
正確的做法應(yīng)該是設(shè)置tableView的contentOffset的值

  • 設(shè)置MainControllerscrollViewDidScroll方法,當(dāng)滾動(dòng)高度大于等于tableHeaderView高度的時(shí)候設(shè)置tableView的contentOffsetY的高度一直為tableHeaderView的高度。一開始設(shè)置的呢個(gè)canScroll屬性就起作用了。具體代碼如下:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
        //如果高度大于等于tableHeaderView的高度的時(shí)候
        if scrollView.contentOffset.y >=  HEADER_HEIGHT{
            //設(shè)置ContentOffsetY的高度為tableHeaderView的高度
            scrollView.contentOffset = CGPoint(x: 0, y: HEADER_HEIGHT)
            if self.canScroll {
                self.canScroll = false//設(shè)置是否可以滾動(dòng)的參數(shù)為false
                //發(fā)送通知給子tableView。設(shè)置子tableView的可滾動(dòng)屬性為true
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ChilderNotice"), object: nil)
            }
        }else{
            if !self.canScroll {
                scrollView.contentOffset = CGPoint(x: 0, y: HEADER_HEIGHT)
            }
        }
    }
  • 設(shè)置子tableView的滾動(dòng)事件。具體代碼如下:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
        //開始的時(shí)候子視圖是無法滾動(dòng)的  canScroll屬性為false
        if !self.canScroll{
            scrollView.contentOffset = CGPoint.zero
        }
        //如果子視圖的滾動(dòng)高度小于等于0證明子視圖滾動(dòng)到了頭部
        if scrollView.contentOffset.y <= 0 {
            self.canScroll = false
            //給主視圖的tableView發(fā)送改變是否可以滾動(dòng)的狀態(tài)。讓主視圖的tbaleView可以滾動(dòng)
            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "mainNotice"), object: nil)
        }
    }

5.完整的代碼下載地址

完整代碼下載地址

6.感謝a1203302261提供的代碼優(yōu)化

效果圖1.png
效果圖2.png
效果圖3.png

百度網(wǎng)盤:9vxh
github
此優(yōu)化由簡(jiǎn)書用戶@a1203302261提供。在此只做總結(jié)方便下載

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

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

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