IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> [Swift]UIScrollView嵌套UITableView联动 -> 正文阅读

[移动开发][Swift]UIScrollView嵌套UITableView联动

众所周知,UITableView和UICollectionView都继承于UIScrollView,实际本文说的就是UIScrollView嵌套UIScrollView的事。

首先,自定义NestScrollView继承于UIScrollView,实现UIGestureRecognizerDelegate协议中的方法允许手势同时识别。

import Foundation
import UIKit

class NestScrollView: UIScrollView {

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

}

extension NestScrollView: UIGestureRecognizerDelegate {
    
    /// 这是实现手势穿透的关键代码。
    /// 返回 YES 允许两者同时识别。 默认实现返回 NO(默认情况下不能同时识别两个手势)
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
    
}

底层,让scrollView继承NestScrollView,实现scrollViewDidScroll:方法,然后接收"ScrollViewCanScroll"通知。

import Foundation
import UIKit

class GAListVC: UIViewController {
    
    @IBOutlet weak var scrollView: NestScrollView!
    @IBOutlet weak var bgHConstraint: NSLayoutConstraint!
    @IBOutlet weak var bgView: UIView!
    private var canScroll: Bool = true

    private lazy var headerView: UIView = {
        let view = Bundle.main.loadNibNamed("GAHeaderView", owner: nil, options: nil)![0] as! GAHeaderView
        return view
    }()
    
    private lazy var contentVC: GAContentVC = {
        let vc = GAContentVC()
        return vc
    }()
    
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
        NotificationCenter.default.addObserver(self, selector: #selector(ScrollViewCanScroll(_:)), name: NSNotification.Name("ScrollViewCanScroll"), object: nil)
    }
    
    @objc private func ScrollViewCanScroll(_ notifi: Notification) {
        canScroll = true
    }
 
    private func setupUI() {
        self.navigationController?.isNavigationBarHidden = true
        if #available(iOS 11.0, *){
            scrollView.contentInsetAdjustmentBehavior = .never
        } else {
            self.automaticallyAdjustsScrollViewInsets = false
        }
        
        let headerHeigth: CGFloat = 200.0
        headerView.frame = CGRect(x: 0, y: 0, width: UIDevice.screenWidth(), height: headerHeigth)
        bgView.addSubview(headerView)
        
        let contentHeight: CGFloat = UIDevice.screenHeight() - UIDevice.statusBarHeight()
        contentVC.view.frame = CGRect(x: 0, y: headerHeigth, width: UIDevice.screenWidth(), height: contentHeight)
        bgView.addSubview(contentVC.view)
        contentVC.startReloadVC()
        
        let bgHeight: CGFloat = headerHeigth + contentHeight
        bgHConstraint.constant = bgHeight
    }
    
}

extension GAListVC: UIScrollViewDelegate {

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        // 允许顶部的偏移
        let topOffset: CGFloat = 200.0 - UIDevice.statusBarHeight()
        if self.canScroll == false {
            // canScroll为false时,固定contentOffset,使其不滚动。
            scrollView.contentOffset = CGPoint(x: 0, y: topOffset)
        } else if (scrollView.contentOffset.y >= topOffset) {
            scrollView.contentOffset = CGPoint(x: 0, y: topOffset)
            self.canScroll = false
            // 滑动到顶部,通知嵌套tableView改变tableCanScroll的状态
            NotificationCenter.default.post(name: NSNotification.Name("TableViewCanScroll"), object: nil, userInfo: nil)
        }
    }
    
}

内层,就实现scrollViewDidScroll:方法,然后接收"TableViewCanScroll"通知。

import Foundation
import UIKit

class GAContentVC: UIViewController {
    
    @IBOutlet weak var cateTableView: UITableView!
    @IBOutlet weak var listTableView: UITableView!
    private var dataArray: [GACategoryModel] = []
    private var tableCanScroll: Bool = false
    
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableCanScroll = false
        NotificationCenter.default.addObserver(self, selector: #selector(tableViewCanScroll(_:)), name: NSNotification.Name("TableViewCanScroll"), object: nil)
    }
    
    @objc private func tableViewCanScroll(_ notifi: Notification) {
        tableCanScroll = true
    }
       
    func startReloadVC() {

    }
 
}

extension GAContentVC: UITableViewDelegate, UITableViewDataSource {
	......
}

extension GAContentVC: UIScrollViewDelegate {

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if tableCanScroll == false {
            scrollView.contentOffset = CGPoint.zero
        } else if (scrollView.contentOffset.y <= 0) {
            tableCanScroll = false
            // 通知ScrollView改变CanScroll的状态
            NotificationCenter.default.post(name: NSNotification.Name("ScrollViewCanScroll"), object: nil, userInfo: nil)
        }
    }
    
    /// 解决一个问题。列表1的y坐标为0时,向上滚动列表2后,再回头向下滚动列表1,这时列表1滚动不响应。
    func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
        if scrollView == cateTableView {
            let listOffset = listTableView.contentOffset
            if listOffset.y == 0 {
                let scrEnabled = listTableView.isScrollEnabled
                listTableView.isScrollEnabled = false
                listTableView.contentOffset = CGPoint(x: listOffset.x, y: 1)
                listTableView.isScrollEnabled = scrEnabled
            }
        } else {
            let cateOffset = cateTableView.contentOffset
            if cateOffset.y == 0 {
                let scrEnabled = cateTableView.isScrollEnabled
                cateTableView.isScrollEnabled = false
                cateTableView.contentOffset = CGPoint(x: cateOffset.x, y: 1)
                cateTableView.isScrollEnabled = scrEnabled
            }
        }
    }
    
}

Demo GitHub: https://github.com/Gamin-fzym/GAScrollViewNestDemo

Demo示意图:
在这里插入图片描述
同理,也能实现这样的页面效果。
在这里插入图片描述

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-05-09 12:51:06  更:2022-05-09 12:52:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 1:31:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码