本次效果是參考此文(http://www.itdecent.cn/p/38f0b7eef959)實現(xiàn)的,在此多謝此文作者分享!
思路精髓:實現(xiàn)手勢的穿透響應(也就是不論最上層是否有對象響應滑動手勢,都將這個手勢往底層傳遞),給每個tableView 添加一個shouldScroll的實例變量,通過tableView的代理方法監(jiān)聽contentOffset ,根據(jù)偏移量做判斷并發(fā)送相應通知,然后設置不應該滑動的那個tableView的contentOffset為CGPointZero即可。
- ps: 我為了實現(xiàn)公司的需求,又多嵌套了一層UICollectionView,但萬變不離其宗,思路都是一樣。
先上效果圖

效果動圖.gif
在此,只分析兩個tableView的滑動邏輯
- 底層的UITableView 命名為 tableView
- 嵌套在內(nèi)的UITableView 命名為 innerTableView
自定義UITableView,命名為GXInnerTableView,在GXInnerTableView中遵循 UIGestureRecognizerDelegate協(xié)議,并實現(xiàn)如下方法 ,這是實現(xiàn)手勢穿透的關鍵代碼
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
接下來分別實現(xiàn)兩個tableView的ScrollViewDidScroll代理方法
- tableView的代理方法
/// tableView是否能夠滾動
var shouldScroll:Bool = true
/// 底部的理論上是否應該滾動
var bottomShouldScroll:Bool = true
/// 頂部的理論上是否應該滾動
var upperShouldScroll:Bool = true
func scrollViewDidScroll(scrollView: UIScrollView) {
print(scrollView.contentOffset.y)
// header頭的高度是150
let standardOffsetY:CGFloat = 150
let offsetY:CGFloat = scrollView.contentOffset.y
bottomShouldScroll = upperShouldScroll
if offsetY >= standardOffsetY{ //如果偏移量大于header頭的高度,不能繼續(xù)滑動,固定tableView的偏移量
scrollView.contentOffset = CGPointMake(0, standardOffsetY)
upperShouldScroll = true
}else{
upperShouldScroll = false
}
if upperShouldScroll != bottomShouldScroll {
if !bottomShouldScroll && upperShouldScroll{
NSNotificationCenter.defaultCenter().postNotificationName(goTopNotificationName, object: nil)
shouldScroll = false
}
if bottomShouldScroll && !upperShouldScroll{
if !shouldScroll{
scrollView.contentOffset = CGPointMake(0, standardOffsetY)
}
}
}
}
- innerTableView的代理方法
func scrollViewDidScroll(scrollView: UIScrollView) {
print(scrollView.contentOffset.y)
if !shouldScroll {
scrollView.setContentOffset(CGPointZero, animated: false)
}
if scrollView.contentOffset.y <= 0{
NSNotificationCenter.defaultCenter().postNotificationName(leaveTopNotificationName, object: nil)
}
}
在代理方法中都發(fā)送了通知,自然需要對相應的通知進行監(jiān)聽了
- tableView對通知的監(jiān)聽方法
@objc private func changeScrollEnable(notification:NSNotification){
shouldScroll = true
}
- innerTableView對通知的監(jiān)聽方法
@objc private func changeScrollEnable(notification:NSNotification){
let nameStr = notification.name
if nameStr == goTopNotificationName{
innerTableView.showsVerticalScrollIndicator = true
shouldScroll = true
}else if nameStr == leaveTopNotificationName{
innerTableView.contentOffset = CGPointZero
shouldScroll = false
innerTableView.showsVerticalScrollIndicator = false
}
}
OK,關鍵代碼就這些,不足之處望簡友多多指教。