「Swift」类抖音、小红书等个人中心多个子控制器功能

需求背景:类似抖音小红书等个人中心文章发布、文章点赞、文章收藏等多子控制器功能,并且子控制器可左右滑动和下拉刷新

技术方案:JXPagingView使用方法详情(JXPagingListRefreshView子页面刷新)

寻找相关资料,发现github上JXPagingView可以实现该功能,以下详细介绍JXPagingListRefreshView使用方法

github: https://github.com/pujiaxin33/JXPagingView

首先在podfile中引入相关库文件

   pod 'JXPagingView'
   pod 'JXSegmentedView'

ps:JXSegmentedView是个分类切换滚动视图
github:https://github.com/pujiaxin33/JXSegmentedView

父控制器相关代码:


import UIKit
import JXPagingView
import JXSegmentedView

/// 父控制器
class HomeViewController: BaseViewController {
	///文章分类上方部分
    private var myHeaderView = HomeHeaderView()
    
    ///三个子控制器
    private var hotChildVC = HomeHotListChildViewController()
    private var newChildVC = HomeNewListChildViewController()
    private var allChildVC = HomeAllListChildViewController()
    
   	///这里上滑触顶的时候,状态栏为透明色
    private var blankView = UIView()
    
    lazy var pagingView: JXPagingListRefreshView = JXPagingListRefreshView(delegate: self)
    
    lazy var segmentedView: JXSegmentedView = JXSegmentedView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: CGFloat(headerInSectionHeight)))
    var dataSource = JXSegmentedTitleDataSource()
    var titles = ["热门", "最新", "全部"]
    
    ///分类上方头部高度
    private var headerViewHeight: Int = Int(205.fit() + Common.navigationBarHeight)
    ///分类标题高度
    private var headerInSectionHeight: Int = Int(52.fit())
    ///上滑触顶偏移量
    private var pagingViewPinSectionHeaderVerticalOffset: Int = Int(31.fit())
 
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        initView()
        setupLayout()
    }
    
    private func initView() {
        self.isNavBarisHidden = true
        self.view.backgroundColor = UIColor.design(.design_F7F7F7)
        
        blankView.backgroundColor = UIColor.design(.design_F7F7F7)
        
        ///分类标题栏数据内容
        dataSource.titles = titles
        dataSource.titleSelectedColor = UIColor.design(.design_24292B)
        dataSource.titleNormalColor = UIColor.design(.design_9DA2A5)
        dataSource.titleNormalFont = UIFont.font(of: 16.fit(), weight: .medium)
        dataSource.isTitleColorGradientEnabled = true
        dataSource.isTitleZoomEnabled = false

        segmentedView.backgroundColor = UIColor.design(.design_F7F7F7)
        segmentedView.delegate = self
        segmentedView.dataSource = dataSource
        segmentedView.listContainer = pagingView.listContainerView

        //扣边返回处理,下面的代码要加上(demo中展示需加上)
        pagingView.listContainerView.scrollView.panGestureRecognizer.require(toFail: self.navigationController!.interactivePopGestureRecognizer!)
        pagingView.mainTableView.panGestureRecognizer.require(toFail: self.navigationController!.interactivePopGestureRecognizer!)
               self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
        
        pagingView.pinSectionHeaderVerticalOffset = pagingViewPinSectionHeaderVerticalOffset

        pagingView.backgroundColor = UIColor.design(.design_F7F7F7)

        self.view.addSubview(pagingView)
        self.view.addSubview(blankView)
    }
    
    private func setupLayout() {        
        pagingView.snp.makeConstraints { make in
            make.top.equalToSuperview()
            make.left.equalToSuperview()
            make.width.equalTo(Common.screenWidth)
            make.height.equalTo(Common.screenHeight)
        }
        
        blankView.snp.makeConstraints { make in
            make.top.equalToSuperview()
            make.left.equalToSuperview()
            make.width.equalTo(Common.screenWidth)
            make.height.equalTo(Common.navigationBarHeight)
        }
    }
    
}

///JXpagingView代理方法
extension HomeViewController: JXPagingViewDelegate {
    func tableHeaderViewHeight(in pagingView: JXPagingView) -> Int {
    	///上方头部高度
        return headerViewHeight
    }
    
    func tableHeaderView(in pagingView: JXPagingView) -> UIView {
    	///上方头部View(我这里使用的自定义View,建议提出单独写View)
        return myHeaderView
    }
    
    func heightForPinSectionHeader(in pagingView: JXPagingView) -> Int {
    	///上滑移动最大偏移量(大于这个偏移量就无法再上滑)
        return headerInSectionHeight
    }
    
    func viewForPinSectionHeader(in pagingView: JXPagingView) -> UIView {
    	///分类文章标题View
        return segmentedView
    }
    
    func numberOfLists(in pagingView: JXPagingView) -> Int {
    	///分类标题个数
        return titles.count
    }
    
    func pagingView(_ pagingView: JXPagingView, initListAtIndex index: Int) -> JXPagingViewListViewDelegate {
        ///每个标题分别对应的子控制器
        if index == 0 {
            return hotChildVC
            
        } else if index == 1 {
            return newChildVC
            
        } else {
            return allChildVC
        }
    }
    
    func pagingView(_ pagingView: JXPagingView, mainTableViewDidScroll scrollView: UIScrollView) {
        
    }

}

extension HomeViewController: JXSegmentedViewDelegate {
	///默认的分类标题选择项
    func segmentedView(_ segmentedView: JXSegmentedView, didSelectedItemAt index: Int) {
        self.navigationController?.interactivePopGestureRecognizer?.isEnabled = (index == 0)
    }
}

/// 需要将JXPagingListContainerView继承JXSegmentedViewListContainer,不然会报错,开发文档中也有所提及
extension JXPagingListContainerView: JXSegmentedViewListContainer {}

子控制器相关代码:

import UIKit
import JXPagingView
import MJRefresh

/// 热门商品列表
class HomeHotListChildViewController: UIViewController, JXPagingViewListViewDelegate {
	///三个子控制器需要添加的代理方法
    func listView() -> UIView {
        return self.view
    }

    func listScrollView() -> UIScrollView {
    	///传入带有UIScrollView的组件,可以进行滚动
        return self.myTableView
    }

    func listViewDidScrollCallback(callback: @escaping (UIScrollView) -> ()) {
    	///这个比较重要,可以将父控制器的上下滚动传递进来
        self.scrollCallback = callback
    }

    private var myTableView: UITableView!
    
    private var productList = [productModel]()
    
    /// scrollView回调
    var scrollCallback:((UIScrollView) -> Void)?

    override func viewDidLoad() {
        super.viewDidLoad()

        initView()
        setupLayout()
        requestData()
        addUpDownPullRefresh()
    }
    
    private func initView() {
        self.view.backgroundColor = UIColor.design(.design_F7F7F7)
        
        myTableView = UITableView(frame: .zero, style: .plain)
        myTableView.backgroundColor = UIColor.design(.design_F7F7F7)
        myTableView.showsVerticalScrollIndicator = false
        myTableView.separatorStyle = .none
        myTableView.delegate = self
        myTableView.dataSource = self
        
        myTableView.register(HomeProductCell.self, forCellReuseIdentifier: NSStringFromClass(HomeProductCell.self))
        
        self.view.addSubview(myTableView)
        
    }
    
    private func setupLayout() {
        myTableView.snp.makeConstraints { make in
            make.top.equalTo(8.fit())
            make.left.equalTo(16.fit())
            make.right.equalTo(-16.fit())
            make.bottom.equalToSuperview()
        }
    }
    
    ///添加tableView的下拉刷新和上拉加载更多
    private func addUpDownPullRefresh() {
        myTableView.mj_header = MJRefreshNormalHeader(refreshingBlock: { [weak self] in
            guard let self = self else {return}
            self.requestData()
        })
        
        myTableView.mj_footer = MJRefreshAutoNormalFooter(refreshingBlock: { [weak self] in
            guard let self = self else {return}
            self.requestDataMore()
        })
    }
    
    private func requestData() {
		print("requestData")

        myTableView.mj_footer?.resetNoMoreData()
        myTableView.mj_header?.endRefreshing()
    }
    
    private func requestDataMore() {
        print("requestDataMore")
        
        myTableView.mj_footer?.endRefreshing()
    }
}

///下面就是常规的UITableView代理方法
extension HomeHotListChildViewController: UITableViewDelegate,
                                          UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return productList.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: NSStringFromClass(HomeProductCell.self), for: indexPath) as! HomeProductCell
        cell.selectionStyle = .none
        cell.updateCellWithModel(model: productList[indexPath.row])
        cell.clickLearnMoreBtnAction = { [self] in
            print("success Click")
            let vc = HomeProductDetailViewController(model: productList[indexPath.row])
            vc.hidesBottomBarWhenPushed = true
            
            self.navigationController?.pushViewController(vc, animated: true)
        }
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        if indexPath.row == productList.count - 1 {
            return 120.fit()
            
        } else {
            return 132.fit()
        }
    }
    
    ///记得加上ScrollView的回调 
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        self.scrollCallback?(scrollView)
    }
}
其他子控制器与此类似

效果展示:

在这里插入图片描述

该代码部分取自原先项目,以此记录以便后续查看,如有可以改进之处也希望各位大佬多多指出!希望大家多多点赞!
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淡酒交魂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值