소스 검색

首页调试

南鑫林 6 년 전
부모
커밋
fc2d09a6c7

BIN
.DS_Store


+ 45 - 5
RainbowPlanet/RainbowPlanet.xcodeproj/project.pbxproj

@@ -160,6 +160,13 @@
 		A73911B0229E4D970033177E /* PGYManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A73911AF229E4D970033177E /* PGYManager.swift */; };
 		A73911B3229ECE340033177E /* UICollectionViewLeftAlignedLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = A73911B1229ECE340033177E /* UICollectionViewLeftAlignedLayout.m */; };
 		A73911B6229EDAC80033177E /* ListTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = A73911B5229EDAC80033177E /* ListTransform.swift */; };
+		A7391218229F75F50033177E /* PagingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7391210229F75F50033177E /* PagingViewController.swift */; };
+		A7391219229F75F50033177E /* PagingListBaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7391211229F75F50033177E /* PagingListBaseView.swift */; };
+		A739121A229F75F50033177E /* JXPagingMainTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7391213229F75F50033177E /* JXPagingMainTableView.swift */; };
+		A739121B229F75F50033177E /* JXPagingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7391214229F75F50033177E /* JXPagingView.swift */; };
+		A739121C229F75F50033177E /* JXPagingListRefreshView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7391215229F75F50033177E /* JXPagingListRefreshView.swift */; };
+		A739121D229F75F50033177E /* JXPagingListContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7391216229F75F50033177E /* JXPagingListContainerView.swift */; };
+		A739121E229F75F50033177E /* PagingViewTableHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7391217229F75F50033177E /* PagingViewTableHeaderView.swift */; };
 		A73D7C682268A032002A4CE3 /* SwiftyStarRatingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A73D7C672268A032002A4CE3 /* SwiftyStarRatingView.swift */; };
 		A75414FD224B5F28002480B5 /* MobileLoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A75414FB224B5F28002480B5 /* MobileLoginViewController.swift */; };
 		A7541502224C5ECB002480B5 /* BaiduMapManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7541501224C5ECA002480B5 /* BaiduMapManager.swift */; };
@@ -226,7 +233,6 @@
 		A7A98E17227EED76005306E9 /* SpecialViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7A98E16227EED76005306E9 /* SpecialViewController.swift */; };
 		A7A98E1B227EEE49005306E9 /* SpecialView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7A98E1A227EEE49005306E9 /* SpecialView.swift */; };
 		A7A98E1D227EF1CB005306E9 /* SpecialBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7A98E1C227EF1CB005306E9 /* SpecialBannerView.swift */; };
-		A7A98E28227FD6C6005306E9 /* ShoppingMallListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7A98E27227FD6C6005306E9 /* ShoppingMallListViewController.swift */; };
 		A7A98E2D22801642005306E9 /* SwiftMoyaServiceCMSApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7A98E2C22801642005306E9 /* SwiftMoyaServiceCMSApi.swift */; };
 		A7A98E2F228017E2005306E9 /* SwiftMoyaNetWorkServiceCMS.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7A98E2E228017E2005306E9 /* SwiftMoyaNetWorkServiceCMS.swift */; };
 		A7A98E3122801B10005306E9 /* ShoppingMallListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7A98E3022801B10005306E9 /* ShoppingMallListView.swift */; };
@@ -551,6 +557,13 @@
 		A73911B1229ECE340033177E /* UICollectionViewLeftAlignedLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UICollectionViewLeftAlignedLayout.m; sourceTree = "<group>"; };
 		A73911B2229ECE340033177E /* UICollectionViewLeftAlignedLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UICollectionViewLeftAlignedLayout.h; sourceTree = "<group>"; };
 		A73911B5229EDAC80033177E /* ListTransform.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTransform.swift; sourceTree = "<group>"; };
+		A7391210229F75F50033177E /* PagingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagingViewController.swift; sourceTree = "<group>"; };
+		A7391211229F75F50033177E /* PagingListBaseView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagingListBaseView.swift; sourceTree = "<group>"; };
+		A7391213229F75F50033177E /* JXPagingMainTableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JXPagingMainTableView.swift; sourceTree = "<group>"; };
+		A7391214229F75F50033177E /* JXPagingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JXPagingView.swift; sourceTree = "<group>"; };
+		A7391215229F75F50033177E /* JXPagingListRefreshView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JXPagingListRefreshView.swift; sourceTree = "<group>"; };
+		A7391216229F75F50033177E /* JXPagingListContainerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JXPagingListContainerView.swift; sourceTree = "<group>"; };
+		A7391217229F75F50033177E /* PagingViewTableHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagingViewTableHeaderView.swift; sourceTree = "<group>"; };
 		A73D7C672268A032002A4CE3 /* SwiftyStarRatingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftyStarRatingView.swift; sourceTree = "<group>"; };
 		A75414FB224B5F28002480B5 /* MobileLoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MobileLoginViewController.swift; sourceTree = "<group>"; };
 		A7541501224C5ECA002480B5 /* BaiduMapManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaiduMapManager.swift; sourceTree = "<group>"; };
@@ -628,7 +641,6 @@
 		A7A98E16227EED76005306E9 /* SpecialViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpecialViewController.swift; sourceTree = "<group>"; };
 		A7A98E1A227EEE49005306E9 /* SpecialView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpecialView.swift; sourceTree = "<group>"; };
 		A7A98E1C227EF1CB005306E9 /* SpecialBannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpecialBannerView.swift; sourceTree = "<group>"; };
-		A7A98E27227FD6C6005306E9 /* ShoppingMallListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShoppingMallListViewController.swift; sourceTree = "<group>"; };
 		A7A98E2C22801642005306E9 /* SwiftMoyaServiceCMSApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftMoyaServiceCMSApi.swift; sourceTree = "<group>"; };
 		A7A98E2E228017E2005306E9 /* SwiftMoyaNetWorkServiceCMS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftMoyaNetWorkServiceCMS.swift; sourceTree = "<group>"; };
 		A7A98E3022801B10005306E9 /* ShoppingMallListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShoppingMallListView.swift; sourceTree = "<group>"; };
@@ -1743,6 +1755,27 @@
 			path = ListTransform;
 			sourceTree = "<group>";
 		};
+		A739120F229F75F50033177E /* Personal */ = {
+			isa = PBXGroup;
+			children = (
+				A7391210229F75F50033177E /* PagingViewController.swift */,
+				A7391211229F75F50033177E /* PagingListBaseView.swift */,
+				A7391217229F75F50033177E /* PagingViewTableHeaderView.swift */,
+			);
+			path = Personal;
+			sourceTree = "<group>";
+		};
+		A7391212229F75F50033177E /* JXPagingView-Swift */ = {
+			isa = PBXGroup;
+			children = (
+				A7391213229F75F50033177E /* JXPagingMainTableView.swift */,
+				A7391214229F75F50033177E /* JXPagingView.swift */,
+				A7391215229F75F50033177E /* JXPagingListRefreshView.swift */,
+				A7391216229F75F50033177E /* JXPagingListContainerView.swift */,
+			);
+			path = "JXPagingView-Swift";
+			sourceTree = "<group>";
+		};
 		A73D7C662268A032002A4CE3 /* SwiftyStarRatingView */ = {
 			isa = PBXGroup;
 			children = (
@@ -1830,7 +1863,6 @@
 				A775CBFD2237493600EBDCF8 /* ShoppingMallNavigationBarView.swift */,
 				A775CBFF223774A300EBDCF8 /* ShoppingMallView.swift */,
 				A7A98E3022801B10005306E9 /* ShoppingMallListView.swift */,
-				BD09C84022955B480080D5A4 /* PopTopTriangleView.swift */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -2078,6 +2110,7 @@
 		A77F2CA32232010F001BD3F6 /* ShoppingMallModule */ = {
 			isa = PBXGroup;
 			children = (
+				A739120F229F75F50033177E /* Personal */,
 				A77F2CA42232010F001BD3F6 /* ShoppingMall */,
 				A7FF1550228AC22700A85748 /* ProductAllComment */,
 				A70B2C122286B14C00B2449F /* ProductView */,
@@ -2102,7 +2135,6 @@
 			isa = PBXGroup;
 			children = (
 				A77F2CA72232010F001BD3F6 /* ShoppingMallViewController.swift */,
-				A7A98E27227FD6C6005306E9 /* ShoppingMallListViewController.swift */,
 			);
 			path = ViewController;
 			sourceTree = "<group>";
@@ -2197,6 +2229,7 @@
 		A77F2CBC2232022A001BD3F6 /* Tools */ = {
 			isa = PBXGroup;
 			children = (
+				A7391212229F75F50033177E /* JXPagingView-Swift */,
 				A73911B4229EDABB0033177E /* ListTransform */,
 				A7146346228EFCE20066099B /* SKUDataFilter */,
 				A7274C51228EE635000E3A07 /* SwiftScan */,
@@ -2382,6 +2415,7 @@
 		A7A98E38228030F8005306E9 /* ShoppingMallCategory */ = {
 			isa = PBXGroup;
 			children = (
+				BD09C84022955B480080D5A4 /* PopTopTriangleView.swift */,
 				A7A98E392280312C005306E9 /* ShoppingMallCategoryTableViewCell.swift */,
 				A7A98E3B228036D7005306E9 /* ShoppingMallCategoryCollectionViewCell.swift */,
 			);
@@ -3395,6 +3429,7 @@
 				A7B4E738228191CC0012914A /* CommondModel.swift in Sources */,
 				BD7AB841228438C80030646A /* OrderPaySelfPickAddressCell.swift in Sources */,
 				BDF862AC228E5112000DEF84 /* OrderCommentAddImgCollectionCell.swift in Sources */,
+				A7391219229F75F50033177E /* PagingListBaseView.swift in Sources */,
 				A7CC74D4226FF1AA003C4F38 /* MineView.swift in Sources */,
 				A71AA5152272160A008FF1A5 /* ExpressAddressListTableViewCell.swift in Sources */,
 				A72A72B722321DE000B21995 /* Extension+NSMutableAttributedString.swift in Sources */,
@@ -3423,6 +3458,7 @@
 				A7FF159C228D9E3D00A85748 /* OrderRefundDetailModel.swift in Sources */,
 				A7C3DD1C226422D200FA262E /* SwiftMoyaNetWorkServiceSMS.swift in Sources */,
 				BDF862A2228E41CC000DEF84 /* OrderLogisticsInfoCell.swift in Sources */,
+				A739121D229F75F50033177E /* JXPagingListContainerView.swift in Sources */,
 				A72A7386223396CB00B21995 /* SwiftMoyaNetWorkManager.swift in Sources */,
 				A70B2C252286C03800B2449F /* NXLPageControl.swift in Sources */,
 				A7A98E12227ECA11005306E9 /* ProductSearchModel.swift in Sources */,
@@ -3553,13 +3589,13 @@
 				A70B842E228F97EC00882BC5 /* ProcuctDetailSelectSkuTableViewCell.swift in Sources */,
 				A72A72AE22321DE000B21995 /* CountdownButton.swift in Sources */,
 				A71738AD228AB7B2000AEA6A /* ProductCommentListModel.swift in Sources */,
-				A7A98E28227FD6C6005306E9 /* ShoppingMallListViewController.swift in Sources */,
 				A7B4E71F228131720012914A /* ProductSlidingLeftRightCollectionViewCell.swift in Sources */,
 				A77F2CB72232010F001BD3F6 /* MineViewController.swift in Sources */,
 				A7778CA92244904500C7C47A /* Extension+Gifu.GIFImageView.swift in Sources */,
 				A71738AB22898660000AEA6A /* ShopModel.swift in Sources */,
 				A7FF1557228AC3E800A85748 /* ProductAllCommentViewController.swift in Sources */,
 				A7A98E02227E8900005306E9 /* ProductSearchListModel.swift in Sources */,
+				A739121E229F75F50033177E /* PagingViewTableHeaderView.swift in Sources */,
 				A7A98E17227EED76005306E9 /* SpecialViewController.swift in Sources */,
 				A7778CB32244D73400C7C47A /* RegisterLoginViewController.swift in Sources */,
 				BD7AB8432284390B0030646A /* OrderPaySelfPickInfoCell.swift in Sources */,
@@ -3575,6 +3611,7 @@
 				A7636AC822682BAF00374F9E /* LocationView.swift in Sources */,
 				A738D205225AF90D00EEE860 /* WeChatpayOrderModel.swift in Sources */,
 				A7274C5C228EE636000E3A07 /* LBXScanLineAnimation.swift in Sources */,
+				A739121A229F75F50033177E /* JXPagingMainTableView.swift in Sources */,
 				A7CC7524227190FB003C4F38 /* AccountSecurityView.swift in Sources */,
 				BD1DC6CB228D157000B89C57 /* OrderCreateBackModel.swift in Sources */,
 				A72A72BD22321DE000B21995 /* Extension+UIColor.swift in Sources */,
@@ -3628,6 +3665,7 @@
 				A7A98E1B227EEE49005306E9 /* SpecialView.swift in Sources */,
 				BDF47D7A228271F600941AB9 /* ShoppingCartView.swift in Sources */,
 				A7824AFB2271EA2600ABA381 /* SelfMentionContactsListView.swift in Sources */,
+				A7391218229F75F50033177E /* PagingViewController.swift in Sources */,
 				A72A72AB22321DE000B21995 /* SwiftProgressHUD.swift in Sources */,
 				BDF862B1228E6690000DEF84 /* OrderApplyRefundProductCell.swift in Sources */,
 				A7CC751C22716426003C4F38 /* SetLogoutTableViewCell.swift in Sources */,
@@ -3658,6 +3696,7 @@
 				A72A726722321DBD00B21995 /* LocationModel.swift in Sources */,
 				A7A98E10227EC531005306E9 /* ProductHSmallTableViewCell.swift in Sources */,
 				A7A98DFD227E84F4005306E9 /* SwiftMoyaServiceProductApi.swift in Sources */,
+				A739121B229F75F50033177E /* JXPagingView.swift in Sources */,
 				BD7AB8452284398A0030646A /* OrderPaySelfPickAddInfoCell.swift in Sources */,
 				A72A72D222321E2700B21995 /* Common.swift in Sources */,
 				A70B2C64228875DE00B2449F /* ShopViewShopInfoTableViewCell.swift in Sources */,
@@ -3669,6 +3708,7 @@
 				BD7AB838228420310030646A /* ShoppingCartPayOrderHeader.swift in Sources */,
 				A7824B002271F0DD00ABA381 /* EditSelfMentionContactsViewController.swift in Sources */,
 				A7CC751F227190C5003C4F38 /* AccountSecurityViewController.swift in Sources */,
+				A739121C229F75F50033177E /* JXPagingListRefreshView.swift in Sources */,
 				BD29A92E228F99780018CFC3 /* OrderCommentParameterModel.swift in Sources */,
 				A7284440224DFACD00F82F30 /* InfoModel.swift in Sources */,
 				A72A72B522321DE000B21995 /* Extension+UITextView.swift in Sources */,

+ 87 - 0
RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/Personal/PagingListBaseView.swift

@@ -0,0 +1,87 @@
+//
+//  PagingListBaseView.swift
+//  JXPagingView
+//
+//  Created by jiaxin on 2018/5/28.
+//  Copyright © 2018年 jiaxin. All rights reserved.
+//
+
+import UIKit
+
+@objc public class PagingListBaseView: UIView {
+    @objc public var tableView: UITableView!
+    @objc public var dataSource: [String]?
+    var listViewDidScrollCallback: ((UIScrollView) -> ())?
+    private var isHeaderRefreshed: Bool = false
+    deinit {
+        listViewDidScrollCallback = nil
+    }
+
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+
+        tableView = UITableView(frame: frame, style: .plain)
+        tableView.backgroundColor = UIColor.white
+        tableView.tableFooterView = UIView()
+        tableView.dataSource = self
+        tableView.delegate = self
+        tableView.register(UITableViewCell.classForCoder(), forCellReuseIdentifier: "cell")
+        addSubview(tableView)
+    }
+
+    func beginFirstRefresh() {
+        if !isHeaderRefreshed {
+            self.isHeaderRefreshed = true
+            self.tableView.reloadData()
+        }
+    }
+
+
+    required public init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    override public func layoutSubviews() {
+        super.layoutSubviews()
+
+        tableView.frame = self.bounds
+    }
+
+}
+
+extension PagingListBaseView: UITableViewDataSource, UITableViewDelegate {
+    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        if isHeaderRefreshed {
+            return dataSource?.count ?? 0
+        }
+        return 0
+    }
+
+    public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
+        cell.textLabel?.text = dataSource?[indexPath.row]
+        return cell
+    }
+
+    public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
+        return 50
+    }
+
+    public func scrollViewDidScroll(_ scrollView: UIScrollView) {
+        self.listViewDidScrollCallback?(scrollView)
+    }
+}
+
+extension PagingListBaseView: JXPagingViewListViewDelegate {
+    public func listView() -> UIView {
+        return self
+    }
+    
+    public func listViewDidScrollCallback(callback: @escaping (UIScrollView) -> ()) {
+        self.listViewDidScrollCallback = callback
+    }
+
+    public func listScrollView() -> UIScrollView {
+        return self.tableView
+    }
+}

+ 118 - 0
RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/Personal/PagingViewController.swift

@@ -0,0 +1,118 @@
+//
+//  PagingViewController.swift
+//  JXPagingView
+//
+//  Created by jiaxin on 2018/8/10.
+//  Copyright © 2018年 jiaxin. All rights reserved.
+//
+
+import UIKit
+import JXSegmentedView
+
+class PagingViewController: UIViewController {
+    var pagingView: JXPagingView!
+    var userHeaderView: PagingViewTableHeaderView!
+    var userHeaderContainerView: UIView!
+    var segmentedViewDataSource: JXSegmentedTitleDataSource!
+    var segmentedView: JXSegmentedView!
+    var titles = ["能力", "爱好", "队友"]
+    var JXTableHeaderViewHeight: Int = 0
+    var JXheightForHeaderInSection: Int = 50
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+
+        self.title = "个人中心"
+        self.navigationController?.navigationBar.isTranslucent = false
+
+        userHeaderContainerView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: CGFloat(JXTableHeaderViewHeight)))
+        userHeaderView = PagingViewTableHeaderView(frame: userHeaderContainerView.bounds)
+        userHeaderContainerView.addSubview(userHeaderView)
+
+        //segmentedViewDataSource一定要通过属性强持有!!!!!!!!!
+        segmentedViewDataSource = JXSegmentedTitleDataSource()
+        segmentedViewDataSource.titles = titles
+        segmentedViewDataSource.titleSelectedColor = UIColor(red: 105/255, green: 144/255, blue: 239/255, alpha: 1)
+        segmentedViewDataSource.titleNormalColor = UIColor.black
+        segmentedViewDataSource.isTitleColorGradientEnabled = true
+        segmentedViewDataSource.isTitleZoomEnabled = true
+        segmentedViewDataSource.reloadData(selectedIndex: 0)
+
+        segmentedView = JXSegmentedView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: CGFloat(JXheightForHeaderInSection)))
+        segmentedView.backgroundColor = UIColor.white
+        segmentedView.dataSource = segmentedViewDataSource
+        segmentedView.isContentScrollViewClickTransitionAnimationEnabled = false
+
+        let lineView = JXSegmentedIndicatorLineView()
+        lineView.indicatorColor = UIColor(red: 105/255, green: 144/255, blue: 239/255, alpha: 1)
+        lineView.indicatorWidth = 30
+        segmentedView.indicators = [lineView]
+
+        let lineWidth = 1/UIScreen.main.scale
+        let lineLayer = CALayer()
+        lineLayer.backgroundColor = UIColor.lightGray.cgColor
+        lineLayer.frame = CGRect(x: 0, y: segmentedView.bounds.height - lineWidth, width: segmentedView.bounds.width, height: lineWidth)
+        segmentedView.layer.addSublayer(lineLayer)
+
+        pagingView = JXPagingView(delegate: self)
+        pagingView.mainTableView.addHeaderWithHeader(withBeginRefresh: true, animation: false) { (page) in
+            self.segmentedViewDataSource.reloadData(selectedIndex: 1)
+            
+            self.segmentedView.defaultSelectedIndex = 1
+            self.segmentedView.reloadData()
+    
+            self.pagingView.listContainerView.reloadData()
+            self.pagingView.reloadData()
+        }
+
+        self.view.addSubview(pagingView)        
+        segmentedView.contentScrollView = pagingView.listContainerView.collectionView
+    }
+
+    override func viewDidLayoutSubviews() {
+        super.viewDidLayoutSubviews()
+
+        pagingView.frame = self.view.bounds
+    }
+}
+
+extension PagingViewController: JXPagingViewDelegate {
+
+    func tableHeaderViewHeight(in pagingView: JXPagingView) -> Int {
+        return JXTableHeaderViewHeight
+    }
+
+    func tableHeaderView(in pagingView: JXPagingView) -> UIView {
+        return userHeaderContainerView
+    }
+
+    func heightForPinSectionHeader(in pagingView: JXPagingView) -> Int {
+        return JXheightForHeaderInSection
+    }
+
+    func viewForPinSectionHeader(in pagingView: JXPagingView) -> UIView {
+        return segmentedView
+    }
+
+    func numberOfLists(in pagingView: JXPagingView) -> Int {
+        return titles.count
+    }
+
+    func pagingView(_ pagingView: JXPagingView, initListAtIndex index: Int) -> JXPagingViewListViewDelegate {
+        let list = PagingListBaseView()
+        if index == 0 {
+            list.dataSource = ["橡胶火箭", "橡胶火箭炮", "橡胶机关枪", "橡胶子弹", "橡胶攻城炮", "橡胶象枪", "橡胶象枪乱打", "橡胶灰熊铳", "橡胶雷神象枪", "橡胶猿王枪", "橡胶犀·榴弹炮", "橡胶大蛇炮", "橡胶火箭", "橡胶火箭炮", "橡胶机关枪", "橡胶子弹", "橡胶攻城炮", "橡胶象枪", "橡胶象枪乱打", "橡胶灰熊铳", "橡胶雷神象枪", "橡胶猿王枪", "橡胶犀·榴弹炮", "橡胶大蛇炮"]
+        }else if index == 1 {
+            list.dataSource = ["吃烤肉", "吃鸡腿肉", "吃牛肉", "各种肉"]
+        }else {
+            list.dataSource = ["【剑士】罗罗诺亚·索隆", "【航海士】娜美", "【狙击手】乌索普", "【厨师】香吉士", "【船医】托尼托尼·乔巴", "【船匠】 弗兰奇", "【音乐家】布鲁克", "【考古学家】妮可·罗宾"]
+        }
+        list.beginFirstRefresh()
+        return list
+    }
+
+//    func mainTableViewDidScroll(_ scrollView: UIScrollView) {
+//        userHeaderView?.scrollViewDidScroll(contentOffsetY: scrollView.contentOffset.y)
+//    }
+}
+

+ 45 - 0
RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/Personal/PagingViewTableHeaderView.swift

@@ -0,0 +1,45 @@
+//
+//  PagingViewTableHeaderView.swift
+//  JXPagingView
+//
+//  Created by jiaxin on 2018/5/28.
+//  Copyright © 2018年 jiaxin. All rights reserved.
+//
+
+import UIKit
+
+class PagingViewTableHeaderView: UIView {
+    var imageView: UIImageView!
+    var imageViewFrame: CGRect!
+
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+
+        imageView = UIImageView(image: UIImage(named: "lufei.jpg"))
+        imageView.clipsToBounds = true
+        imageView.contentMode = .scaleAspectFill
+        imageView.frame = CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height)
+        self.addSubview(imageView)
+
+        imageViewFrame = imageView.frame
+
+//        let label = UILabel(frame: CGRect(x: 10, y: frame.size.height - 30, width: 200, height: 30))
+//        label.font = UIFont.systemFont(ofSize: 20)
+//        label.text = "Monkey·D·路飞"
+//        label.textColor = UIColor.red
+//        label.autoresizingMask = AutoresizingMask(rawValue: AutoresizingMask.flexibleRightMargin.rawValue | AutoresizingMask.flexibleTopMargin.rawValue)
+//        self.addSubview(label)
+    }
+
+    func scrollViewDidScroll(contentOffsetY: CGFloat) {
+        var frame = imageViewFrame!
+        frame.size.height -= contentOffsetY
+        frame.origin.y = contentOffsetY
+        imageView.frame = frame
+    }
+
+    required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+}

RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/ShoppingMall/View/PopTopTriangleView.swift → RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/ShoppingMall/View/ShoppingMallCategory/PopTopTriangleView.swift


+ 81 - 6
RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/ShoppingMall/View/ShoppingMallListView.swift

@@ -10,15 +10,74 @@ import UIKit
 
 class ShoppingMallListView: BaseView {
     
-    var cmsSectionModels : Array<CMSContentModel>? {
+    var listViewDidScrollCallback: ((UIScrollView) -> ())?
+    deinit {
+        listViewDidScrollCallback = nil
+    }
+    
+    var shoppingMallListVCType : Int = 0 {
         didSet {
-            tableView.reloadData()
+            cmsTemplateSetPreviewApi()
         }
     }
+
     
-    var productModelsArrays : Array<[ProductModel]>? {
-        didSet {
-            tableView.reloadData()
+    var cmsSectionModels : Array<CMSContentModel>?
+    var productModelsArrays : Array<[ProductModel]>?
+    
+    /// 获取首页数据
+    func cmsTemplateSetPreviewApi() {
+        SwiftMoyaNetWorkServiceCMS.shared().cmsTemplateSetPreviewApi(type: shoppingMallListVCType) {
+            [weak self] (cmsModel) -> (Void) in
+            let cmsModel = cmsModel as! CMSModel
+            self?.cmsSectionModels = cmsModel.content
+            self?.tableView.reloadData()
+            DispatchQueue.global(qos: .default).async {
+                self?.productHomeProductApi(cmsModel: cmsModel)
+            }
+        }
+    }
+    
+    
+    /// 获取商品列表
+    func productHomeProductApi(cmsModel:CMSModel?) {
+        
+        if let model = cmsModel {
+            if !(model.content?.isEmpty ?? true) {
+                for cmsSectionModel in model.content! {
+                    if  cmsSectionModel.areaType == "floor" {
+                        
+                        if !(cmsSectionModel.rule?.isEmpty ?? true) {
+                            var productModelsArray = Array<[ProductModel]>.init(repeating: [], count: cmsSectionModel.rule!.count)
+                            for  (index, cmsRuleModel) in cmsSectionModel.rule!.enumerated()  {
+                                
+                                
+                                let sema = DispatchSemaphore(value: 0)
+                                SwiftMoyaNetWorkServiceProduct.shared().productHomeProductApi(ids: cmsRuleModel.productId ?? "", completion: {[weak self] (productModels) -> (Void) in
+                                    if productModels is String {
+                                        NXLLog("signal\(index)")
+                                        sema.signal()
+                                    }else {
+                                        productModelsArray[index] = productModels as! [ProductModel]
+                                        self?.productModelsArrays = productModelsArray
+                                        NXLLog("signal\(index)")
+                                        sema.signal()
+                                    }
+                                    
+                                })
+                                //异步调用返回前,就会一直阻塞在这
+                                sema.wait()
+                                NXLLog("wait\(index)")
+                                
+                            }
+                            DispatchQueue.main.async {
+                                [weak self] in
+                                self?.tableView.reloadData()
+                            }
+                        }
+                    }
+                }
+            }
         }
     }
     
@@ -134,6 +193,22 @@ extension ShoppingMallListView : UITableViewDelegate, UITableViewDataSource {
         return nil
     }
     
+    public func scrollViewDidScroll(_ scrollView: UIScrollView) {
+        self.listViewDidScrollCallback?(scrollView)
+    }
+    
 }
 
-
+extension ShoppingMallListView: JXPagingViewListViewDelegate {
+    public func listView() -> UIView {
+        return self
+    }
+    
+    public func listViewDidScrollCallback(callback: @escaping (UIScrollView) -> ()) {
+        self.listViewDidScrollCallback = callback
+    }
+    
+    public func listScrollView() -> UIScrollView {
+        return self.tableView
+    }
+}

+ 123 - 52
RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/ShoppingMall/View/ShoppingMallView.swift

@@ -8,28 +8,91 @@
 
 import UIKit
 import JXSegmentedView
+import RxSwift
 
-class ShoppingMallView: BaseView {
+class ShoppingMallView: UIView {
     
-    var cmsTemplateTitles = Array<String>()
+    let disposeBag = DisposeBag()
+    
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        self.cmsTemplateSetTemplateNameApi()
+    }
+    required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
     
+    var JXTableHeaderViewHeight: Int = 0
+    var JXheightForHeaderInSection: Int = 44
+    var cmsTemplateTitles = Array<String>()
+    var shoppingMallListVCType : Int = 0
+
     var cmsTemplateModels : Array<CMSTemplateModel>? {
         didSet {
             guard cmsTemplateModels?.isEmpty ?? true else {
+                cmsTemplateTitles.removeAll()
                 for cmsTemplateModel in cmsTemplateModels! {
                     cmsTemplateTitles.append(cmsTemplateModel.title!)
                 }
-                setupView()
-                setupLayout()
+                addHeader()
                 return
             }
+            addHeader()
             return
         }
     }
     
+    
+    /// 添加View
+    func addHeader() {
+        setupView()
+        isShowEmpty()
+        pagingView.mainTableView.addHeaderWithHeader(withBeginRefresh: false, animation: false) { [weak self] (page) in
+            self?.cmsTemplateSetTemplateNameApi()
+        }
+    }
+    
+    /// 缺省页面
+    private func isShowEmpty() {
+        segmentedView.contentScrollView!.ly_emptyView = emptyView
+        if cmsTemplateTitles.isEmpty {
+            segmentedView.contentScrollView!.ly_showEmpty()
+        }else {
+            segmentedView.contentScrollView!.ly_hideEmpty()
+            self.reloadData()
+        }
+    }
+    /// 刷新页面
+    func reloadData() {
+        segmentedDataSource.titles = cmsTemplateTitles
+        segmentedView.indicators = [indicator]
+        if cmsTemplateTitles.count == 1 {
+            JXheightForHeaderInSection = 0
+        }else {
+            JXheightForHeaderInSection = 44
+        }
+        self.segmentedDataSource.reloadData(selectedIndex: shoppingMallListVCType)
+        self.segmentedView.defaultSelectedIndex = shoppingMallListVCType
+        self.segmentedView.reloadData()
+        self.pagingView.reloadData()
+    }
+    /// 请求模板
+    private func cmsTemplateSetTemplateNameApi() {
+        SwiftMoyaNetWorkServiceCMS.shared().cmsTemplateSetTemplateNameApi(completion: {
+            [weak self] (cmsTemplateModels) -> (Void) in
+            let cmsTemplateModels = cmsTemplateModels as! Array<CMSTemplateModel>
+            if !cmsTemplateModels.isEmpty {
+                if cmsTemplateModels.count < self?.cmsTemplateModels?.count ?? 0 {
+                    self?.shoppingMallListVCType = cmsTemplateModels.count - 1
+                }
+            }
+            self?.cmsTemplateModels = cmsTemplateModels
+        })
+    }
+    
     func setupView() {
-        addSubview(segmentedView)
-        addSubview(listContainerView)
+        addSubview(pagingView)
+        segmentedView.contentScrollView = pagingView.listContainerView.collectionView
         
         let deliverType = DeliveryMethodTypeModel.shared().getModel()?.deliveryMethodType
         if deliverType == "1" {
@@ -46,25 +109,6 @@ class ShoppingMallView: BaseView {
             }
         }                
     }
-
-    func setupLayout() {
-        segmentedView.snp.makeConstraints { (make) in
-            make.top.left.right.equalToSuperview()
-            if segmentedDataSource.titles.count > 1 {
-                 make.height.equalTo(44)
-            }else {
-                make.height.equalTo(0)
-            }
-        }
-        listContainerView.snp.makeConstraints { (make) in
-            if segmentedDataSource.titles.count > 1 {
-                make.top.equalTo(segmentedView.snp.bottom)
-            }else {
-                make.top.equalToSuperview()
-            }
-            make.left.right.bottom.equalToSuperview()
-        }
-    }
     
     //初始化自提地址提示View
     lazy var selfAddressPopView: PopTopTriangleView = {
@@ -76,18 +120,16 @@ class ShoppingMallView: BaseView {
     
     //1.初始化JXSegmentedView
     lazy var segmentedView: JXSegmentedView = {
-        let segmentedView = JXSegmentedView()
+        let segmentedView = JXSegmentedView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: CGFloat(JXheightForHeaderInSection)))
         segmentedView.delegate = self
         segmentedView.dataSource = segmentedDataSource
-        segmentedView.indicators = [indicator]
-        segmentedView.contentScrollView = listContainerView.scrollView
+        segmentedView.contentScrollView = pagingView.listContainerView.collectionView
         return segmentedView
     }()
     
     //2.初始化dataSource
     lazy var segmentedDataSource: JXSegmentedTitleDataSource = {
         let segmentedDataSource = JXSegmentedTitleDataSource()
-        segmentedDataSource.titles = cmsTemplateTitles
         segmentedDataSource.isTitleColorGradientEnabled = true
         segmentedDataSource.isItemSpacingAverageEnabled = true
         segmentedDataSource.titleNormalColor = k333333Color
@@ -108,11 +150,32 @@ class ShoppingMallView: BaseView {
         return indicator
     }()
     
-    //4.初始化JXSegmentedListContainerView
-    lazy var listContainerView: JXSegmentedListContainerView = {
-        let listContainerView = JXSegmentedListContainerView(dataSource: self)
-        listContainerView.didAppearPercent = 0.01
-        return listContainerView
+    //4.pagingView
+    lazy var pagingView: JXPagingView = {
+        let pagingView = JXPagingView(delegate: self)
+        pagingView.frame = self.bounds
+        return pagingView
+    }()
+    
+    
+    /// 5.头部headerView
+    lazy var headerView: UIView = {
+        var headerView = UIView()
+        return headerView
+    }()
+    
+    /// 6.包含头部
+    lazy var headerContainerView: UIView = {
+        var headerContainerView =  UIView()
+        headerContainerView.addSubview(headerView)
+        return headerContainerView
+    }()
+    
+    /// 7.加载空白图
+    lazy var emptyView: LYEmptyView = {
+        let emptyView =  EmptyView.shared.diyCustomEmptyViewStyle2(iconStr: "page04", titleStr: "当前暂无数据,请下拉刷新")
+        emptyView.contentViewY = kScaleValue(value: 182)
+        return emptyView
     }()
     
 }
@@ -120,24 +183,19 @@ class ShoppingMallView: BaseView {
 extension ShoppingMallView : JXSegmentedViewDelegate {
     //点击选中或者滚动选中都会调用该方法。适用于只关心选中事件,而不关心具体是点击还是滚动选中的情况。
     func segmentedView(_ segmentedView: JXSegmentedView, didSelectedItemAt index: Int) {
-       
+        self.shoppingMallListVCType = index
     }
     
     // 点击选中的情况才会调用该方法
     func segmentedView(_ segmentedView: JXSegmentedView, didClickSelectedItemAt index: Int) {
-        //传递didClickSelectedItemAt事件给listContainerView,必须调用!!!
-        listContainerView.didClickSelectedItem(at: index)
     }
     
     // 滚动选中的情况才会调用该方法
     func segmentedView(_ segmentedView: JXSegmentedView, didScrollSelectedItemAt index: Int) {
-        
     }
     
     // 正在滚动中的回调
     func segmentedView(_ segmentedView: JXSegmentedView, scrollingFrom leftIndex: Int, to rightIndex: Int, percent: CGFloat) {
-        //传递scrolling事件给listContainerView,必须调用!!!
-        listContainerView.segmentedViewScrolling(from: leftIndex, to: rightIndex, percent: percent, selectedIndex: segmentedView.selectedIndex)
     }
     
     /// 是否允许点击选中目标index的item
@@ -146,19 +204,32 @@ extension ShoppingMallView : JXSegmentedViewDelegate {
     }
 }
 
-extension ShoppingMallView :JXSegmentedListContainerViewDataSource {
-
+extension ShoppingMallView: JXPagingViewDelegate {
     
-    func numberOfLists(in listContainerView: JXSegmentedListContainerView) -> Int {
-        if let titleDataSource = segmentedView.dataSource as? JXSegmentedBaseDataSource {
-            return titleDataSource.dataSource.count
-        }
-        return 0
+    func tableHeaderViewHeight(in pagingView: JXPagingView) -> Int {
+        return JXTableHeaderViewHeight
+    }
+    
+    func tableHeaderView(in pagingView: JXPagingView) -> UIView {
+        return headerContainerView
+    }
+    
+    func heightForPinSectionHeader(in pagingView: JXPagingView) -> Int {
+        return JXheightForHeaderInSection
     }
-    func listContainerView(_ listContainerView: JXSegmentedListContainerView, initListAt index: Int) -> JXSegmentedListContainerViewListDelegate {
-        let vc = ShoppingMallListViewController()
-        let cmsTemplateModel = cmsTemplateModels![index]
-        vc.shoppingMallListVCType = cmsTemplateModel.applyType ?? 0
-        return vc
+    
+    func viewForPinSectionHeader(in pagingView: JXPagingView) -> UIView {
+        return segmentedView
+    }
+    
+    func numberOfLists(in pagingView: JXPagingView) -> Int {
+        return cmsTemplateTitles.count
+    }
+    
+    func pagingView(_ pagingView: JXPagingView, initListAtIndex index: Int) -> JXPagingViewListViewDelegate {
+        let list = ShoppingMallListView()
+        list.shoppingMallListVCType = index
+        self.shoppingMallListVCType = index
+        return list
     }
 }

+ 0 - 110
RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/ShoppingMall/ViewController/ShoppingMallListViewController.swift

@@ -1,110 +0,0 @@
-//
-//  ShoppingMallListViewController.swift
-//  RainbowPlanet
-//
-//  Created by 南鑫林 on 2019/5/6.
-//  Copyright © 2019 南鑫林. All rights reserved.
-//
-
-import UIKit
-import JXSegmentedView
-
-class ShoppingMallListViewController: UIViewController {
-    
-    var shoppingMallListVCType : Int = 0
-    
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        setupView()
-        setupLayouts()
-        setupdata()
-    }
-    
-    func setupdata() {
-        shoppingMallListView.tableView
-            .addHeaderWithHeader(withBeginRefresh: true, animation: false) {
-                [weak self] (page) in
-            self?.cmsTemplateSetPreviewApi()
-        }
-    }
-    func setupView() {
-        view.backgroundColor = kf7f8faColor
-        view.addSubview(shoppingMallListView)
-    }
-    
-    func setupLayouts() {
-        shoppingMallListView.snp.makeConstraints { (make) in
-            make.edges.equalToSuperview()
-        }
-    }
-    
-    lazy var shoppingMallListView: ShoppingMallListView = {
-        let shoppingMallListView = ShoppingMallListView()
-        return shoppingMallListView
-    }()
-    
-    
-    /// 获取首页数据
-    func cmsTemplateSetPreviewApi() {
-        SwiftMoyaNetWorkServiceCMS.shared().cmsTemplateSetPreviewApi(type: shoppingMallListVCType) {
-            [weak self] (cmsModel) -> (Void) in
-            let cmsModel = cmsModel as! CMSModel
-            self?.shoppingMallListView.cmsSectionModels = cmsModel.content
-            
-            DispatchQueue.global(qos: .default).async {
-                self?.productHomeProductApi(cmsModel: cmsModel)
-            }
-        
-        }
-    }
-    
-    var productModelsArrays = Array<[ProductModel]>()
-    
-    /// 获取商品列表
-    func productHomeProductApi(cmsModel:CMSModel?) {
-
-        if let model = cmsModel {
-            if !(model.content?.isEmpty ?? true) {
-                for cmsSectionModel in model.content! {
-                    if  cmsSectionModel.areaType == "floor" {
-
-                        if !(cmsSectionModel.rule?.isEmpty ?? true) {
-                            var productModelsArray = Array<[ProductModel]>.init(repeating: [], count: cmsSectionModel.rule!.count)
-                            for  (index, cmsRuleModel) in cmsSectionModel.rule!.enumerated()  {
-                                
-
-                                    let sema = DispatchSemaphore(value: 0)
-                                    SwiftMoyaNetWorkServiceProduct.shared().productHomeProductApi(ids: cmsRuleModel.productId ?? "", completion: {[weak self] (productModels) -> (Void) in
-                                        if productModels is String {
-                                            NXLLog("signal\(index)")
-                                            sema.signal()
-                                        }else {
-                                            productModelsArray[index] = productModels as! [ProductModel]
-                                            self?.productModelsArrays = productModelsArray
-                                            NXLLog("signal\(index)")
-                                            sema.signal()
-                                        }
-                                        
-                                    })
-                                    //异步调用返回前,就会一直阻塞在这
-                                    sema.wait()
-                                    NXLLog("wait\(index)")
-                                
-                                }
-                            DispatchQueue.main.async {
-                                self.shoppingMallListView.productModelsArrays = self.productModelsArrays
-                            }
-
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
-
-extension ShoppingMallListViewController : JXSegmentedListContainerViewListDelegate {
-    func listView() -> UIView {
-        return view
-    }
-}

+ 6 - 18
RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/ShoppingMall/ViewController/ShoppingMallViewController.swift

@@ -26,6 +26,8 @@ class ShoppingMallViewController: BaseViewController {
     override func setupViews() {
         super.setupViews()
         navigationBar.addSubview(navigationBarView)
+        view.addSubview(shoppingMallView)
+
     }
 
     override func setupLayouts() {
@@ -33,6 +35,10 @@ class ShoppingMallViewController: BaseViewController {
             make.top.equalToSuperview().offset(kSafeStatusBarHeight)
             make.left.right.bottom.equalToSuperview()
         }
+        shoppingMallView.snp.makeConstraints { (make) in
+            make.bottom.left.right.equalToSuperview()
+            make.top.equalTo(kNavBarTotalHeight)
+        }
     }
     
     override func setupData() {
@@ -77,9 +83,6 @@ class ShoppingMallViewController: BaseViewController {
             vc.navigationBar.title = "团购分类"
             self?.navigationController?.pushViewController(vc, animated: true)
         }).disposed(by: disposeBag)
-        
-        /// 请求模板
-        self.cmsTemplateSetTemplateNameApi()
     }
     
     func pushVCCMSRule(cmsRuleModel:CMSRuleModel?,areaType:String) {
@@ -103,27 +106,12 @@ class ShoppingMallViewController: BaseViewController {
 
     private lazy var navigationBarView: ShoppingMallNavigationBarView = {
         let navigationBarView = ShoppingMallNavigationBarView()
-        
         return navigationBarView
     }()
 
     private lazy var shoppingMallView: ShoppingMallView = {
         let shoppingMallView = ShoppingMallView()
-        view.addSubview(shoppingMallView)
         return shoppingMallView
     }()
-    
-    /// 请求模板
-     private func cmsTemplateSetTemplateNameApi() {
-        SwiftMoyaNetWorkServiceCMS.shared().cmsTemplateSetTemplateNameApi(completion: {
-            [weak self] (cmsTemplateModels) -> (Void) in
-            let cmsTemplateModels = cmsTemplateModels as! Array<CMSTemplateModel>
-            self?.shoppingMallView.snp.makeConstraints { (make) in
-                make.bottom.left.right.equalToSuperview()
-                make.top.equalTo(kNavBarTotalHeight)
-            }
-            self?.shoppingMallView.cmsTemplateModels = cmsTemplateModels
-        })
-    }
 }
 

+ 181 - 0
RainbowPlanet/RainbowPlanet/Tools/JXPagingView-Swift/JXPagingListContainerView.swift

@@ -0,0 +1,181 @@
+//
+//  DQEventMatchLiveListContainerView.swift
+//  DQGuess
+//
+//  Created by jiaxin on 2018/5/16.
+//  Copyright © 2018年 jingbo. All rights reserved.
+//
+
+import UIKit
+
+@objc public protocol JXPagingListContainerViewDelegate {
+
+    func numberOfRows(in listContainerView: JXPagingListContainerView) -> Int
+
+    func listContainerView(_ listContainerView: JXPagingListContainerView, viewForListInRow row: Int) -> UIView
+
+    func listContainerView(_ listContainerView: JXPagingListContainerView, willDisplayCellAt row: Int)
+
+    func listContainerView(_ listContainerView: JXPagingListContainerView, didEndDisplayingCellAt row: Int)
+}
+
+@objc public protocol JXPagingListContainerCollectionViewGestureDelegate {
+    @objc optional func pagingListContainerCollectionViewGestureRecognizerShouldBegin(collectionView: JXPagingListContainerCollectionView, gestureRecognizer: UIGestureRecognizer) -> Bool
+    @objc optional func pagingListContainerCollectionViewGestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool
+}
+
+public class JXPagingListContainerCollectionView: UICollectionView, UIGestureRecognizerDelegate {
+    public var isNestEnabled = false
+    public weak var gestureDelegate: JXPagingListContainerCollectionViewGestureDelegate?
+
+    public override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
+        //如果有代理,就以代理的处理为准
+        if let result = self.gestureDelegate?.pagingListContainerCollectionViewGestureRecognizerShouldBegin?(collectionView: self, gestureRecognizer: gestureRecognizer) {
+            return result
+        }else {
+            if isNestEnabled {
+                //没有代理,但是isNestEnabled为true
+                if gestureRecognizer.isMember(of: NSClassFromString("UIScrollViewPanGestureRecognizer")!) {
+                    let panGesture = gestureRecognizer as! UIPanGestureRecognizer
+                    let velocityX = panGesture.velocity(in: panGesture.view!).x
+                    if velocityX > 0 {
+                        //当前在第一个页面,且往左滑动,就放弃该手势响应,让外层接收,达到多个PagingView左右切换效果
+                        if self.contentOffset.x == 0 {
+                            return false
+                        }
+                    }else if velocityX < 0 {
+                        //当前在最后一个页面,且往右滑动,就放弃该手势响应,让外层接收,达到多个PagingView左右切换效果
+                        if self.contentOffset.x + self.bounds.size.width == self.contentSize.width {
+                            return false
+                        }
+                    }
+                }
+                return true
+            }
+        }
+        return true
+    }
+
+    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
+        if let result = gestureDelegate?.pagingListContainerCollectionViewGestureRecognizer?(gestureRecognizer, shouldRecognizeSimultaneouslyWith: otherGestureRecognizer) {
+            return result
+        }
+        return false;
+    }
+}
+
+open class JXPagingListContainerView: UIView {
+    open var collectionView: JXPagingListContainerCollectionView!
+    unowned var delegate: JXPagingListContainerViewDelegate
+    weak var mainTableView: JXPagingMainTableView?
+
+    private var selectedIndexPath: IndexPath?
+
+    public init(delegate: JXPagingListContainerViewDelegate) {
+        self.delegate = delegate
+
+        super.init(frame: CGRect.zero)
+
+        self.initializeViews()
+    }
+
+    @available(*, unavailable)
+    required public init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    open func initializeViews() {
+        let layout = UICollectionViewFlowLayout()
+        layout.minimumLineSpacing = 0
+        layout.minimumInteritemSpacing = 0
+        layout.scrollDirection = .horizontal
+        collectionView = JXPagingListContainerCollectionView(frame: self.bounds, collectionViewLayout: layout)
+        collectionView.backgroundColor = .white
+        collectionView.showsVerticalScrollIndicator = false
+        collectionView.showsHorizontalScrollIndicator = false
+        collectionView.isPagingEnabled = true
+        collectionView.bounces = false
+        collectionView.dataSource = self
+        collectionView.delegate = self
+        collectionView.scrollsToTop = false
+        collectionView.register(UICollectionViewCell.classForCoder(), forCellWithReuseIdentifier: "cell")
+        if #available(iOS 10.0, *) {
+            collectionView.isPrefetchingEnabled = false
+        }
+        if #available(iOS 11.0, *) {
+            collectionView.contentInsetAdjustmentBehavior = .never
+        }
+        self.addSubview(collectionView)
+    }
+
+    override open func layoutSubviews() {
+        super.layoutSubviews()
+
+        collectionView.frame = self.bounds
+        if selectedIndexPath != nil && self.delegate.numberOfRows(in: self) >= 1 + selectedIndexPath!.item {
+            collectionView.scrollToItem(at: selectedIndexPath!, at: UICollectionView.ScrollPosition.centeredHorizontally, animated: false)
+        }
+    }
+
+    open func reloadData() {
+        self.collectionView.reloadData()
+    }
+
+    open func deviceOrientationDidChanged() {
+        selectedIndexPath = IndexPath(item: Int(collectionView.contentOffset.x/bounds.size.width), section: 0)
+    }
+}
+
+extension JXPagingListContainerView: UICollectionViewDataSource, UICollectionViewDelegate {
+    
+    public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
+        return self.delegate.numberOfRows(in: self)
+    }
+
+    public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
+        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
+        for view in cell.contentView.subviews {
+            view.removeFromSuperview()
+        }
+        let listView = self.delegate.listContainerView(self, viewForListInRow: indexPath.item)
+        listView.frame = cell.bounds
+        cell.contentView.addSubview(listView)
+        return cell
+    }
+
+    public func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
+        self.delegate.listContainerView(self, willDisplayCellAt: indexPath.item)
+    }
+
+    public func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
+        self.delegate.listContainerView(self, didEndDisplayingCellAt: indexPath.item)
+    }
+
+    public func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool {
+        return false
+    }
+
+    public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
+        self.mainTableView?.isScrollEnabled = true
+    }
+
+    public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
+        self.mainTableView?.isScrollEnabled = true
+    }
+
+    public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
+        self.mainTableView?.isScrollEnabled = true
+    }
+
+    public func scrollViewDidScroll(_ scrollView: UIScrollView) {
+        if scrollView.isTracking || scrollView.isDecelerating {
+            self.mainTableView?.isScrollEnabled = false
+        }
+    }
+}
+
+extension JXPagingListContainerView: UICollectionViewDelegateFlowLayout {
+    public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
+        return self.bounds.size
+    }
+}

+ 82 - 0
RainbowPlanet/RainbowPlanet/Tools/JXPagingView-Swift/JXPagingListRefreshView.swift

@@ -0,0 +1,82 @@
+//
+//  JXPagingListRefreshView.swift
+//  JXPagingView
+//
+//  Created by jiaxin on 2018/8/28.
+//  Copyright © 2018年 jiaxin. All rights reserved.
+//
+
+import UIKit
+
+open class JXPagingListRefreshView: JXPagingView {
+    fileprivate var lastScrollingListViewContentOffsetY: CGFloat = 0
+
+    override open func initializeViews() {
+        super.initializeViews()
+
+        mainTableView.bounces = false
+    }
+
+    override open func preferredProcessMainTableViewDidScroll(_ scrollView: UIScrollView) {
+        if pinSectionHeaderVerticalOffset != 0 {
+            if scrollView.contentOffset.y == 0 {
+                mainTableView.bounces = false
+            }else {
+                mainTableView.bounces = true
+            }
+        }
+        if (self.currentScrollingListView != nil && self.currentScrollingListView!.contentOffset.y > 0) {
+            //mainTableView的header已经滚动不见,开始滚动某一个listView,那么固定mainTableView的contentOffset,让其不动
+            self.mainTableView.contentOffset = CGPoint(x: 0, y: getMainTableViewMaxContentOffsetY())
+        }
+
+        if (mainTableView.contentOffset.y < getMainTableViewMaxContentOffsetY()) {
+            //mainTableView已经显示了header,listView的contentOffset需要重置
+            for list in self.validListDict.values {
+                //正在下拉刷新时,不需要重置
+                if list.listScrollView().contentOffset.y > 0 {
+                    list.listScrollView().contentOffset = CGPoint.zero
+                }
+            }
+        }
+
+        if scrollView.contentOffset.y > getMainTableViewMaxContentOffsetY() && self.currentScrollingListView?.contentOffset.y == 0 {
+            //当往上滚动mainTableView的headerView时,滚动到底时,修复listView往上小幅度滚动
+            self.mainTableView.contentOffset = CGPoint(x: 0, y: getMainTableViewMaxContentOffsetY())
+        }
+    }
+    
+    override open func preferredProcessListViewDidScroll(scrollView: UIScrollView) {
+        var shouldProcess = true
+        if currentScrollingListView!.contentOffset.y > self.lastScrollingListViewContentOffsetY {
+            //往上滚动
+        }else {
+            //往下滚动
+            if self.mainTableView.contentOffset.y == 0 {
+                shouldProcess = false
+            }else {
+                if (self.mainTableView.contentOffset.y < getMainTableViewMaxContentOffsetY()) {
+                    //mainTableView的header还没有消失,让listScrollView一直为0
+                    currentScrollingListView!.contentOffset = CGPoint.zero;
+                    currentScrollingListView!.showsVerticalScrollIndicator = false;
+                }
+            }
+        }
+        if shouldProcess {
+            if (self.mainTableView.contentOffset.y < getMainTableViewMaxContentOffsetY()) {
+                //处于下拉刷新的状态,scrollView.contentOffset.y为负数,就重置为0
+                if currentScrollingListView!.contentOffset.y > 0 {
+                    //mainTableView的header还没有消失,让listScrollView一直为0
+                    currentScrollingListView!.contentOffset = CGPoint.zero;
+                    currentScrollingListView!.showsVerticalScrollIndicator = false;
+                }
+            } else {
+                //mainTableView的header刚好消失,固定mainTableView的位置,显示listScrollView的滚动条
+                self.mainTableView.contentOffset = CGPoint(x: 0, y: getMainTableViewMaxContentOffsetY());
+                currentScrollingListView!.showsVerticalScrollIndicator = true;
+            }
+        }
+        self.lastScrollingListViewContentOffsetY = currentScrollingListView!.contentOffset.y;
+    }
+
+}

+ 26 - 0
RainbowPlanet/RainbowPlanet/Tools/JXPagingView-Swift/JXPagingMainTableView.swift

@@ -0,0 +1,26 @@
+//
+//  JXPagingViewMainTableView.swift
+//  JXPagingView
+//
+//  Created by jiaxin on 2018/5/22.
+//  Copyright © 2018年 jiaxin. All rights reserved.
+//
+
+import UIKit
+
+@objc public protocol JXPagingMainTableViewGestureDelegate {
+    //如果headerView(或其他地方)有水平滚动的scrollView,当其正在左右滑动的时候,就不能让列表上下滑动,所以有此代理方法进行对应处理
+    func mainTableViewGestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool
+}
+
+open class JXPagingMainTableView: UITableView, UIGestureRecognizerDelegate {
+    open weak var gestureDelegate: JXPagingMainTableViewGestureDelegate?
+
+    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
+        if gestureDelegate != nil {
+            return gestureDelegate!.mainTableViewGestureRecognizer(gestureRecognizer, shouldRecognizeSimultaneouslyWith:otherGestureRecognizer)
+        }else {
+            return gestureRecognizer.isKind(of: UIPanGestureRecognizer.classForCoder()) && otherGestureRecognizer.isKind(of: UIPanGestureRecognizer.classForCoder())
+        }
+    }
+}

+ 408 - 0
RainbowPlanet/RainbowPlanet/Tools/JXPagingView-Swift/JXPagingView.swift

@@ -0,0 +1,408 @@
+//
+//  JXPagingView.swift
+//  JXPagingView
+//
+//  Created by jiaxin on 2018/5/22.
+//  Copyright © 2018年 jiaxin. All rights reserved.
+//
+
+import UIKit
+
+@objc public protocol JXPagingViewListViewDelegate: NSObjectProtocol {
+
+    /// 返回listView
+    ///
+    /// - Returns: UIView
+    func listView() -> UIView
+
+    /// 返回listView内部持有的UIScrollView或UITableView或UICollectionView
+    /// 主要用于mainTableView已经显示了header,listView的contentOffset需要重置时,内部需要访问到外部传入进来的listView内的scrollView
+    ///
+    /// - Returns: listView内部持有的UIScrollView或UITableView或UICollectionView
+    func listScrollView() -> UIScrollView
+
+
+    /// 当listView内部持有的UIScrollView或UITableView或UICollectionView的代理方法`scrollViewDidScroll`回调时,需要调用该代理方法传入的callback
+    ///
+    /// - Parameter callback: `scrollViewDidScroll`回调时调用的callback
+    func listViewDidScrollCallback(callback: @escaping (UIScrollView)->())
+
+    /// 将要重置listScrollView的contentOffset
+    @objc optional func listScrollViewWillResetContentOffset()
+
+    /// 列表显示的时候调用
+    @objc optional func listDidAppear()
+
+    /// 列表消失的时候调用
+    @objc optional func listDidDisappear()
+}
+
+@objc public protocol JXPagingViewDelegate: NSObjectProtocol {
+
+
+    /// tableHeaderView的高度,因为内部需要比对判断,只能是整型数
+    ///
+    /// - Parameter pagingView: JXPagingViewView
+    /// - Returns: height
+    func tableHeaderViewHeight(in pagingView: JXPagingView) -> Int
+
+
+    /// 返回tableHeaderView
+    ///
+    /// - Parameter pagingView: JXPagingViewView
+    /// - Returns: view
+    func tableHeaderView(in pagingView: JXPagingView) -> UIView
+
+
+    /// 返回悬浮HeaderView的高度,因为内部需要比对判断,只能是整型数
+    ///
+    /// - Parameter pagingView: JXPagingViewView
+    /// - Returns: height
+    func heightForPinSectionHeader(in pagingView: JXPagingView) -> Int
+
+
+    /// 返回悬浮HeaderView。我用的是自己封装的JXCategoryView(Github:https://github.com/pujiaxin33/JXCategoryView),你也可以选择其他的三方库或者自己写
+    ///
+    /// - Parameter pagingView: JXPagingViewView
+    /// - Returns: view
+    func viewForPinSectionHeader(in pagingView: JXPagingView) -> UIView
+
+    /// 返回列表的数量
+    ///
+    /// - Parameter pagingView: pagingView description
+    /// - Returns: 列表的数量
+    func numberOfLists(in pagingView: JXPagingView) -> Int
+
+    /// 根据index初始化一个对应列表实例,需要是遵从`JXPagerViewListViewDelegate`协议的对象。
+    /// 如果列表是用自定义UIView封装的,就让自定义UIView遵从`JXPagerViewListViewDelegate`协议,该方法返回自定义UIView即可。
+    /// 如果列表是用自定义UIViewController封装的,就让自定义UIViewController遵从`JXPagerViewListViewDelegate`协议,该方法返回自定义UIViewController即可。
+    /// 注意:一定要是新生成的实例!!!
+    ///
+    /// - Parameters:
+    ///   - pagingView: pagingView description
+    ///   - index: 新生成的列表实例
+    func pagingView(_ pagingView: JXPagingView, initListAtIndex index: Int) -> JXPagingViewListViewDelegate
+
+    /// mainTableView的滚动回调,用于实现头图跟随缩放
+    ///
+    /// - Parameter scrollView: JXPagingViewMainTableView
+    @objc optional func mainTableViewDidScroll(_ scrollView: UIScrollView)
+}
+
+open class JXPagingView: UIView {
+    public unowned let delegate: JXPagingViewDelegate
+    open var mainTableView: JXPagingMainTableView!
+    open var listContainerView: JXPagingListContainerView!
+    public var validListDict = [Int:JXPagingViewListViewDelegate]() //当前已经加载过可用的列表字典,key就是index值,value是对应的列表。
+    open var pinSectionHeaderVerticalOffset: CGFloat = 0  //顶部固定sectionHeader的垂直偏移量。数值越大越往下沉。
+    public var isListHorizontalScrollEnabled = true {
+        didSet {
+            refreshListHorizontalScrollEnabledState()
+        }
+    }
+    open var automaticallyDisplayListVerticalScrollIndicator = true //是否允许当前列表自动显示或隐藏列表是垂直滚动指示器。true:悬浮的headerView滚动到顶部开始滚动列表时,就会显示,反之隐藏。false:内部不会处理列表的垂直滚动指示器。默认为:true。
+    public var currentScrollingListView: UIScrollView?
+    public var currentList: JXPagingViewListViewDelegate?
+    private var currentDeviceOrientation: UIDeviceOrientation?
+    private var currentIndex: Int = 0
+    private var retainedSelf: JXPagingView?
+    private var isWillRemoveFromWindow: Bool = false
+    private var isFirstMoveToWindow: Bool = true
+
+    deinit {
+        NotificationCenter.default.removeObserver(self)
+    }
+
+    public init(delegate: JXPagingViewDelegate) {
+        self.delegate = delegate
+        super.init(frame: CGRect.zero)
+
+        initializeViews()
+    }
+
+    @available(*, unavailable)
+    required public init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    open func initializeViews(){
+        mainTableView = JXPagingMainTableView(frame: CGRect.zero, style: .plain)
+        mainTableView.showsVerticalScrollIndicator = false
+        mainTableView.showsHorizontalScrollIndicator = false
+        mainTableView.separatorStyle = .none
+        mainTableView.dataSource = self
+        mainTableView.delegate = self
+        mainTableView.scrollsToTop = false
+        mainTableView.tableHeaderView = self.delegate.tableHeaderView(in: self)
+        mainTableView.register(UITableViewCell.classForCoder(), forCellReuseIdentifier: "cell")
+        addSubview(mainTableView)
+
+        if #available(iOS 11.0, *) {
+            mainTableView.contentInsetAdjustmentBehavior = .never
+        } 
+
+        listContainerView = JXPagingListContainerView(delegate: self)
+        listContainerView.mainTableView = mainTableView
+
+        refreshListHorizontalScrollEnabledState()
+
+        self.currentDeviceOrientation = UIDevice.current.orientation
+        NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationDidChange(notification:)), name: UIDevice.orientationDidChangeNotification, object: nil)
+    }
+
+    open override func willMove(toWindow newWindow: UIWindow?) {
+        if self.isFirstMoveToWindow {
+            //第一次调用过滤,因为第一次列表显示通知会从willDisplayCell方法通知
+            self.isFirstMoveToWindow = false
+            return
+        }
+        //当前页面push到一个新的页面时,willMoveToWindow会调用三次。第一次调用的newWindow为nil,第二次调用间隔1ms左右newWindow有值,第三次调用间隔400ms左右newWindow为nil。
+        //根据上述事实,第一次和第二次为无效调用,可以根据其间隔1ms左右过滤掉
+        if newWindow == nil {
+            self.isWillRemoveFromWindow = true
+            //当前页面被pop的时候,willMoveToWindow只会调用一次,而且整个页面会被销毁掉,所以需要循环引用自己,确保能延迟执行currentListDidDisappear方法,触发列表消失事件。由此可见,循环引用也不一定是个坏事。是天使还是魔鬼,就看你如何对待它了。
+            self.retainedSelf = self
+            self.perform(#selector(currentListDidDisappear), with: nil, afterDelay: 0.02)
+        }else {
+            if self.isWillRemoveFromWindow {
+                self.isWillRemoveFromWindow = false
+                NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(currentListDidDisappear), object: nil)
+            }else {
+                self.currentListDidAppear()
+            }
+        }
+    }
+
+    override open func layoutSubviews() {
+        super.layoutSubviews()
+
+        mainTableView.frame = self.bounds
+    }
+
+    open func reloadData() {
+        self.currentList = nil
+        self.currentScrollingListView = nil
+
+        for list in validListDict.values {
+            list.listView().removeFromSuperview()
+        }
+        validListDict.removeAll()
+
+        self.mainTableView.tableHeaderView = self.delegate.tableHeaderView(in: self)
+        self.mainTableView.reloadData()
+        self.listContainerView.reloadData()
+    }
+
+    open func preferredProcessListViewDidScroll(scrollView: UIScrollView) {
+        if (self.mainTableView.contentOffset.y < getMainTableViewMaxContentOffsetY()) {
+            //mainTableView的header还没有消失,让listScrollView一直为0
+            self.currentList?.listScrollViewWillResetContentOffset?()
+            currentScrollingListView!.contentOffset = CGPoint.zero
+            if automaticallyDisplayListVerticalScrollIndicator {
+                currentScrollingListView!.showsVerticalScrollIndicator = false
+            }
+        } else {
+            //mainTableView的header刚好消失,固定mainTableView的位置,显示listScrollView的滚动条
+            self.mainTableView.contentOffset = CGPoint(x: 0, y: getMainTableViewMaxContentOffsetY())
+            if automaticallyDisplayListVerticalScrollIndicator {
+                currentScrollingListView!.showsVerticalScrollIndicator = true
+            }
+        }
+    }
+
+    open func preferredProcessMainTableViewDidScroll(_ scrollView: UIScrollView) {
+        if (self.currentScrollingListView != nil && self.currentScrollingListView!.contentOffset.y > 0) {
+            //mainTableView的header已经滚动不见,开始滚动某一个listView,那么固定mainTableView的contentOffset,让其不动
+            self.mainTableView.contentOffset = CGPoint(x: 0, y: getMainTableViewMaxContentOffsetY())
+        }
+
+        if (self.mainTableView.contentOffset.y < getMainTableViewMaxContentOffsetY()) {
+            //mainTableView已经显示了header,listView的contentOffset需要重置
+            for list in self.validListDict.values {
+                list.listScrollViewWillResetContentOffset?()
+                list.listScrollView().contentOffset = CGPoint.zero
+            }
+        }
+
+        if scrollView.contentOffset.y > getMainTableViewMaxContentOffsetY() && self.currentScrollingListView?.contentOffset.y == 0 {
+            //当往上滚动mainTableView的headerView时,滚动到底时,修复listView往上小幅度滚动
+            self.mainTableView.contentOffset = CGPoint(x: 0, y: getMainTableViewMaxContentOffsetY())
+        }
+    }
+
+    //MARK: - Private
+
+    func refreshListHorizontalScrollEnabledState() {
+        listContainerView.collectionView.isScrollEnabled = isListHorizontalScrollEnabled
+    }
+
+    func getMainTableViewMaxContentOffsetY() -> CGFloat {
+        return CGFloat(self.delegate.tableHeaderViewHeight(in: self)) - pinSectionHeaderVerticalOffset
+    }
+
+    func getPinSectionHeaderHeight() -> CGFloat {
+        return CGFloat(self.delegate.heightForPinSectionHeader(in: self))
+    }
+
+    /// 外部传入的listView,当其内部的scrollView滚动时,需要调用该方法
+    func listViewDidScroll(scrollView: UIScrollView) {
+        self.currentScrollingListView = scrollView
+
+        preferredProcessListViewDidScroll(scrollView: scrollView)
+    }
+
+    @objc func deviceOrientationDidChange(notification: Notification) {
+        if self.currentDeviceOrientation != UIDevice.current.orientation {
+            self.currentDeviceOrientation = UIDevice.current.orientation
+            //前后台切换也会触发该通知,所以不相同的时候才处理
+            mainTableView.reloadData()
+            listContainerView.deviceOrientationDidChanged()
+            listContainerView.reloadData()
+        }
+    }
+
+    @objc func currentListDidDisappear() {
+        let list = self.validListDict[self.currentIndex]
+        list?.listDidDisappear?()
+        self.isWillRemoveFromWindow = false
+        self.retainedSelf = nil
+    }
+
+    func currentListDidAppear() {
+        self.listDidAppear(index: self.currentIndex)
+    }
+
+    func listDidAppear(index: Int) {
+        let count = self.delegate.numberOfLists(in: self)
+        if count <= 0 || index >= count {
+            return
+        }
+        self.currentIndex = index
+        let list = self.validListDict[index]
+        list?.listDidAppear?()
+    }
+
+    func listDidDisappear(index: Int) {
+        let count = self.delegate.numberOfLists(in: self)
+        if count <= 0 || index >= count {
+            return
+        }
+        self.currentIndex = index
+        let list = self.validListDict[index]
+        list?.listDidDisappear?()
+    }
+}
+
+//MARK: - UITableViewDataSource, UITableViewDelegate
+extension JXPagingView: UITableViewDataSource, UITableViewDelegate {
+    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        return 1
+    }
+
+    public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
+        return self.bounds.height - getPinSectionHeaderHeight() - pinSectionHeaderVerticalOffset
+    }
+
+    public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
+        for subview in cell.contentView.subviews {
+            subview.removeFromSuperview()
+        }
+        listContainerView.frame = cell.contentView.bounds
+        cell.contentView.addSubview(listContainerView)
+        return cell
+    }
+
+    public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
+        return getPinSectionHeaderHeight()
+    }
+
+    public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
+        return self.delegate.viewForPinSectionHeader(in: self)
+    }
+
+    //加上footer之后,下滑滚动就变得丝般顺滑了
+    public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
+        return 1
+    }
+
+    public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
+        let footerView = UIView(frame: CGRect.zero)
+        footerView.backgroundColor = UIColor.clear
+        return footerView
+    }
+
+    public func scrollViewDidScroll(_ scrollView: UIScrollView) {
+        //用户正在上下滚动的时候,就不允许左右滚动
+        if scrollView.isTracking && isListHorizontalScrollEnabled {
+            self.listContainerView.collectionView.isScrollEnabled = false
+        }
+
+        if scrollView.contentOffset.y < pinSectionHeaderVerticalOffset && scrollView.contentOffset.y >= 0 {
+            //因为设置了contentInset.top,所以顶部会有对应高度的空白区间,所以需要设置负数抵消掉
+            scrollView.contentInset = UIEdgeInsets(top: -scrollView.contentOffset.y, left: 0, bottom: 0, right: 0)
+        }else if scrollView.contentOffset.y > pinSectionHeaderVerticalOffset {
+            //固定的位置就是contentInset.top
+            scrollView.contentInset = UIEdgeInsets(top: pinSectionHeaderVerticalOffset, left: 0, bottom: 0, right: 0)
+        }
+
+        preferredProcessMainTableViewDidScroll(scrollView)
+
+        self.delegate.mainTableViewDidScroll?(scrollView)
+    }
+
+    public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
+        if isListHorizontalScrollEnabled {
+            self.listContainerView.collectionView.isScrollEnabled = true
+        }
+    }
+
+    public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
+        if isListHorizontalScrollEnabled {
+            self.listContainerView.collectionView.isScrollEnabled = true
+        }
+    }
+
+    public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
+        if isListHorizontalScrollEnabled {
+            self.listContainerView.collectionView.isScrollEnabled = true
+        }
+    }
+}
+
+extension JXPagingView: JXPagingListContainerViewDelegate {
+    public func numberOfRows(in listContainerView: JXPagingListContainerView) -> Int {
+        return self.delegate.numberOfLists(in: self)
+    }
+    public func listContainerView(_ listContainerView: JXPagingListContainerView, viewForListInRow row: Int) -> UIView {
+        var list = validListDict[row]
+        if list == nil {
+            list = self.delegate.pagingView(self, initListAtIndex: row)
+            list?.listViewDidScrollCallback {[weak self, weak list] (scrollView) in
+                self?.currentList = list
+                self?.listViewDidScroll(scrollView: scrollView)
+            }
+            validListDict[row] = list!
+        }
+        for listItem in validListDict.values {
+            if listItem === list {
+                listItem.listScrollView().scrollsToTop = true
+            }else {
+                listItem.listScrollView().scrollsToTop = false
+            }
+        }
+        return list!.listView()
+    }
+
+    public func listContainerView(_ listContainerView: JXPagingListContainerView, willDisplayCellAt row: Int) {
+        self.listDidAppear(index: row)
+        self.currentScrollingListView = validListDict[row]?.listScrollView()
+    }
+
+    public func listContainerView(_ listContainerView: JXPagingListContainerView, didEndDisplayingCellAt row: Int) {
+        self.listDidDisappear(index: row)
+    }
+}
+
+
+