Procházet zdrojové kódy

商城首页面处理了

nanxinlin před 6 roky
rodič
revize
3f69befd30

+ 1 - 0
RainbowPlanet/Podfile

@@ -36,6 +36,7 @@ target 'RainbowPlanet' do
   pod 'MLeaksFinder'
   # 占位图
   pod 'LYEmptyView'
+  pod 'JXCategoryView'
   # 轮播
 #  pod 'FSPagerView'
   # 分段导航栏

+ 5 - 1
RainbowPlanet/Podfile.lock

@@ -5,6 +5,7 @@ PODS:
   - DeviceKit (1.11.0)
   - FBRetainCycleDetector (0.1.4)
   - IQKeyboardManagerSwift (6.2.0)
+  - JXCategoryView (1.2.9)
   - Kingfisher (4.10.1)
   - LYEmptyView (1.2.3)
   - MBProgressHUD (1.1.0)
@@ -59,6 +60,7 @@ DEPENDENCIES:
   - CryptoSwift
   - DeviceKit
   - IQKeyboardManagerSwift
+  - JXCategoryView
   - Kingfisher
   - LYEmptyView
   - MBProgressHUD
@@ -89,6 +91,7 @@ SPEC REPOS:
     - DeviceKit
     - FBRetainCycleDetector
     - IQKeyboardManagerSwift
+    - JXCategoryView
     - Kingfisher
     - LYEmptyView
     - MBProgressHUD
@@ -118,6 +121,7 @@ SPEC CHECKSUMS:
   DeviceKit: a3a86f8dddbe1317a9a243cdf9646858bf135dce
   FBRetainCycleDetector: 46f8179bbb1c587deee3ea838a1a3ee02acf5015
   IQKeyboardManagerSwift: b07ccf9d8cafe993dcd6cb794eb4ba34611a0c4e
+  JXCategoryView: 88a56da74d553ef98e9fc827dde46e277a2c3ed4
   Kingfisher: c148cd7b47ebde9989f6bc7c27dcaa79d81279a0
   LYEmptyView: ea5827f3f81fcbec427f990005501991477bdae8
   MBProgressHUD: e7baa36a220447d8aeb12769bf0585582f3866d9
@@ -140,6 +144,6 @@ SPEC CHECKSUMS:
   UMCSecurityPlugins: 0831a08f3988f3cea9f1d3a7626cd9bee4fef150
   UMCShare: 552b29753f1b4da87b51d96545ed19e6263df397
 
-PODFILE CHECKSUM: a4d53eeb91931bb1e29f62d510d184baf7b4b365
+PODFILE CHECKSUM: baaea47df5a007a33ef762fe5cbd89bb9bae070f
 
 COCOAPODS: 1.5.3

+ 18 - 8
RainbowPlanet/RainbowPlanet.xcodeproj/project.pbxproj

@@ -108,8 +108,6 @@
 		A775CBFE2237493600EBDCF8 /* ShoppingMallNavigationBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A775CBFD2237493600EBDCF8 /* ShoppingMallNavigationBarView.swift */; };
 		A775CC00223774A300EBDCF8 /* ShoppingMallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A775CBFF223774A300EBDCF8 /* ShoppingMallView.swift */; };
 		A775CC0322377C6500EBDCF8 /* EmptyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A775CC0222377C6500EBDCF8 /* EmptyView.swift */; };
-		A775CC05223798F000EBDCF8 /* ShoppingMallCategoryCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A775CC04223798F000EBDCF8 /* ShoppingMallCategoryCollectionViewCell.swift */; };
-		A775CC072237A69D00EBDCF8 /* ShoppingMallHeaderCollectionReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A775CC062237A69D00EBDCF8 /* ShoppingMallHeaderCollectionReusableView.swift */; };
 		A77F2C612231FB49001BD3F6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A77F2C602231FB49001BD3F6 /* AppDelegate.swift */; };
 		A77F2C682231FB4A001BD3F6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A77F2C672231FB4A001BD3F6 /* Assets.xcassets */; };
 		A77F2C762231FB4A001BD3F6 /* RainbowPlanetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A77F2C752231FB4A001BD3F6 /* RainbowPlanetTests.swift */; };
@@ -127,6 +125,10 @@
 		A77F2CC722320627001BD3F6 /* WRNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = A77F2CC522320627001BD3F6 /* WRNavigationBar.swift */; };
 		A77F2CC822320627001BD3F6 /* WRCustomNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = A77F2CC622320627001BD3F6 /* WRCustomNavigationBar.swift */; };
 		A77F2CCA223209F2001BD3F6 /* BaseTabbarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A77F2CC9223209F2001BD3F6 /* BaseTabbarViewController.swift */; };
+		A7A97FDA2238FBAD0070F84D /* VerticalListSectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7A97FD62238FBAC0070F84D /* VerticalListSectionModel.swift */; };
+		A7A97FDB2238FBAD0070F84D /* VerticalListCellModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7A97FD72238FBAC0070F84D /* VerticalListCellModel.swift */; };
+		A7A97FDC2238FBAD0070F84D /* VerticalListCellCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7A97FD82238FBAC0070F84D /* VerticalListCellCollectionViewCell.swift */; };
+		A7A97FDD2238FBAD0070F84D /* VerticalSectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7A97FD92238FBAD0070F84D /* VerticalSectionHeaderView.swift */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -258,8 +260,6 @@
 		A775CBFD2237493600EBDCF8 /* ShoppingMallNavigationBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShoppingMallNavigationBarView.swift; sourceTree = "<group>"; };
 		A775CBFF223774A300EBDCF8 /* ShoppingMallView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShoppingMallView.swift; sourceTree = "<group>"; };
 		A775CC0222377C6500EBDCF8 /* EmptyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyView.swift; sourceTree = "<group>"; };
-		A775CC04223798F000EBDCF8 /* ShoppingMallCategoryCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShoppingMallCategoryCollectionViewCell.swift; sourceTree = "<group>"; };
-		A775CC062237A69D00EBDCF8 /* ShoppingMallHeaderCollectionReusableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShoppingMallHeaderCollectionReusableView.swift; sourceTree = "<group>"; };
 		A77F2C5D2231FB49001BD3F6 /* RainbowPlanet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RainbowPlanet.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		A77F2C602231FB49001BD3F6 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
 		A77F2C672231FB4A001BD3F6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@@ -284,6 +284,10 @@
 		A77F2CC622320627001BD3F6 /* WRCustomNavigationBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WRCustomNavigationBar.swift; sourceTree = "<group>"; };
 		A77F2CC9223209F2001BD3F6 /* BaseTabbarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseTabbarViewController.swift; sourceTree = "<group>"; };
 		A7A59A7722363CCB00417FA4 /* RainbowPlanet.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RainbowPlanet.entitlements; sourceTree = "<group>"; };
+		A7A97FD62238FBAC0070F84D /* VerticalListSectionModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerticalListSectionModel.swift; sourceTree = "<group>"; };
+		A7A97FD72238FBAC0070F84D /* VerticalListCellModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerticalListCellModel.swift; sourceTree = "<group>"; };
+		A7A97FD82238FBAC0070F84D /* VerticalListCellCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerticalListCellCollectionViewCell.swift; sourceTree = "<group>"; };
+		A7A97FD92238FBAD0070F84D /* VerticalSectionHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerticalSectionHeaderView.swift; sourceTree = "<group>"; };
 		A7E03A30F40582782EC5DA89 /* Pods_RainbowPlanetTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RainbowPlanetTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		B1B8205A06E3602D2CF199C8 /* Pods-RainbowPlanetTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RainbowPlanetTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RainbowPlanetTests/Pods-RainbowPlanetTests.release.xcconfig"; sourceTree = "<group>"; };
 		BD9052C044FD3AE4E62D3929 /* Pods-RainbowPlanet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RainbowPlanet.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RainbowPlanet/Pods-RainbowPlanet.debug.xcconfig"; sourceTree = "<group>"; };
@@ -668,8 +672,10 @@
 			children = (
 				A775CBFD2237493600EBDCF8 /* ShoppingMallNavigationBarView.swift */,
 				A775CBFF223774A300EBDCF8 /* ShoppingMallView.swift */,
-				A775CC04223798F000EBDCF8 /* ShoppingMallCategoryCollectionViewCell.swift */,
-				A775CC062237A69D00EBDCF8 /* ShoppingMallHeaderCollectionReusableView.swift */,
+				A7A97FD82238FBAC0070F84D /* VerticalListCellCollectionViewCell.swift */,
+				A7A97FD72238FBAC0070F84D /* VerticalListCellModel.swift */,
+				A7A97FD62238FBAC0070F84D /* VerticalListSectionModel.swift */,
+				A7A97FD92238FBAD0070F84D /* VerticalSectionHeaderView.swift */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -1175,6 +1181,7 @@
 				"${BUILT_PRODUCTS_DIR}/DeviceKit/DeviceKit.framework",
 				"${BUILT_PRODUCTS_DIR}/FBRetainCycleDetector/FBRetainCycleDetector.framework",
 				"${BUILT_PRODUCTS_DIR}/IQKeyboardManagerSwift/IQKeyboardManagerSwift.framework",
+				"${BUILT_PRODUCTS_DIR}/JXCategoryView/JXCategoryView.framework",
 				"${BUILT_PRODUCTS_DIR}/Kingfisher/Kingfisher.framework",
 				"${BUILT_PRODUCTS_DIR}/LYEmptyView/LYEmptyView.framework",
 				"${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework",
@@ -1200,6 +1207,7 @@
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DeviceKit.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBRetainCycleDetector.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/IQKeyboardManagerSwift.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JXCategoryView.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Kingfisher.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/LYEmptyView.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MBProgressHUD.framework",
@@ -1286,6 +1294,7 @@
 				A72A73392232688100B21995 /* AlipayOrderModel.swift in Sources */,
 				A72A72A322321DE000B21995 /* LBXScanView.swift in Sources */,
 				A72A730D2232207700B21995 /* AppDelegate+BaiduMap.swift in Sources */,
+				A7A97FDC2238FBAD0070F84D /* VerticalListCellCollectionViewCell.swift in Sources */,
 				A72A7386223396CB00B21995 /* SwiftMoyaNetWorkManager.swift in Sources */,
 				A72A735C2233635B00B21995 /* AppDelegate+ShanYan.swift in Sources */,
 				A77F2CCA223209F2001BD3F6 /* BaseTabbarViewController.swift in Sources */,
@@ -1312,7 +1321,6 @@
 				A72A72A622321DE000B21995 /* LBXScanViewStyle.swift in Sources */,
 				A72A72B422321DE000B21995 /* Extension+UIImage.swift in Sources */,
 				A72A72AF22321DE000B21995 /* AppInfo.swift in Sources */,
-				A775CC072237A69D00EBDCF8 /* ShoppingMallHeaderCollectionReusableView.swift in Sources */,
 				A72A72D422321E2700B21995 /* EnumMacro.swift in Sources */,
 				A775CC0322377C6500EBDCF8 /* EmptyView.swift in Sources */,
 				A72A72B322321DE000B21995 /* UIAlertController+BAKit.m in Sources */,
@@ -1321,18 +1329,20 @@
 				A72A72B622321DE000B21995 /* Extension+NSRange.swift in Sources */,
 				A72A72A722321DE000B21995 /* LBXPermissions.swift in Sources */,
 				A72A72AE22321DE000B21995 /* CountdownButton.swift in Sources */,
-				A775CC05223798F000EBDCF8 /* ShoppingMallCategoryCollectionViewCell.swift in Sources */,
 				A77F2CB72232010F001BD3F6 /* MineViewController.swift in Sources */,
+				A7A97FDD2238FBAD0070F84D /* VerticalSectionHeaderView.swift in Sources */,
 				A72A7385223396CB00B21995 /* SwiftMoyaNetWorkService.swift in Sources */,
 				A72A7346223350ED00B21995 /* ShanYanManager.swift in Sources */,
 				A72A72A822321DE000B21995 /* LBXScanWrapper.swift in Sources */,
 				A72A73932233BFCD00B21995 /* SwiftMoyaNetWorkCacheModel.swift in Sources */,
+				A7A97FDB2238FBAD0070F84D /* VerticalListCellModel.swift in Sources */,
 				A72A72BD22321DE000B21995 /* Extension+UIColor.swift in Sources */,
 				A77F2CC822320627001BD3F6 /* WRCustomNavigationBar.swift in Sources */,
 				A72A72BC22321DE000B21995 /* Extension+UIAlertController.swift in Sources */,
 				A72A730C2232207700B21995 /* AppDelegate+UM.swift in Sources */,
 				A72A730F2232207700B21995 /* AppDelegate+IQKeyboardManagerSwift.swift in Sources */,
 				A72A72B122321DE000B21995 /* UIScrollView+MJRefreshEX.m in Sources */,
+				A7A97FDA2238FBAD0070F84D /* VerticalListSectionModel.swift in Sources */,
 				A72A72A522321DE000B21995 /* LBXScanLineAnimation.swift in Sources */,
 				A72A72C322321DE000B21995 /* Extension+Date.swift in Sources */,
 				A72A72B222321DE000B21995 /* NSObject+BARunTime.m in Sources */,

+ 2 - 0
RainbowPlanet/RainbowPlanet/Define/RainbowPlanet-Bridging-Header.h

@@ -14,6 +14,8 @@
 //支付宝支付
 #import <AlipaySDK/AlipaySDK.h>
 
+#import <JXCategoryView/JXCategoryView.h>
+
 //微信支付
 #import "WXApi.h"
 

+ 0 - 101
RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/ShoppingMall/View/ShoppingMallCategoryCollectionViewCell.swift

@@ -1,101 +0,0 @@
-//
-//  ShoppingMallCategoryCollectionViewCell.swift
-//  RainbowPlanet
-//
-//  Created by 南鑫林 on 2019/3/12.
-//  Copyright © 2019 南鑫林. All rights reserved.
-//
-
-import UIKit
-
-class ShoppingMallCategoryCollectionViewCell: UICollectionViewCell {
-    class func cellWith(collectionView:UICollectionView,indexPath:IndexPath) -> ShoppingMallCategoryCollectionViewCell {
-        let ID = "ShoppingMallCategoryCollectionViewCell"
-        collectionView.register(ShoppingMallCategoryCollectionViewCell.self, forCellWithReuseIdentifier: ID)
-        let cell : ShoppingMallCategoryCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: ID, for: indexPath) as! ShoppingMallCategoryCollectionViewCell
-        cell.indexPath = indexPath
-        return cell
-    }
-    //MARK: - indexPath
-    var indexPath: IndexPath?{
-        didSet {
-
-        }
-    }
-    //MARK: - 初始化
-    override init(frame: CGRect) {
-        super.init(frame: frame)
-        setupViews()
-        setupLayouts()
-    }
-
-    required init?(coder aDecoder: NSCoder) {
-        fatalError("init(coder:) has not been implemented")
-    }
-
-    //MARK: - 设置view
-    private func setupViews() {
-        addSubview(titleLabel)
-        addSubview(underLineLabel)
-    }
-
-    private func setupLayouts() {
-
-        titleLabel.snp.makeConstraints { (make) in
-            make.edges.equalToSuperview()
-        }
-
-        underLineLabel.snp.makeConstraints { (make) in
-            make.left.right.equalTo(titleLabel)
-            make.bottom.equalToSuperview()
-            make.height.equalTo(2)
-        }
-    }
-
-    private lazy var titleLabel: UILabel = {
-        let titleLabel = UILabel()
-        titleLabel.textColor = UIColor.black
-        titleLabel.highlightedTextColor = UIColor.green
-        titleLabel.textAlignment = .center
-        titleLabel.font = kBoldFont15
-        titleLabel.isHighlighted = false
-        return titleLabel
-    }()
-
-    private lazy var underLineLabel: UILabel = {
-        let underLineLabel = UILabel()
-        underLineLabel.backgroundColor = UIColor.green
-        underLineLabel.textAlignment = .center
-
-        underLineLabel.isHidden = true
-        return underLineLabel
-    }()
-
-    var categoryArray: Array<String>? {
-        didSet {
-            titleLabel.text = categoryArray![(indexPath?.row)!]
-        }
-    }
-
-    override var isSelected: Bool {
-        didSet {
-            isHighlighted = isSelected
-            if isHighlighted {
-                titleLabel.font = kBoldFont15
-            }else {
-                titleLabel.font = kBoldFont15
-            }
-            titleLabel.isHighlighted = isSelected
-            underLineLabel.isHidden = !isSelected
-
-            titleLabel.snp.updateConstraints { (make) in
-                make.edges.equalToSuperview()
-            }
-            underLineLabel.snp.updateConstraints { (make) in
-                make.left.right.equalTo(titleLabel)
-                make.bottom.equalToSuperview()
-                make.height.equalTo(2)
-            }
-        }
-    }
-}

+ 0 - 60
RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/ShoppingMall/View/ShoppingMallHeaderCollectionReusableView.swift

@@ -1,60 +0,0 @@
-//
-//  ShoppingMallHeaderCollectionReusableView.swift
-//  RainbowPlanet
-//
-//  Created by 南鑫林 on 2019/3/12.
-//  Copyright © 2019 南鑫林. All rights reserved.
-//
-
-import UIKit
-
-class ShoppingMallHeaderCollectionReusableView: UICollectionReusableView {
-    class func headerWith(collectionView:UICollectionView,kind: String,indexPath: IndexPath) -> ShoppingMallHeaderCollectionReusableView {
-        let ID = "ShoppingMallHeaderCollectionReusableView"
-        collectionView.register(ShoppingMallHeaderCollectionReusableView.self, forSupplementaryViewOfKind: kind, withReuseIdentifier: ID)
-        let headerView : ShoppingMallHeaderCollectionReusableView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: ID, for: indexPath) as! ShoppingMallHeaderCollectionReusableView
-        headerView.indexPath = indexPath
-        return headerView
-    }
-
-    var indexPath : IndexPath? {
-        didSet {
-
-        }
-    }
-    override init(frame: CGRect) {
-        super.init(frame: frame)
-        setupViews()
-        setupLayouts()
-    }
-
-    required init?(coder aDecoder: NSCoder) {
-        fatalError("init(coder:) has not been implemented")
-    }
-
-    //MARK: - 设置View
-    private func setupViews() {
-        addSubview(titleLabel)
-    }
-
-    private func setupLayouts() {
-        titleLabel.snp.makeConstraints { (make) in
-            make.edges.equalToSuperview()
-        }
-    }
-
-    private lazy var titleLabel: UILabel = {
-        let titleLabel = UILabel()
-        titleLabel.backgroundColor = UIColor.cyan
-        titleLabel.textColor = UIColor.green
-        titleLabel.textAlignment = .center
-        titleLabel.font = kRegularFont13
-        return titleLabel
-    }()
-
-    var categoryArray: Array<String>? {
-        didSet {
-            titleLabel.text = categoryArray![(indexPath?.row)!]
-        }
-    }
-}

+ 142 - 104
RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/ShoppingMall/View/ShoppingMallView.swift

@@ -8,46 +8,68 @@
 
 import UIKit
 
+let verticalListCategoryViewHeight = 30;   //悬浮categoryView的高度
+let verticalListPinSectionIndex = 1;    //悬浮固定section的index
+
 class ShoppingMallView: BaseView {
 
 
     typealias CategoryActionBlock = () -> Void
     var categoryActionBlock : CategoryActionBlock?
 
-    let categoryArray = ["今日爆款","限量秒杀","萌娃专区萌娃专区","乳饮烘焙","新鲜水果","海鲜水产","方便食品","生活服务","休息食品","美妆日化","家用电器","萌娃专区萌娃专区","乳饮烘焙","新鲜水果","海鲜水产","方便食品","生活服务","休息食品","美妆日化","家用电器"]
+    var dataSource = Array<VerticalListSectionModel>()
+
+    var sectionHeaderAttributes = Array<UICollectionViewLayoutAttributes>()
 
-    fileprivate var selectIndex = 0
-    fileprivate var isScrollDown = true
-    fileprivate var lastOffsetY : CGFloat = 0.0
+    let headerTitles = ["我的频道", "超级大IP", "热门HOT", "周边衍生", "影视综", "游戏集锦", "搞笑百事"];
+    var imageNames = ["boat", "crab", "lobster", "apple", "carrot", "grape", "watermelon"];
 
     override func setupViews() {
         super.setupViews()
+        for (index, title) in headerTitles.enumerated() {
+            let sectionModel = VerticalListSectionModel()
+            sectionModel.sectionTitle = title
+            let randomCount = arc4random()%10 + 5
+            var cellModels = Array<VerticalListCellModel>()
+
+            for _ in 0..<randomCount {
+                let cellModel = VerticalListCellModel()
+                cellModel.imageName = imageNames[index]
+                cellModel.itemName = title
+                cellModels.append(cellModel)
+            }
+            sectionModel.cellModels = cellModels
+            dataSource.append(sectionModel)
+        }
         addSubview(categoryButton)
-        addSubview(categorycollectionView)
+        addSubview(pinCategoryView)
         addSubview(allCollectionView)
 
+
     }
 
+
+
     override func setupLayouts() {
         categoryButton.snp.makeConstraints { (make) in
             make.top.equalToSuperview().offset(2)
             make.right.equalToSuperview().offset(-10)
             make.size.equalTo(30)
         }
-        categorycollectionView.snp.makeConstraints { (make) in
+        pinCategoryView.snp.makeConstraints { (make) in
             make.top.equalToSuperview().offset(2)
             make.right.equalTo(categoryButton.snp.left)
             make.left.equalToSuperview().offset(10)
             make.height.equalTo(30)
         }
         allCollectionView.snp.makeConstraints { (make) in
-            make.top.equalTo(categorycollectionView.snp.bottom)
+            make.top.equalTo(pinCategoryView.snp.bottom)
             make.left.right.bottom.equalToSuperview()
         }
-        categorycollectionView.selectItem(at: IndexPath(item: 0, section: 0), animated: false, scrollPosition: UICollectionView.ScrollPosition.top)
 
     }
 
+
     private lazy var categoryButton: UIButton = {
         let categoryButton = UIButton(type: UIButton.ButtonType.custom)
         categoryButton.setImage(kImage(name: "shop"), for: UIControl.State.normal)
@@ -60,14 +82,18 @@ class ShoppingMallView: BaseView {
         return categoryButton
     }()
 
-    private lazy var categorycollectionView: UICollectionView = {
-        let categorycollectionView = UICollectionView.init(frame: CGRect.zero, collectionViewLayout: categoryCollectionViewLayout)
-        categorycollectionView.backgroundColor = UIColor.white;
-        categorycollectionView.showsVerticalScrollIndicator = false
-        categorycollectionView.showsHorizontalScrollIndicator = false
-        categorycollectionView.delegate = self;
-        categorycollectionView.dataSource = self;
-        return categorycollectionView
+    private lazy var pinCategoryView: JXCategoryTitleView = {
+        let pinCategoryView = JXCategoryTitleView()
+        pinCategoryView.backgroundColor = UIColor.white
+        pinCategoryView.titles = headerTitles
+        pinCategoryView.titleColorGradientEnabled = true
+        pinCategoryView.titleLabelZoomEnabled = true
+        pinCategoryView.titleLabelZoomScale = 1.2
+        let lineView = JXCategoryIndicatorLineView()
+        lineView.lineStyle = .lengthen
+        pinCategoryView.indicators = [lineView];
+        pinCategoryView.delegate = self
+        return pinCategoryView
     }()
 
     private lazy var categoryCollectionViewLayout: UICollectionViewFlowLayout = {
@@ -89,133 +115,145 @@ class ShoppingMallView: BaseView {
         let allCollectionViewLayout = UICollectionViewFlowLayout.init()
         allCollectionViewLayout.scrollDirection = UICollectionView.ScrollDirection.vertical
         //分组头悬停
-        allCollectionViewLayout.sectionHeadersPinToVisibleBounds = true
+//        allCollectionViewLayout.sectionHeadersPinToVisibleBounds = true
         allCollectionViewLayout.itemSize = CGSize(width: kScreenWidth, height:30)
         return allCollectionViewLayout
     }()
 
 }
 
-extension ShoppingMallView : UICollectionViewDelegateFlowLayout,UICollectionViewDataSource {
+extension ShoppingMallView : UICollectionViewDelegate,UICollectionViewDataSource {
+
     func numberOfSections(in collectionView: UICollectionView) -> Int {
-        if collectionView == categorycollectionView {
-            return 1
-        }else {
-            return categoryArray.count
-        }
+        return dataSource.count
     }
     func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-
-        if collectionView == categorycollectionView {
-            return categoryArray.count
-        }else {
-            return categoryArray.count
-        }
+        return self.dataSource[section].cellModels!.count;
     }
 
     func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
-        if collectionView == categorycollectionView {
-            let cell = ShoppingMallCategoryCollectionViewCell.cellWith(collectionView: collectionView, indexPath: indexPath)
-            cell.categoryArray = categoryArray
-            return cell
-        }else {
-            let cell = ShoppingMallCategoryCollectionViewCell.cellWith(collectionView: collectionView, indexPath: indexPath)
-            cell.categoryArray = categoryArray
-            return cell
-        }
+        let cell = VerticalListCellCollectionViewCell.cellWith(collectionView: collectionView, indexPath: indexPath)
+        let sectionModel = dataSource[indexPath.section]
+        let cellModel: VerticalListCellModel? = sectionModel.cellModels![indexPath.row]
+        cell.itemImageView.image = UIImage(named: cellModel?.imageName ?? "")
+        cell.titleLabel.text = cellModel?.itemName
+        return cell
     }
 
     func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-        if collectionView == categorycollectionView {
-            selectIndex = indexPath.row
-             //右侧collection自动滚动到对应的分区
-            collectionViewScrollToTop(section: selectIndex, animated: true)
-             //左侧tableView将该单元格滚动到顶部
-            categorycollectionView.scrollToItem(at: IndexPath(row: selectIndex, section: 0), at: .centeredHorizontally, animated: true)
-        }
-    }
 
-    //将右侧colletionView的指定分区自动滚动到最顶端
-    func collectionViewScrollToTop(section: Int, animated: Bool) {
-        let headerRect = collectionViewHeaderFrame(section: section)
-        let topOfHeader = CGPoint(x: 0, y: headerRect.origin.y
-            - allCollectionView.contentInset.top)
-        allCollectionView.setContentOffset(topOfHeader, animated: animated)
     }
 
-    //后获colletionView的指定分区头的高度
-    func collectionViewHeaderFrame(section: Int) -> CGRect {
-        let indexPath = IndexPath(item: 0, section: section)
-        let attributes = allCollectionView.collectionViewLayout
-            .layoutAttributesForSupplementaryView(ofKind:
-                UICollectionView.elementKindSectionHeader, at: indexPath)
-        guard let frameForFirstCell = attributes?.frame else {
-            return .zero
+    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
+        if kind == UICollectionView.elementKindSectionHeader {
+
+            let headerView = VerticalSectionHeaderView.headerWith(collectionView: collectionView, kind:  UICollectionView.elementKindSectionHeader, indexPath: indexPath)
+            let sectionModel = dataSource[indexPath.section]
+            headerView.titleLabel.text = sectionModel.sectionTitle
+            return headerView
         }
-        return frameForFirstCell;
+        return UICollectionReusableView()
     }
 
+     // 标记一下 CollectionView 的滚动方向,是向上还是向下
+    func scrollViewDidScroll(_ scrollView: UIScrollView) {
 
-    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
-        if collectionView == categorycollectionView {
-            let shoppingMallHeaderCollectionReusableView = ShoppingMallHeaderCollectionReusableView.headerWith(collectionView: collectionView, kind: UICollectionView.elementKindSectionHeader, indexPath: indexPath)
-            shoppingMallHeaderCollectionReusableView.categoryArray = categoryArray
-            return shoppingMallHeaderCollectionReusableView
-        }else {
-            if kind == UICollectionView.elementKindSectionHeader {
-                let shoppingMallHeaderCollectionReusableView = ShoppingMallHeaderCollectionReusableView.headerWith(collectionView: collectionView, kind: UICollectionView.elementKindSectionHeader, indexPath: indexPath)
-                shoppingMallHeaderCollectionReusableView.categoryArray = categoryArray
-                return shoppingMallHeaderCollectionReusableView
-            }else {
-                return UICollectionReusableView()
+        if sectionHeaderAttributes.count <= 0 {
+            var attributes: [AnyHashable] = []
+            var lastHeaderAttri: UICollectionViewLayoutAttributes? = nil
+            for i in 0..<headerTitles.count {
+                let attri: UICollectionViewLayoutAttributes? = allCollectionView.collectionViewLayout.layoutAttributesForSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, at: IndexPath(item: 0, section: i))
+                if let attri = attri {
+                    attributes.append(attri)
+                }
+                if i == headerTitles.count - 1 {
+                    lastHeaderAttri = attri
+                }
+            }
+            sectionHeaderAttributes = attributes as! [UICollectionViewLayoutAttributes]
+
+            //如果最后一个section条目太少了,会导致滚动最底部,但是却不能触发categoryView选中最后一个item。而且点击最后一个滚动的contentOffset.y也不要弄。所以添加contentInset,让最后一个section滚到最下面能显示完整个屏幕,
+
+            let lastCellAttri: UICollectionViewLayoutAttributes? = allCollectionView.collectionViewLayout.layoutAttributesForItem(at: IndexPath(item: (dataSource[headerTitles.count - 1]).cellModels!.count - 1, section: headerTitles.count - 1))
+            let lastSectionHeight: CGFloat = (lastCellAttri?.frame.maxY)! - (lastHeaderAttri?.frame.minY)!
+
+            let value = CGFloat(bounds.size.height - CGFloat(verticalListCategoryViewHeight)) - lastSectionHeight
+            if value > 0 {
+                allCollectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: value, right: 0)
             }
         }
 
-    }
 
-    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
-        if collectionView == categorycollectionView {
-            return CGSize(width: 0, height: 0)
-        }else {
-            return CGSize(width: kScreenWidth, height: 30)
+        if (!(scrollView.isTracking || scrollView.isDecelerating)) {
+            //不是用户滚动的,比如setContentOffset等方法,引起的滚动不需要处理。
+            return;
         }
-    }
 
-    // CollectionView 分区标题即将展示
-    func collectionView(_ collectionView: UICollectionView, willDisplaySupplementaryView view: UICollectionReusableView, forElementKind elementKind: String, at indexPath: IndexPath) {
-        // 当前 CollectionView 滚动的方向向上,CollectionView 是用户拖拽而产生滚动的(主要是判断 CollectionView 是用户拖拽而滚动的,还是点击 TableView 而滚动的)
-        if collectionView == allCollectionView {
-            if !isScrollDown && (collectionView.isDragging || collectionView.isDecelerating) {
-                selectRow(index: indexPath.section)
+        //用户滚动的才处理
+        //获取categoryView下面一点的所有布局信息,用于知道,当前最上方是显示的哪个section
+        let topRect = CGRect(x: 0, y: scrollView.contentOffset.y + 1, width: bounds.size.width, height: 1)
+        let topAttributes: UICollectionViewLayoutAttributes? = allCollectionView.collectionViewLayout.layoutAttributesForElements(in: topRect)?.first
+        let topSection: Int? = topAttributes?.indexPath.section
+        if topAttributes != nil && topSection! >= 0 {
+            if pinCategoryView.selectedIndex != topSection! {
+                //不相同才切换
+                pinCategoryView.selectItem(at: topSection!)
             }
         }
     }
+}
 
-    //分区头即将要消失时调用
-    func collectionView(_ collectionView: UICollectionView,
-                        didEndDisplayingSupplementaryView view: UICollectionReusableView,
-                        forElementOfKind elementKind: String, at indexPath: IndexPath) {
-        //如果是由用户手动滑动屏幕造成的向下滚动,那么左侧表格自动选中该分区对应的下一个分区的分类
-        if collectionView == allCollectionView {
-            if isScrollDown && (collectionView.isDragging || collectionView.isDecelerating) {
-                selectRow(index: indexPath.section + 1)
-            }
-        }
+extension ShoppingMallView:UICollectionViewDelegateFlowLayout {
+
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
+        return CGSize(width: self.bounds.size.width, height: 40)
     }
 
 
-    // 当拖动 CollectionView 的时候,处理 categorycollectionView
-    private func selectRow(index : Int) {
-        categorycollectionView.selectItem(at: IndexPath(row: index, section: 0), animated: true, scrollPosition: UICollectionView.ScrollPosition.centeredHorizontally)
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
+        return CGSize(width: 100, height: 100)
+    }
 
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
+        return 10
     }
 
-     // 标记一下 CollectionView 的滚动方向,是向上还是向下
-    func scrollViewDidScroll(_ scrollView: UIScrollView) {
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
+        return (self.bounds.size.width - 100 * 3) / 4
+    }
+
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
+        let margin: CGFloat = (self.bounds.size.width - 100 * 3) / 4
+        return UIEdgeInsets(top: 0, left: margin, bottom: 0, right: margin)
+    }
+
+}
+
+
+extension ShoppingMallView: JXCategoryViewDelegate{
+
+    func categoryView(_ categoryView: JXCategoryBaseView!, didClickSelectedItemAt index: Int) {
+        self.collectionViewScrollToTop(section: index, animated: true)
+    }
+
+    //将右侧colletionView的指定分区自动滚动到最顶端
+    func collectionViewScrollToTop(section: Int, animated: Bool) {
+        let headerRect = collectionViewHeaderFrame(section: section)
+        let topOfHeader = CGPoint(x: 0, y: headerRect.origin.y
+            - allCollectionView.contentInset.top)
+        allCollectionView.setContentOffset(topOfHeader, animated: animated)
+    }
 
-        if allCollectionView == scrollView {
-            isScrollDown = lastOffsetY < scrollView.contentOffset.y
-            lastOffsetY = scrollView.contentOffset.y
+    //后获colletionView的指定分区头的高度
+    func collectionViewHeaderFrame(section: Int) -> CGRect {
+        let indexPath = IndexPath(item: 0, section: section)
+        let attributes = allCollectionView.collectionViewLayout
+            .layoutAttributesForSupplementaryView(ofKind:
+                UICollectionView.elementKindSectionHeader, at: indexPath)
+        guard let frameForFirstCell = attributes?.frame else {
+            return .zero
         }
+        return frameForFirstCell;
     }
+
 }

+ 62 - 0
RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/ShoppingMall/View/VerticalListCellCollectionViewCell.swift

@@ -0,0 +1,62 @@
+//
+//  VerticalListCellCollectionViewCell.swift
+//  Test
+//
+//  Created by 南鑫林 on 2019/3/13.
+//  Copyright © 2019 南鑫林. All rights reserved.
+//
+
+import UIKit
+
+class VerticalListCellCollectionViewCell: UICollectionViewCell {
+    class func cellWith(collectionView:UICollectionView,indexPath:IndexPath) -> VerticalListCellCollectionViewCell {
+        let ID = "VerticalListCellCollectionViewCell"
+        collectionView.register(VerticalListCellCollectionViewCell.self, forCellWithReuseIdentifier: ID)
+        let cell : VerticalListCellCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: ID, for: indexPath) as! VerticalListCellCollectionViewCell
+        cell.indexPath = indexPath
+        return cell
+    }
+    //MARK: - indexPath
+    var indexPath: IndexPath?{
+        didSet {
+
+        }
+    }
+    //MARK: - 初始化
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        setupViews()
+    }
+
+    required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    //MARK: - 设置view
+    private func setupViews() {
+        contentView.backgroundColor = UIColor.white
+        contentView.layer.cornerRadius = 10
+        contentView.addSubview(titleLabel)
+        contentView.addSubview(itemImageView)
+    }
+
+    override func layoutSubviews() {
+        super.layoutSubviews()
+        self.itemImageView.bounds = CGRect(x: 0, y: 0, width: 50, height: 50)
+        self.itemImageView.center = CGPoint(x: self.bounds.size.width/2, y: 30)
+
+        self.titleLabel.frame = CGRect(x: 0, y: itemImageView.frame.maxY + 5, width:  self.bounds.size.width, height: 30)
+    }
+
+    lazy var titleLabel: UILabel = {
+        let titleLabel = UILabel()
+        titleLabel.textAlignment = .center
+        return titleLabel
+    }()
+
+    lazy var itemImageView: UIImageView = {
+        let itemImageView = UIImageView()
+        return itemImageView
+    }()
+
+}

+ 14 - 0
RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/ShoppingMall/View/VerticalListCellModel.swift

@@ -0,0 +1,14 @@
+//
+//  VerticalListCellModel.swift
+//  Test
+//
+//  Created by 南鑫林 on 2019/3/13.
+//  Copyright © 2019 南鑫林. All rights reserved.
+//
+
+import UIKit
+
+class VerticalListCellModel: NSObject {
+    var imageName : String?
+    var itemName : String?
+}

+ 14 - 0
RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/ShoppingMall/View/VerticalListSectionModel.swift

@@ -0,0 +1,14 @@
+//
+//  VerticalListSectionModel.swift
+//  Test
+//
+//  Created by 南鑫林 on 2019/3/13.
+//  Copyright © 2019 南鑫林. All rights reserved.
+//
+
+import UIKit
+
+class VerticalListSectionModel: NSObject {
+    var sectionTitle : String?
+    var cellModels : Array<VerticalListCellModel>?
+}

+ 55 - 0
RainbowPlanet/RainbowPlanet/Modules/ShoppingMallModule/ShoppingMall/View/VerticalSectionHeaderView.swift

@@ -0,0 +1,55 @@
+//
+//  VerticalSectionHeaderView.swift
+//  Test
+//
+//  Created by 南鑫林 on 2019/3/13.
+//  Copyright © 2019 南鑫林. All rights reserved.
+//
+
+import UIKit
+
+class VerticalSectionHeaderView: UICollectionReusableView {
+    class func headerWith(collectionView:UICollectionView,kind: String,indexPath: IndexPath) -> VerticalSectionHeaderView {
+        let ID = "VerticalSectionHeaderView"
+        collectionView.register(VerticalSectionHeaderView.self, forSupplementaryViewOfKind: kind, withReuseIdentifier: ID)
+        let headerView : VerticalSectionHeaderView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: ID, for: indexPath) as! VerticalSectionHeaderView
+        headerView.indexPath = indexPath
+        return headerView
+    }
+
+    var indexPath : IndexPath? {
+        didSet {
+
+        }
+    }
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        setupViews()
+    }
+
+    required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    //MARK: - 设置View
+    private func setupViews() {
+        backgroundColor = UIColor(red: 0.94, green: 0.94, blue: 0.94, alpha: 1)
+
+        addSubview(titleLabel)
+    }
+
+    override func layoutSubviews() {
+        super.layoutSubviews()
+
+        titleLabel.sizeToFit()
+        titleLabel.frame = CGRect(x: 16, y: (bounds.size.height - (titleLabel.bounds.size.height)) / 2, width: 200, height: titleLabel.bounds.size.height)
+    }
+
+    lazy var titleLabel: UILabel = {
+        let titleLabel = UILabel()
+        titleLabel.textColor = UIColor.lightGray
+        titleLabel.font = UIFont.systemFont(ofSize: 15)
+        return titleLabel
+    }()
+
+}