IOS嵌套scrollview滑动切换页面tab吸顶

嵌套scrollview, 实现tab吸顶,页面左右滑动切换,上滑tab吸顶,自己研究了一下,下面看看效果

42731e2528d845a29dbc7ef2829a886e.png

 

创建一些基本UI 

/// 屏幕宽度

let Screen_Width = UIScreen.main.bounds.width

 

/// 屏幕高度

let Screen_Height = UIScreen.main.bounds.height

 

 

class JWDoubleScrollViewVC: UIViewController {

 

    var headView:UIView?

    var slideLine:UILabel?

    var segBtns = [UIButton]()

    var tableviews = [UITableView]()

    

    let segWidth = Screen_Width / 4

    let headViewH = 300

    let segH = 40

    var currentTabIndex = 0

    var distance:Int{

        get{

            return headViewH - segH

        }

    }

    

    fileprivate var rootScrollView:MyScrollView={

        let scrollview = MyScrollView.init()

        scrollview.backgroundColor = UIColor.white

        scrollview.bounces = false

        scrollview.showsVerticalScrollIndicator = false

        scrollview.showsHorizontalScrollIndicator = false

        return scrollview

    }()

    

    fileprivate var containerScrollView:UIScrollView = {

        let scrollview = UIScrollView.init()

        scrollview.backgroundColor = UIColor.white

        scrollview.bounces = false

        scrollview.isPagingEnabled = true

        scrollview.showsVerticalScrollIndicator = false

        scrollview.showsHorizontalScrollIndicator = false

        return scrollview

    }()

    

    override func viewDidLoad() {

        super.viewDidLoad()

 

        // Do any additional setup after loading the view.

        self.view.backgroundColor = UIColor.white

 

        self.setupUI()

    }

    

    override func viewWillAppear(_ animated: Bool) {

        super.viewWillAppear(animated)

        rootScrollView.isScrollEnabled = true

    }

    

    

    func setupUI() {

        

        rootScrollView.delegate = self

        containerScrollView.delegate = self

        

        let rootView = UIView.init()

        self.view.addSubview(rootView)

        rootView.snp.makeConstraints { (make) in

            make.top.equalTo(90)

            make.left.right.bottom.equalToSuperview()

        }

        rootView.layoutIfNeeded()

        

        rootView.addSubview(rootScrollView)

        rootScrollView.snp.makeConstraints { (make) in

            make.edges.equalTo(rootView)

        }

        rootScrollView.layoutIfNeeded()

        

        //headview

        headView = UIView.init()

        headView?.backgroundColor = UIColor.blue

        rootScrollView.addSubview(headView!)

        headView?.snp.makeConstraints({ (make) in

            make.top.left.right.equalToSuperview()

            make.width.equalTo(Screen_Width)

            make.height.equalTo(headViewH)

        })

        headView?.layoutIfNeeded()

        

        rootScrollView.addSubview(containerScrollView)

        containerScrollView.snp.makeConstraints { (make) in

            make.left.right.bottom.equalToSuperview()

            make.top.equalTo(headView!.snp.bottom)

            make.width.equalTo(Screen_Width)

            make.height.equalTo(rootScrollView.frame.height)

        }

        containerScrollView.layoutIfNeeded()

        

        //tab背景view

        let btnContainerView = UIView.init()

        rootScrollView.addSubview(btnContainerView)

        btnContainerView.snp.makeConstraints { (make) in

            make.left.right.equalToSuperview()

            make.height.equalTo(segH)

            make.bottom.equalTo(headView!.snp.bottom)

            make.width.equalTo(Screen_Width)

        }

        btnContainerView.layoutIfNeeded()

        

        for i in 0...3 {

            //添加Tab

            let button = self.createButton(i)

            btnContainerView.addSubview(button)

            segBtns.append(button)

            

            //添加tableview

            let tableview = self.createTableView(i)

            containerScrollView.addSubview(tableview)

            tableviews.append(tableview)

        }

        

        //tab底部横线

        slideLine = UILabel.init(frame: CGRect.init(x: 0, y: CGFloat(segH - 6), width: segWidth, height: 4))

        slideLine?.backgroundColor = .white

        slideLine?.layer.cornerRadius = 4/2

        slideLine?.layer.masksToBounds = true

        btnContainerView.addSubview(slideLine!)

        

        //设置scrollview滑动区域

        containerScrollView.contentSize = CGSize.init(width: CGFloat(segBtns.count) * Screen_Width, height: 0)

    }

    

    /**

    创建Tab

     */

    func createButton(_ i:Int) -> UIButton {

        let button = UIButton.init(type: .custom)

        button.frame = CGRect.init(x: CGFloat(i)*segWidth, y: 0, width: segWidth, height: CGFloat(segH))

        button.setTitle(String.init(format: "第%i个", i), for: .normal)

        button.titleLabel?.textAlignment = .center

        button.tag = 1000 + i

        button.backgroundColor = .red

        button.setTitleColor(UIColor.white, for: .normal)

        button.setTitleColor(UIColor.yellow, for: .selected)

        button.addTarget(self, action: #selector(segAction(button:)), for:.touchUpInside)

        return button

    }

    

    /**

     创建tableview

     */

    func createTableView(_ i:Int) ->UITableView{

        let tableView = UITableView.init(frame: .zero, style: .plain)

        tableView.frame = CGRect.init(x: CGFloat(i)*Screen_Width, y: 0, width: Screen_Width, height: rootScrollView.frame.height - CGFloat(segH))

        tableView.delegate = self

        tableView.dataSource = self

        tableView.backgroundColor = .green

        tableView.sectionHeaderHeight = 0

        tableView.sectionFooterHeight = 0

        //tableView.bounces = false

        tableView.backgroundColor = UIColor.white

        tableView.register(UITableViewCell.classForCoder(), forCellReuseIdentifier: NSStringFromClass(UITableViewCell.classForCoder()))

        return tableView

    }

    

 

    /**

     滑动tab切换

     */

    func sliderAnimationWithTag(tag:Int){

        

        rootScrollView.isScrollEnabled = true

        

        currentTabIndex = tag;

        

        for item in segBtns.enumerated() {

            let button = item.element

            button.isSelected = false

        }

        

        let button = segBtns[tag]

        button.isSelected = true

        

        UIView.animate(withDuration: 0.25) { [weak self] in

            self!.slideLine?.center = CGPoint.init(x: CGFloat(button.center.x), y: CGFloat((self!.slideLine?.center.y)!))

        }

        

    }

    

    @objc func segAction(button:UIButton) {

        

        //滑动到指定页面

        containerScrollView.setContentOffset(CGPoint.init(x:CGFloat(button.tag - 1000) * Screen_Width, y: 0), animated: true)

 

    }

    

    //tablview是否可以滑动

    func canTableViewScroll() -> Bool {

        return rootScrollView.contentOffset.y >= CGFloat(self.distance)

    }

    

    //主rootscrollview是否可以滑动

    func canRootViewScroll() -> Bool {

        return tableviews[currentTabIndex].contentOffset.y <= 0

    }

 

    /*

    // MARK: - Navigation

 

    // In a storyboard-based application, you will often want to do a little preparation before navigation

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        // Get the new view controller using segue.destination.

        // Pass the selected object to the new view controller.

    }

    */

 

}

 

此部分处理嵌套scrollview手势页面交互

extension JWDoubleScrollViewVC:UIScrollViewDelegate{

    

    

    func scrollViewDidScroll(_ scrollView: UIScrollView) {

        

        if scrollView.isKind(of: UITableView.classForCoder()){ //tableview

            

            let offY = tableviews[currentTabIndex].contentOffset.y;

            if offY < 0 {

                tableviews[currentTabIndex].contentOffset = .zero;//去掉tableview上方弹性

            }

            

            guard !canTableViewScroll() else {

                return

            }

            

            scrollView.contentOffset.y = 0

 

        }else if scrollView === rootScrollView{  //主scrollview

            

            

            guard !canRootViewScroll() else {

                return

            }

            

            let sliderSafeArea = (self.distance);

            

            scrollView.setContentOffset(CGPoint.init(x: 0, y: sliderSafeArea), animated: false)

            

        }else if scrollView === containerScrollView{ //滑动scrollview

            

            rootScrollView.isScrollEnabled = false

            

            //滑动切换Tab

            let page = Double(scrollView.contentOffset.x/Screen_Width)

            self.sliderAnimationWithTag(tag: Int(page + 0.5))

            

        }

    }

    

    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {

            rootScrollView.isScrollEnabled = true

    }

    

    

}

 

extension JWDoubleScrollViewVC:UITableViewDelegate,UITableViewDataSource{

    func numberOfSections(in tableView: UITableView) -> Int {

        return 1

    }

    

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

        return 50.0

    }

    

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return 30

    }

    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let tableviewcell = tableView.dequeueReusableCell(withIdentifier: NSStringFromClass(UITableViewCell.classForCoder()), for: indexPath)

        tableviewcell.textLabel?.text = String.init(format: "第%i个", indexPath.row)

        tableviewcell.backgroundColor = .orange

        return tableviewcell

    }

    

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        tableView.deselectRow(at: indexPath, animated: false)

    }

    

}

 

 

class MyScrollView:UIScrollView,UIGestureRecognizerDelegate{

    

    //当前scrollview与其他scrollview都响应手势操作

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {

        return true

    }

}

 

 

demo 地址:jwsource/JSDoubleScrollView

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值