需求背景:类似抖音小红书等个人中心文章发布、文章点赞、文章收藏等多子控制器功能,并且子控制器可左右滑动和下拉刷新
技术方案:JXPagingView使用方法详情(JXPagingListRefreshView子页面刷新)
寻找相关资料,发现github上JXPagingView可以实现该功能,以下详细介绍JXPagingListRefreshView使用方法
github: github.com/pujiaxin33/...
首先在podfile中引入相关库文件
swift
pod 'JXPagingView'
pod 'JXSegmentedView'
ps:JXSegmentedView是个分类切换滚动视图
github:github.com/pujiaxin33/...
父控制器相关代码:
swift
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 {}
子控制器相关代码:
swift
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)
}
}