소스 검색

1.调整框架

南鑫林 5 년 전
부모
커밋
06400a2d1d
20개의 변경된 파일1746개의 추가작업 그리고 45개의 파일을 삭제
  1. 2 2
      RainbowPlanet/Podfile
  2. 5 5
      RainbowPlanet/Podfile.lock
  3. 100 1
      RainbowPlanet/RainbowPlanet.xcodeproj/project.pbxproj
  4. 25 0
      RainbowPlanet/RainbowPlanet/Base/BaseTabbarViewController/BaseBasicContentView.swift
  5. 40 0
      RainbowPlanet/RainbowPlanet/Base/BaseTabbarViewController/BaseBouncesContentView.swift
  6. 118 0
      RainbowPlanet/RainbowPlanet/Base/BaseTabbarViewController/BaseIrregularityBasicContentView.swift
  7. 41 22
      RainbowPlanet/RainbowPlanet/Base/BaseTabbarViewController/BaseTabbarViewController.swift
  8. 16 15
      RainbowPlanet/RainbowPlanet/Macro/ColorMacro.swift
  9. 29 0
      RainbowPlanet/RainbowPlanet/Modules/CommunityModule/Community/ViewController/CommunityViewController.swift
  10. 22 0
      RainbowPlanet/RainbowPlanet/Supporting Files/Assets.xcassets/TabbarIcons/photo_verybig.imageset/Contents.json
  11. BIN
      RainbowPlanet/RainbowPlanet/Supporting Files/Assets.xcassets/TabbarIcons/photo_verybig.imageset/photo_verybig.png
  12. BIN
      RainbowPlanet/RainbowPlanet/Supporting Files/Assets.xcassets/TabbarIcons/photo_verybig.imageset/photo_verybig@2x.png
  13. 438 0
      RainbowPlanet/RainbowPlanet/Tools/ESTabBarController-swift/ESTabBar.swift
  14. 152 0
      RainbowPlanet/RainbowPlanet/Tools/ESTabBarController-swift/ESTabBarController.swift
  15. 107 0
      RainbowPlanet/RainbowPlanet/Tools/ESTabBarController-swift/ESTabBarItem.swift
  16. 116 0
      RainbowPlanet/RainbowPlanet/Tools/ESTabBarController-swift/ESTabBarItemBadgeView.swift
  17. 67 0
      RainbowPlanet/RainbowPlanet/Tools/ESTabBarController-swift/ESTabBarItemContainer.swift
  18. 394 0
      RainbowPlanet/RainbowPlanet/Tools/ESTabBarController-swift/ESTabBarItemContentView.swift
  19. 71 0
      RainbowPlanet/RainbowPlanet/Tools/ESTabBarController-swift/ESTabBarItemMoreContentView.swift
  20. 3 0
      RainbowPlanet/RainbowPlanet/Tools/ESTabBarController-swift/en.lproj/Localizable.strings

+ 2 - 2
RainbowPlanet/Podfile

@@ -42,12 +42,12 @@ target 'RainbowPlanet' do
 #  pod 'EFQRCode'
   # 小红点
   pod 'PPBadgeViewSwift'
+  # 动画效果
+  pod 'pop'
   # pop动画
   pod 'FWPopupView'
   # 存储数据Keychain
   pod 'KeychainAccess'
-  # TabBar
-  pod 'ESTabBarController-swift'
   # mvvm
 #  pod 'ReactorKit'
   # 富文本

+ 5 - 5
RainbowPlanet/Podfile.lock

@@ -4,7 +4,6 @@ PODS:
   - BMKLocationKit (1.5.0)
   - Cache (5.2.0)
   - DeviceKit (2.0.0)
-  - ESTabBarController-swift (2.7)
   - FMDB (2.7.5):
     - FMDB/standard (= 2.7.5)
   - FMDB/standard (2.7.5)
@@ -25,6 +24,7 @@ PODS:
     - Moya/Core
     - RxSwift (~> 4.0)
   - ObjectMapper (3.4.2)
+  - pop (1.0.12)
   - PPBadgeViewSwift (3.1.0)
   - Result (4.1.0)
   - RxCocoa (4.5.0):
@@ -60,7 +60,6 @@ DEPENDENCIES:
   - BMKLocationKit (= 1.5.0)
   - Cache
   - DeviceKit
-  - ESTabBarController-swift
   - FMDB
   - FSPagerView
   - FWPopupView
@@ -73,6 +72,7 @@ DEPENDENCIES:
   - MJRefresh
   - Moya/RxSwift
   - ObjectMapper
+  - pop
   - PPBadgeViewSwift
   - RxCocoa
   - RxSwift
@@ -95,7 +95,6 @@ SPEC REPOS:
     - BMKLocationKit
     - Cache
     - DeviceKit
-    - ESTabBarController-swift
     - FMDB
     - FSPagerView
     - FWPopupView
@@ -108,6 +107,7 @@ SPEC REPOS:
     - MJRefresh
     - Moya
     - ObjectMapper
+    - pop
     - PPBadgeViewSwift
     - Result
     - RxCocoa
@@ -127,7 +127,6 @@ SPEC CHECKSUMS:
   BMKLocationKit: 40d267478acd8704ddebd0e9deaddc727b13df9f
   Cache: 807c5d86d01a177f06ede9865add3aea269bbfd4
   DeviceKit: 72d36709552d4b3582abd76a53949148acad9811
-  ESTabBarController-swift: 4fb52ad03d94d0717ef97bc9eb09a5abfdded0a2
   FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
   FSPagerView: 816a18842306973cc7cc6df8a5332272f7815c30
   FWPopupView: 50e0db3245879b9b73552c897b17a215ac0f9199
@@ -140,6 +139,7 @@ SPEC CHECKSUMS:
   MJRefresh: ed450d6eb9d3346a2cb033ab7eb6de090aeef437
   Moya: f4a4b80ff2f8a4ffc208dfb31cd91636622fee6e
   ObjectMapper: 0d4402610f4e468903ae64629eec4784531e5c51
+  pop: d582054913807fd11fd50bfe6a539d91c7e1a55a
   PPBadgeViewSwift: 18a219a9897f418342c22dd1a54f7b18ac56546b
   Result: bd966fac789cc6c1563440b348ab2598cc24d5c7
   RxCocoa: cbf70265dc65a981d4ac982e513c10cf23df24a0
@@ -153,6 +153,6 @@ SPEC CHECKSUMS:
   UMCSecurityPlugins: 0831a08f3988f3cea9f1d3a7626cd9bee4fef150
   UMCShare: 552b29753f1b4da87b51d96545ed19e6263df397
 
-PODFILE CHECKSUM: 737295f2e7556094caab18f75bba749d0cfe3d55
+PODFILE CHECKSUM: ce904adbb6da37ca3145c2921469be1ffc5965e0
 
 COCOAPODS: 1.7.1

+ 100 - 1
RainbowPlanet/RainbowPlanet.xcodeproj/project.pbxproj

@@ -54,6 +54,7 @@
 		A71901692275464000104A50 /* ProvinceCityAreaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A71901682275464000104A50 /* ProvinceCityAreaView.swift */; };
 		A719016B22757A5A00104A50 /* ProvinceCityAreaTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A719016A22757A5A00104A50 /* ProvinceCityAreaTableViewCell.swift */; };
 		A71901752275F71F00104A50 /* BaiduToCityModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A71901742275F71F00104A50 /* BaiduToCityModel.swift */; };
+		A719EE6E22AF441F001AAC98 /* CommunityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A719EE6D22AF441F001AAC98 /* CommunityViewController.swift */; };
 		A71AA50C2272126A008FF1A5 /* EditAddressFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A71AA50B2272126A008FF1A5 /* EditAddressFooterView.swift */; };
 		A71AA5102272156A008FF1A5 /* ExpressAddressListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A71AA50F2272156A008FF1A5 /* ExpressAddressListViewController.swift */; };
 		A71AA513227215B5008FF1A5 /* ExpressAddressListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A71AA512227215B5008FF1A5 /* ExpressAddressListView.swift */; };
@@ -210,6 +211,17 @@
 		A7824B082271F53A00ABA381 /* EditSetDefaultTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7824B072271F53A00ABA381 /* EditSetDefaultTableViewCell.swift */; };
 		A79057022276C9770037F823 /* SetPasswordModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79057012276C9770037F823 /* SetPasswordModel.swift */; };
 		A79057062276EA3D0037F823 /* OpenCityListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79057052276EA3D0037F823 /* OpenCityListModel.swift */; };
+		A7931DEF22AF4C9100297D0A /* BaseBasicContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7931DEC22AF4C9100297D0A /* BaseBasicContentView.swift */; };
+		A7931DF022AF4C9100297D0A /* BaseBouncesContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7931DED22AF4C9100297D0A /* BaseBouncesContentView.swift */; };
+		A7931DF122AF4C9100297D0A /* BaseIrregularityBasicContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7931DEE22AF4C9100297D0A /* BaseIrregularityBasicContentView.swift */; };
+		A7931DFE22AF827600297D0A /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A7931DF522AF827600297D0A /* Localizable.strings */; };
+		A7931DFF22AF827600297D0A /* ESTabBarItemMoreContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7931DF722AF827600297D0A /* ESTabBarItemMoreContentView.swift */; };
+		A7931E0022AF827600297D0A /* ESTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7931DF822AF827600297D0A /* ESTabBarController.swift */; };
+		A7931E0122AF827600297D0A /* ESTabBarItemContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7931DF922AF827600297D0A /* ESTabBarItemContentView.swift */; };
+		A7931E0222AF827600297D0A /* ESTabBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7931DFA22AF827600297D0A /* ESTabBarItem.swift */; };
+		A7931E0322AF827600297D0A /* ESTabBarItemBadgeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7931DFB22AF827600297D0A /* ESTabBarItemBadgeView.swift */; };
+		A7931E0422AF827600297D0A /* ESTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7931DFC22AF827600297D0A /* ESTabBar.swift */; };
+		A7931E0522AF827600297D0A /* ESTabBarItemContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7931DFD22AF827600297D0A /* ESTabBarItemContainer.swift */; };
 		A7A17E5F22A0CEF200B7A77E /* SwiftMoyaNetWorkManagerTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7A17E5E22A0CEF200B7A77E /* SwiftMoyaNetWorkManagerTools.swift */; };
 		A7A98DFD227E84F4005306E9 /* SwiftMoyaServiceProductApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7A98DFC227E84F4005306E9 /* SwiftMoyaServiceProductApi.swift */; };
 		A7A98DFF227E8501005306E9 /* SwiftMoyaNetWorkServiceProduct.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7A98DFE227E8501005306E9 /* SwiftMoyaNetWorkServiceProduct.swift */; };
@@ -453,6 +465,7 @@
 		A71901682275464000104A50 /* ProvinceCityAreaView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProvinceCityAreaView.swift; sourceTree = "<group>"; };
 		A719016A22757A5A00104A50 /* ProvinceCityAreaTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProvinceCityAreaTableViewCell.swift; sourceTree = "<group>"; };
 		A71901742275F71F00104A50 /* BaiduToCityModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaiduToCityModel.swift; sourceTree = "<group>"; };
+		A719EE6D22AF441F001AAC98 /* CommunityViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommunityViewController.swift; sourceTree = "<group>"; };
 		A71AA50B2272126A008FF1A5 /* EditAddressFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditAddressFooterView.swift; sourceTree = "<group>"; };
 		A71AA50F2272156A008FF1A5 /* ExpressAddressListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpressAddressListViewController.swift; sourceTree = "<group>"; };
 		A71AA512227215B5008FF1A5 /* ExpressAddressListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpressAddressListView.swift; sourceTree = "<group>"; };
@@ -622,6 +635,17 @@
 		A7824B072271F53A00ABA381 /* EditSetDefaultTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditSetDefaultTableViewCell.swift; sourceTree = "<group>"; };
 		A79057012276C9770037F823 /* SetPasswordModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetPasswordModel.swift; sourceTree = "<group>"; };
 		A79057052276EA3D0037F823 /* OpenCityListModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenCityListModel.swift; sourceTree = "<group>"; };
+		A7931DEC22AF4C9100297D0A /* BaseBasicContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseBasicContentView.swift; sourceTree = "<group>"; };
+		A7931DED22AF4C9100297D0A /* BaseBouncesContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseBouncesContentView.swift; sourceTree = "<group>"; };
+		A7931DEE22AF4C9100297D0A /* BaseIrregularityBasicContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseIrregularityBasicContentView.swift; sourceTree = "<group>"; };
+		A7931DF622AF827600297D0A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
+		A7931DF722AF827600297D0A /* ESTabBarItemMoreContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ESTabBarItemMoreContentView.swift; sourceTree = "<group>"; };
+		A7931DF822AF827600297D0A /* ESTabBarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ESTabBarController.swift; sourceTree = "<group>"; };
+		A7931DF922AF827600297D0A /* ESTabBarItemContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ESTabBarItemContentView.swift; sourceTree = "<group>"; };
+		A7931DFA22AF827600297D0A /* ESTabBarItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ESTabBarItem.swift; sourceTree = "<group>"; };
+		A7931DFB22AF827600297D0A /* ESTabBarItemBadgeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ESTabBarItemBadgeView.swift; sourceTree = "<group>"; };
+		A7931DFC22AF827600297D0A /* ESTabBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ESTabBar.swift; sourceTree = "<group>"; };
+		A7931DFD22AF827600297D0A /* ESTabBarItemContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ESTabBarItemContainer.swift; sourceTree = "<group>"; };
 		A7A17E5E22A0CEF200B7A77E /* SwiftMoyaNetWorkManagerTools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftMoyaNetWorkManagerTools.swift; sourceTree = "<group>"; };
 		A7A59A7722363CCB00417FA4 /* RainbowPlanet.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RainbowPlanet.entitlements; sourceTree = "<group>"; };
 		A7A98DFC227E84F4005306E9 /* SwiftMoyaServiceProductApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftMoyaServiceProductApi.swift; sourceTree = "<group>"; };
@@ -1192,6 +1216,38 @@
 			path = BaiduToCityFactory;
 			sourceTree = "<group>";
 		};
+		A719EE6622AF4374001AAC98 /* CommunityModule */ = {
+			isa = PBXGroup;
+			children = (
+				A719EE6722AF438E001AAC98 /* Community */,
+			);
+			path = CommunityModule;
+			sourceTree = "<group>";
+		};
+		A719EE6722AF438E001AAC98 /* Community */ = {
+			isa = PBXGroup;
+			children = (
+				A719EE6922AF43EE001AAC98 /* View */,
+				A719EE6822AF4395001AAC98 /* ViewController */,
+			);
+			path = Community;
+			sourceTree = "<group>";
+		};
+		A719EE6822AF4395001AAC98 /* ViewController */ = {
+			isa = PBXGroup;
+			children = (
+				A719EE6D22AF441F001AAC98 /* CommunityViewController.swift */,
+			);
+			path = ViewController;
+			sourceTree = "<group>";
+		};
+		A719EE6922AF43EE001AAC98 /* View */ = {
+			isa = PBXGroup;
+			children = (
+			);
+			path = View;
+			sourceTree = "<group>";
+		};
 		A71AA50D22721537008FF1A5 /* ExpressAddressList */ = {
 			isa = PBXGroup;
 			children = (
@@ -2030,6 +2086,9 @@
 			isa = PBXGroup;
 			children = (
 				A77F2CC9223209F2001BD3F6 /* BaseTabbarViewController.swift */,
+				A7931DEC22AF4C9100297D0A /* BaseBasicContentView.swift */,
+				A7931DED22AF4C9100297D0A /* BaseBouncesContentView.swift */,
+				A7931DEE22AF4C9100297D0A /* BaseIrregularityBasicContentView.swift */,
 			);
 			path = BaseTabbarViewController;
 			sourceTree = "<group>";
@@ -2069,6 +2128,7 @@
 		A77F2CA22232010F001BD3F6 /* Modules */ = {
 			isa = PBXGroup;
 			children = (
+				A719EE6622AF4374001AAC98 /* CommunityModule */,
 				A77F2CAE2232010F001BD3F6 /* RegisterLoginModule */,
 				BD3AA45422AE635700EF4F20 /* MessageModule */,
 				A77F2CA92232010F001BD3F6 /* MineModule */,
@@ -2082,9 +2142,9 @@
 		A77F2CA32232010F001BD3F6 /* ShoppingMallModule */ = {
 			isa = PBXGroup;
 			children = (
+				A77F2CA42232010F001BD3F6 /* ShoppingMall */,
 				A77F2CB02232010F001BD3F6 /* ShoppingCart */,
 				A7DF50D922A556C300998908 /* BrowsePictures */,
-				A77F2CA42232010F001BD3F6 /* ShoppingMall */,
 				A7FF1550228AC22700A85748 /* ProductAllComment */,
 				A70B2C122286B14C00B2449F /* ProductView */,
 				A70B2C112286B10000B2449F /* ProductDetail */,
@@ -2194,6 +2254,7 @@
 		A77F2CBC2232022A001BD3F6 /* Tools */ = {
 			isa = PBXGroup;
 			children = (
+				A7931DF422AF827600297D0A /* ESTabBarController-swift */,
 				BD108C8D22A60A2000837DAB /* HGImagePicker */,
 				A7391212229F75F50033177E /* JXPagingView-Swift */,
 				A7146346228EFCE20066099B /* SKUDataFilter */,
@@ -2278,6 +2339,21 @@
 			path = SwiftMoyaServiceManger;
 			sourceTree = "<group>";
 		};
+		A7931DF422AF827600297D0A /* ESTabBarController-swift */ = {
+			isa = PBXGroup;
+			children = (
+				A7931DF522AF827600297D0A /* Localizable.strings */,
+				A7931DF722AF827600297D0A /* ESTabBarItemMoreContentView.swift */,
+				A7931DF822AF827600297D0A /* ESTabBarController.swift */,
+				A7931DF922AF827600297D0A /* ESTabBarItemContentView.swift */,
+				A7931DFA22AF827600297D0A /* ESTabBarItem.swift */,
+				A7931DFB22AF827600297D0A /* ESTabBarItemBadgeView.swift */,
+				A7931DFC22AF827600297D0A /* ESTabBar.swift */,
+				A7931DFD22AF827600297D0A /* ESTabBarItemContainer.swift */,
+			);
+			path = "ESTabBarController-swift";
+			sourceTree = "<group>";
+		};
 		A7A98DFB227E84D0005306E9 /* SwiftMoyaServiceProduct */ = {
 			isa = PBXGroup;
 			children = (
@@ -3285,6 +3361,7 @@
 				A7CC74DE22703B4A003C4F38 /* MineModule.xcassets in Resources */,
 				A70B2C2D2286E29900B2449F /* ProductModule.xcassets in Resources */,
 				A71AF0BE226F1792001730FE /* ShoppingMallModule.xcassets in Resources */,
+				A7931DFE22AF827600297D0A /* Localizable.strings in Resources */,
 				A7778C9722438F5D00C7C47A /* AlipaySDK.bundle in Resources */,
 				A7190167227543DB00104A50 /* baidu_cityid_rel.json in Resources */,
 				A77F2C682231FB4A001BD3F6 /* Assets.xcassets in Resources */,
@@ -3386,6 +3463,7 @@
 				BD20F1D52283D15500677D8E /* OrderFinishPayFailureCell.swift in Sources */,
 				A72A72C022321DE000B21995 /* Extension+UIView.swift in Sources */,
 				BD7AB83A2284288D0030646A /* ShoppingCartPayOrderFooter.swift in Sources */,
+				A719EE6E22AF441F001AAC98 /* CommunityViewController.swift in Sources */,
 				A72A72C522321DE000B21995 /* WKWebViewConfig.swift in Sources */,
 				A72A72BB22321DE000B21995 /* Extension+UILabel.swift in Sources */,
 				A70B2C372288177300B2449F /* ProductDetailProductLabelIconCollectionViewCell.swift in Sources */,
@@ -3413,6 +3491,7 @@
 				A7B4E738228191CC0012914A /* CommondModel.swift in Sources */,
 				BD7AB841228438C80030646A /* OrderPaySelfPickAddressCell.swift in Sources */,
 				BDF862AC228E5112000DEF84 /* OrderCommentAddImgCollectionCell.swift in Sources */,
+				A7931E0222AF827600297D0A /* ESTabBarItem.swift in Sources */,
 				A7CC74D4226FF1AA003C4F38 /* MineView.swift in Sources */,
 				A71AA5152272160A008FF1A5 /* ExpressAddressListTableViewCell.swift in Sources */,
 				A72A72B722321DE000B21995 /* Extension+NSMutableAttributedString.swift in Sources */,
@@ -3430,6 +3509,7 @@
 				A7CC74D822700359003C4F38 /* MineTableViewHeaderView.swift in Sources */,
 				A71D2A602265673A00A55D16 /* RegisterLoginView.swift in Sources */,
 				A73D7C682268A032002A4CE3 /* SwiftyStarRatingView.swift in Sources */,
+				A7931E0122AF827600297D0A /* ESTabBarItemContentView.swift in Sources */,
 				A71AA5102272156A008FF1A5 /* ExpressAddressListViewController.swift in Sources */,
 				BDAA40FF228EA37900CF841D /* OrderApplyRefundPhotoCell.swift in Sources */,
 				A7A98E14227ED0E2005306E9 /* CategoryListModel.swift in Sources */,
@@ -3449,6 +3529,7 @@
 				A71AF0B0226EF185001730FE /* SearchCollectionViewCell.swift in Sources */,
 				A7A98E1D227EF1CB005306E9 /* SpecialBannerView.swift in Sources */,
 				BDF47D852282C59F00941AB9 /* ShoppingCartListTableViewCell.swift in Sources */,
+				A7931DFF22AF827600297D0A /* ESTabBarItemMoreContentView.swift in Sources */,
 				A77F2CCA223209F2001BD3F6 /* BaseTabbarViewController.swift in Sources */,
 				A70B2C1D2286B52400B2449F /* ProductDetailViewController.swift in Sources */,
 				A7CC75332271ABB0003C4F38 /* AddressManagerViewController.swift in Sources */,
@@ -3462,6 +3543,7 @@
 				A729B5B022671310004AE098 /* MobileLoginView.swift in Sources */,
 				A71AA50C2272126A008FF1A5 /* EditAddressFooterView.swift in Sources */,
 				A70B2C35228815F700B2449F /* ProductDetailProductSkuLabelCollectionViewCell.swift in Sources */,
+				A7931E0522AF827600297D0A /* ESTabBarItemContainer.swift in Sources */,
 				A70B2C60228870CE00B2449F /* ShopSectionHeaderView.swift in Sources */,
 				A7CC7528227196C4003C4F38 /* AccountSecuritySetTableViewCell.swift in Sources */,
 				A70B2C292286D77200B2449F /* ProductDetailProductInfoTableViewCell.swift in Sources */,
@@ -3493,11 +3575,13 @@
 				A7003EA3229192CC004E51FB /* PayManagerPay.swift in Sources */,
 				A7DC467F22783A47001F3EFC /* EditExpressAddressTableViewCell.swift in Sources */,
 				A7A98E4522804C63005306E9 /* ShoppingMallSepcialCollectionViewCell.swift in Sources */,
+				A7931E0022AF827600297D0A /* ESTabBarController.swift in Sources */,
 				A7824B082271F53A00ABA381 /* EditSetDefaultTableViewCell.swift in Sources */,
 				A77F2CC3223203BA001BD3F6 /* AppDelegate+Window.swift in Sources */,
 				A7824B062271F25400ABA381 /* EditAddressTableViewCell.swift in Sources */,
 				A70B2C4C228845E800B2449F /* ProductDetailParameterTableViewCell.swift in Sources */,
 				A7FF156A228C6E3600A85748 /* OrderProductTableViewCell.swift in Sources */,
+				A7931DF022AF4C9100297D0A /* BaseBouncesContentView.swift in Sources */,
 				A715333E22980CC60017C861 /* ConfigModel.swift in Sources */,
 				A70EBBC022561179000AD74F /* Extension+UITableView.swift in Sources */,
 				A72A72B022321DE000B21995 /* CGView.swift in Sources */,
@@ -3528,6 +3612,8 @@
 				A70B2C75228920BA00B2449F /* ProductDetailSkuSectionHeaerCollectionReusableView.swift in Sources */,
 				A7DF50D822A4FAFC00998908 /* ProductDetailEvaluationImageCollectionViewCell.swift in Sources */,
 				A72843FC224DB6B800F82F30 /* SwiftMoyaServiceUserApi.swift in Sources */,
+				A7931DF122AF4C9100297D0A /* BaseIrregularityBasicContentView.swift in Sources */,
+				A7931DEF22AF4C9100297D0A /* BaseBasicContentView.swift in Sources */,
 				A7CC750622714306003C4F38 /* MessageNoticeHeaderCollectionReusableView.swift in Sources */,
 				A7C3DD1A226422BF00FA262E /* SwiftMoyaServiceSMSApi.swift in Sources */,
 				A7284A7722547333000BAEC4 /* AlipayResultModel.swift in Sources */,
@@ -3608,7 +3694,9 @@
 				A72A72BC22321DE000B21995 /* Extension+UIAlertController.swift in Sources */,
 				A7BB68662269B1DD00AB07A2 /* AddressPOIView.swift in Sources */,
 				BDF862A7228E42FA000DEF84 /* OrderApplyRefundController.swift in Sources */,
+				A7931E0422AF827600297D0A /* ESTabBar.swift in Sources */,
 				A72A72C322321DE000B21995 /* Extension+Date.swift in Sources */,
+				A7931E0322AF827600297D0A /* ESTabBarItemBadgeView.swift in Sources */,
 				A70B2C5522885AF500B2449F /* ShareCollectionViewCell.swift in Sources */,
 				A7A98E3A2280312C005306E9 /* ShoppingMallCategoryTableViewCell.swift in Sources */,
 				A7778CAB2244B12500C7C47A /* CountDownManager.swift in Sources */,
@@ -3759,6 +3847,17 @@
 		};
 /* End PBXTargetDependency section */
 
+/* Begin PBXVariantGroup section */
+		A7931DF522AF827600297D0A /* Localizable.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				A7931DF622AF827600297D0A /* en */,
+			);
+			name = Localizable.strings;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
 /* Begin XCBuildConfiguration section */
 		A77F2C832231FB4A001BD3F6 /* Debug */ = {
 			isa = XCBuildConfiguration;

+ 25 - 0
RainbowPlanet/RainbowPlanet/Base/BaseTabbarViewController/BaseBasicContentView.swift

@@ -0,0 +1,25 @@
+//
+//  BaseBasicContentView.swift
+//  ReceptionHall
+//
+//  Created by 南鑫林 on 2019/4/10.
+//  Copyright © 2019 南鑫林. All rights reserved.
+//
+
+import UIKit
+
+class BaseBasicContentView: ESTabBarItemContentView {
+
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        textColor = kTabbarNormalColor
+        highlightTextColor = kTabbarSelectColor
+        backdropColor = kffffffColor
+        highlightBackdropColor = kffffffColor
+    }
+
+    public required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+}

+ 40 - 0
RainbowPlanet/RainbowPlanet/Base/BaseTabbarViewController/BaseBouncesContentView.swift

@@ -0,0 +1,40 @@
+//
+//  BaseBouncesContentView.swift
+//  ReceptionHall
+//
+//  Created by 南鑫林 on 2019/4/10.
+//  Copyright © 2019 南鑫林. All rights reserved.
+//
+
+import UIKit
+
+class BaseBouncesContentView: BaseBasicContentView {
+    public var duration = 0.3
+
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+    }
+
+    public required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    override func selectAnimation(animated: Bool, completion: (() -> ())?) {
+        self.bounceAnimation()
+        completion?()
+    }
+
+    override func reselectAnimation(animated: Bool, completion: (() -> ())?) {
+        self.bounceAnimation()
+        completion?()
+    }
+
+    func bounceAnimation() {
+        let impliesAnimation = CAKeyframeAnimation(keyPath: "transform.scale")
+        impliesAnimation.values = [1.0 ,1.4, 0.9, 1.15, 0.95, 1.02, 1.0]
+        impliesAnimation.duration = duration * 2
+        impliesAnimation.calculationMode = CAAnimationCalculationMode.cubic
+        imageView.layer.add(impliesAnimation, forKey: nil)
+    }
+
+}

+ 118 - 0
RainbowPlanet/RainbowPlanet/Base/BaseTabbarViewController/BaseIrregularityBasicContentView.swift

@@ -0,0 +1,118 @@
+//
+//  BaseIrregularityContentView.swift
+//  ReceptionHall
+//
+//  Created by 南鑫林 on 2019/4/10.
+//  Copyright © 2019 南鑫林. All rights reserved.
+//
+
+import UIKit
+import pop
+
+class BaseIrregularityBasicContentView: BaseBouncesContentView {
+
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        
+    }
+
+    public required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+}
+
+class BaseIrregularityContentView: ESTabBarItemContentView {
+
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+
+        self.insets = UIEdgeInsets.init(top: 0, left: 0, bottom: -(kTabBarTotalHeight-kSafeTabBarHeight-42)/2, right: 0)
+        let transform = CGAffineTransform.identity
+        self.imageView.transform = transform
+        self.superview?.bringSubviewToFront(self)
+        itemContentMode = .alwaysOriginal
+
+    }
+
+    public required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
+        let p = CGPoint.init(x: point.x - imageView.frame.origin.x, y: point.y - imageView.frame.origin.y)
+        return sqrt(pow(imageView.bounds.size.width / 2.0 - p.x, 2) + pow(imageView.bounds.size.height / 2.0 - p.y, 2)) < imageView.bounds.size.width / 2.0
+    }
+
+    override func updateLayout() {
+        super.updateLayout()
+        self.imageView.sizeToFit()
+        self.imageView.center = CGPoint.init(x: self.bounds.size.width / 2.0, y: self.bounds.size.height / 2.0)
+    }
+
+    public override func selectAnimation(animated: Bool, completion: (() -> ())?) {
+        let view = UIView.init(frame: CGRect.init(origin: CGPoint.zero, size: CGSize(width: 2.0, height: 2.0)))
+        view.layer.cornerRadius = 1.0
+        view.layer.opacity = 0.5
+        view.backgroundColor = UIColor.init(red: 10/255.0, green: 66/255.0, blue: 91/255.0, alpha: 1.0)
+        self.addSubview(view)
+        playMaskAnimation(animateView: view, target: self.imageView, completion: {
+            [weak view] in
+            view?.removeFromSuperview()
+            completion?()
+        })
+    }
+
+    public override func reselectAnimation(animated: Bool, completion: (() -> ())?) {
+        completion?()
+    }
+
+    public override func deselectAnimation(animated: Bool, completion: (() -> ())?) {
+        completion?()
+    }
+
+    public override func highlightAnimation(animated: Bool, completion: (() -> ())?) {
+        UIView.beginAnimations("small", context: nil)
+        UIView.setAnimationDuration(0.2)
+        let transform = self.imageView.transform.scaledBy(x: 0.8, y: 0.8)
+        self.imageView.transform = transform
+        UIView.commitAnimations()
+        completion?()
+    }
+
+    public override func dehighlightAnimation(animated: Bool, completion: (() -> ())?) {
+        UIView.beginAnimations("big", context: nil)
+        UIView.setAnimationDuration(0.2)
+        let transform = CGAffineTransform.identity
+        self.imageView.transform = transform
+        UIView.commitAnimations()
+        completion?()
+    }
+
+    private func playMaskAnimation(animateView view: UIView, target: UIView, completion: (() -> ())?) {
+        view.center = CGPoint.init(x: target.frame.origin.x + target.frame.size.width / 2.0, y: target.frame.origin.y + target.frame.size.height / 2.0)
+
+        let scale = POPBasicAnimation.init(propertyNamed: kPOPLayerScaleXY)
+        scale?.fromValue = NSValue.init(cgSize: CGSize.init(width: 1.0, height: 1.0))
+        scale?.toValue = NSValue.init(cgSize: CGSize.init(width: 36.0, height: 36.0))
+        scale?.beginTime = CACurrentMediaTime()
+        scale?.duration = 0.3
+        scale?.timingFunction = CAMediaTimingFunction.init(name: CAMediaTimingFunctionName.easeOut)
+        scale?.removedOnCompletion = true
+
+        let alpha = POPBasicAnimation.init(propertyNamed: kPOPLayerOpacity)
+        alpha?.fromValue = 0.6
+        alpha?.toValue = 0.6
+        alpha?.beginTime = CACurrentMediaTime()
+        alpha?.duration = 0.25
+        alpha?.timingFunction = CAMediaTimingFunction.init(name: CAMediaTimingFunctionName.easeOut)
+        alpha?.removedOnCompletion = true
+
+        view.layer.pop_add(scale, forKey: "scale")
+        view.layer.pop_add(alpha, forKey: "alpha")
+
+        scale?.completionBlock = ({ animation, finished in
+            completion?()
+        })
+    }
+
+}

+ 41 - 22
RainbowPlanet/RainbowPlanet/Base/BaseTabbarViewController/BaseTabbarViewController.swift

@@ -8,7 +8,7 @@
 
 import UIKit
 
-class BaseTabbarViewController: UITabBarController {
+class BaseTabbarViewController: ESTabBarController {
     private static let _sharedInstance = BaseTabbarViewController()
 
     class func shared() -> BaseTabbarViewController {
@@ -20,32 +20,51 @@ class BaseTabbarViewController: UITabBarController {
 
         // Do any additional setup after loading the view.
     }
+    
+    func tabBarViewController() -> ESTabBarController {
+        let tabBarViewController = ESTabBarController()
+        
+        tabBarViewController.tabBar.shadowImage = UIImage(named: "tab_top_line")
+        
+        tabBarViewController.shouldHijackHandler = {
+            tabbarController, viewController, index in
+            if index == 2 {
+                return true
+            }
+            return false
+        }
+        
+        tabBarViewController.didHijackHandler = {
+            tabbarController, viewController, index in
 
-    func tabBarViewController() -> BaseTabbarViewController {
-        let tabBarViewController = BaseTabbarViewController()
-
-        let v1 = ShoppingMallViewController()
-        let v2 = ShoppingCartViewController()
-        let v3 = MineViewController()
-
+        }
+        
+        /// 社区
+        let v1 = CommunityViewController()
+        /// 商城
+        let v2 = ShoppingMallViewController()
+        /// 发布
+        let v3 = UIViewController()
+        /// 消息
+        let v4 = MessageMainViewController()
+        /// 我的
+        let v5 = MineViewController()
+        
+        v1.tabBarItem = ESTabBarItem.init(BaseIrregularityBasicContentView(),title: "社区", image: UIImage(named: "tabbar_home"), selectedImage: UIImage(named: "tabbar_home_pre"))
+        v2.tabBarItem = ESTabBarItem.init(BaseIrregularityBasicContentView(),title: "商城", image: UIImage(named: "tabbar_home"), selectedImage: UIImage(named: "tabbar_home_pre"))
+        v3.tabBarItem = ESTabBarItem.init(BaseIrregularityContentView(), title: nil, image: UIImage(named: "photo_verybig"), selectedImage: UIImage(named: "photo_verybig"))
+        v4.tabBarItem = ESTabBarItem.init(BaseIrregularityBasicContentView(),title: "消息", image: UIImage(named: "tabbar_shopping"), selectedImage: UIImage(named: "tabbar_shopping_pre"))
+        v5.tabBarItem = ESTabBarItem.init(BaseIrregularityBasicContentView(),title: "我的", image: UIImage(named: "tabbar_my"), selectedImage: UIImage(named: "tabbar_my_pre"))
+        
         let n1 = BaseNavigationViewController.init(rootViewController: v1)
         let n2 = BaseNavigationViewController.init(rootViewController: v2)
         let n3 = BaseNavigationViewController.init(rootViewController: v3)
-
-        tabBarItemStyle(navc: n1, normalImg: "tabbar_home", selectorImg: "tabbar_home_pre", title: "首页")
-        tabBarItemStyle(navc: n2, normalImg: "tabbar_shopping", selectorImg: "tabbar_shopping_pre", title: "购物车")
-        tabBarItemStyle(navc: n3, normalImg: "tabbar_my", selectorImg: "tabbar_my_pre", title: "我的彩虹")
-
-        tabBarViewController.viewControllers = [n1, n2, n3]
+        let n4 = BaseNavigationViewController.init(rootViewController: v4)
+        let n5 = BaseNavigationViewController.init(rootViewController: v5)
+        
+        tabBarViewController.viewControllers = [n1, n2, n3, n4, n5]
+        
         return tabBarViewController
     }
 
-
-    private func tabBarItemStyle(navc : UINavigationController, normalImg : String, selectorImg : String, title : String){
-        navc.tabBarItem = UITabBarItem.init(title: title, image: UIImage(named:normalImg), selectedImage: UIImage(named:selectorImg))
-        navc.tabBarItem.setTitleTextAttributes([NSAttributedString.Key.foregroundColor:k333333Color], for: UIControl.State.normal)
-        navc.tabBarItem.setTitleTextAttributes([NSAttributedString.Key.foregroundColor:k333333Color], for: UIControl.State.selected)
-
-    }
-
 }

+ 16 - 15
RainbowPlanet/RainbowPlanet/Macro/ColorMacro.swift

@@ -7,35 +7,38 @@
 //
 
 import UIKit
-//主题色 导航栏颜色 
-let kNavBgColor = UIColor(hexString: "2d96ee")
 
-let kTabbarSelectColor = UIColor(hexString: "2d96ee")
+let kThemeColor = UIColor(hexString: "FFA42F")
 
-let kTabbarNormalColor = UIColor(hexString: "b1d3f1")
+let kTabbarSelectColor = UIColor(hexString: "FFA42F")
 
-let kDisabledButtonColor = UIColor(hexString: "#E6E6E6")
+let kTabbarNormalColor = UIColor(hexString: "333333")
 
-let kDisabledTitleColor = UIColor(hexString: "#666666")
+let kDisabledButtonColor = UIColor(hexString: "E6E6E6")
 
-let kEnabledButtonColor = UIColor(hexString: "#FFA42F")
+let kDisabledTitleColor = UIColor(hexString: "666666")
 
-let kEnabledTitleColor = UIColor(hexString: "#FFFFFF")
+let kEnabledButtonColor = UIColor(hexString: "FFA42F")
 
-let k333333Color = UIColor(hexString: "333333")
-
-let kE6E6E6Color = UIColor(hexString: "E6E6E6")
+let kEnabledTitleColor = UIColor(hexString: "FFFFFF")
 
-let k404040Color = UIColor(hexString: "404040")
 
-let kFE352BColor = UIColor(hexString: "FE352B")
+let k333333Color = UIColor(hexString: "333333")
 
 let k666666Color = UIColor(hexString: "666666")
 
 let k999999Color = UIColor(hexString: "999999")
 
+let kffffffColor = UIColor(hexString: "ffffff")
+
 let keeeeeeColor = UIColor(hexString: "eeeeee")
 
+let kE6E6E6Color = UIColor(hexString: "E6E6E6")
+
+let k404040Color = UIColor(hexString: "404040")
+
+let kFE352BColor = UIColor(hexString: "FE352B")
+
 let kED3934Color = UIColor(hexString: "ED3934")
 
 let ke6e6e6Color = UIColor(hexString: "e6e6e6")
@@ -48,8 +51,6 @@ let kd8d8d8Color = UIColor(hexString: "d8d8d8")
 
 let kd9d9d9Color = UIColor(hexString: "d9d9d9")
 
-let kffffffColor = UIColor(hexString: "ffffff")
-
 let kff630fColor = UIColor(hexString: "ff630f")
 
 let kff8400Color = UIColor(hexString: "ff8400")

+ 29 - 0
RainbowPlanet/RainbowPlanet/Modules/CommunityModule/Community/ViewController/CommunityViewController.swift

@@ -0,0 +1,29 @@
+//
+//  CommunityViewController.swift
+//  RainbowPlanet
+//
+//  Created by 南鑫林 on 2019/6/11.
+//  Copyright © 2019 RainbowPlanet. All rights reserved.
+//  社区首页
+
+import UIKit
+
+class CommunityViewController: BaseViewController {
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+    }
+    
+    override func setupViews() {
+        
+    }
+    
+    override func setupLayouts() {
+        
+    }
+    
+    override func setupData() {
+        
+    }
+    
+}

+ 22 - 0
RainbowPlanet/RainbowPlanet/Supporting Files/Assets.xcassets/TabbarIcons/photo_verybig.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "photo_verybig.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "photo_verybig@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

BIN
RainbowPlanet/RainbowPlanet/Supporting Files/Assets.xcassets/TabbarIcons/photo_verybig.imageset/photo_verybig.png


BIN
RainbowPlanet/RainbowPlanet/Supporting Files/Assets.xcassets/TabbarIcons/photo_verybig.imageset/photo_verybig@2x.png


+ 438 - 0
RainbowPlanet/RainbowPlanet/Tools/ESTabBarController-swift/ESTabBar.swift

@@ -0,0 +1,438 @@
+//
+//  ESTabBar.swift
+//
+//  Created by Vincent Li on 2017/2/8.
+//  Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import UIKit
+
+
+/// 对原生的UITabBarItemPositioning进行扩展,通过UITabBarItemPositioning设置时,系统会自动添加insets,这使得添加背景样式的需求变得不可能实现。ESTabBarItemPositioning完全支持原有的item Position 类型,除此之外还支持完全fill模式。
+///
+/// - automatic: UITabBarItemPositioning.automatic
+/// - fill: UITabBarItemPositioning.fill
+/// - centered: UITabBarItemPositioning.centered
+/// - fillExcludeSeparator: 完全fill模式,布局不覆盖tabBar顶部分割线
+/// - fillIncludeSeparator: 完全fill模式,布局覆盖tabBar顶部分割线
+public enum ESTabBarItemPositioning : Int {
+    
+    case automatic
+    
+    case fill
+    
+    case centered
+    
+    case fillExcludeSeparator
+    
+    case fillIncludeSeparator
+}
+
+
+
+/// 对UITabBarDelegate进行扩展,以支持UITabBarControllerDelegate的相关方法桥接
+internal protocol ESTabBarDelegate: NSObjectProtocol {
+
+    /// 当前item是否支持选中
+    ///
+    /// - Parameters:
+    ///   - tabBar: tabBar
+    ///   - item: 当前item
+    /// - Returns: Bool
+    func tabBar(_ tabBar: UITabBar, shouldSelect item: UITabBarItem) -> Bool
+    
+    /// 当前item是否需要被劫持
+    ///
+    /// - Parameters:
+    ///   - tabBar: tabBar
+    ///   - item: 当前item
+    /// - Returns: Bool
+    func tabBar(_ tabBar: UITabBar, shouldHijack item: UITabBarItem) -> Bool
+    
+    /// 当前item的点击被劫持
+    ///
+    /// - Parameters:
+    ///   - tabBar: tabBar
+    ///   - item: 当前item
+    /// - Returns: Void
+    func tabBar(_ tabBar: UITabBar, didHijack item: UITabBarItem)
+}
+
+
+
+/// ESTabBar是高度自定义的UITabBar子类,通过添加UIControl的方式实现自定义tabBarItem的效果。目前支持tabBar的大部分属性的设置,例如delegate,items,selectedImge,itemPositioning,itemWidth,itemSpacing等,以后会更加细致的优化tabBar原有属性的设置效果。
+open class ESTabBar: UITabBar {
+
+    internal weak var customDelegate: ESTabBarDelegate?
+    
+    /// tabBar中items布局偏移量
+    public var itemEdgeInsets = UIEdgeInsets.zero
+    /// 是否设置为自定义布局方式,默认为空。如果为空,则通过itemPositioning属性来设置。如果不为空则忽略itemPositioning,所以当tabBar的itemCustomPositioning属性不为空时,如果想改变布局规则,请设置此属性而非itemPositioning。
+    public var itemCustomPositioning: ESTabBarItemPositioning? {
+        didSet {
+            if let itemCustomPositioning = itemCustomPositioning {
+                switch itemCustomPositioning {
+                case .fill:
+                    itemPositioning = .fill
+                case .automatic:
+                    itemPositioning = .automatic
+                case .centered:
+                    itemPositioning = .centered
+                default:
+                    break
+                }
+            }
+            self.reload()
+        }
+    }
+    /// tabBar自定义item的容器view
+    internal var containers = [ESTabBarItemContainer]()
+    /// 缓存当前tabBarController用来判断是否存在"More"Tab
+    internal weak var tabBarController: UITabBarController?
+    /// 自定义'More'按钮样式,继承自ESTabBarItemContentView
+    open var moreContentView: ESTabBarItemContentView? = ESTabBarItemMoreContentView.init() {
+        didSet { self.reload() }
+    }
+    
+    open override var items: [UITabBarItem]? {
+        didSet {
+            self.reload()
+        }
+    }
+    
+    open var isEditing: Bool = false {
+        didSet {
+            if oldValue != isEditing {
+                self.updateLayout()
+            }
+        }
+    }
+    
+    open override func setItems(_ items: [UITabBarItem]?, animated: Bool) {
+        super.setItems(items, animated: animated)
+        self.reload()
+    }
+    
+    open override func beginCustomizingItems(_ items: [UITabBarItem]) {
+        ESTabBarController.printError("beginCustomizingItems(_:) is unsupported in ESTabBar.")
+        super.beginCustomizingItems(items)
+    }
+    
+    open override func endCustomizing(animated: Bool) -> Bool {
+        ESTabBarController.printError("endCustomizing(_:) is unsupported in ESTabBar.")
+        return super.endCustomizing(animated: animated)
+    }
+    
+    open override func layoutSubviews() {
+        super.layoutSubviews()
+        self.updateLayout()
+    }
+    
+    open override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
+        var b = super.point(inside: point, with: event)
+        if !b {
+            for container in containers {
+                if container.point(inside: CGPoint.init(x: point.x - container.frame.origin.x, y: point.y - container.frame.origin.y), with: event) {
+                    b = true
+                }
+            }
+        }
+        return b
+    }
+    
+}
+
+internal extension ESTabBar /* Layout */ {
+    
+    func updateLayout() {
+        guard let tabBarItems = self.items else {
+            ESTabBarController.printError("empty items")
+            return
+        }
+        
+        let tabBarButtons = subviews.filter { subview -> Bool in
+            if let cls = NSClassFromString("UITabBarButton") {
+                return subview.isKind(of: cls)
+            }
+            return false
+            } .sorted { (subview1, subview2) -> Bool in
+                return subview1.frame.origin.x < subview2.frame.origin.x
+        }
+        
+        if isCustomizing {
+            for (idx, _) in tabBarItems.enumerated() {
+                tabBarButtons[idx].isHidden = false
+                moreContentView?.isHidden = true
+            }
+            for (_, container) in containers.enumerated(){
+                container.isHidden = true
+            }
+        } else {
+            for (idx, item) in tabBarItems.enumerated() {
+                if let _ = item as? ESTabBarItem {
+                    tabBarButtons[idx].isHidden = true
+                } else {
+                    tabBarButtons[idx].isHidden = false
+                }
+                if isMoreItem(idx), let _ = moreContentView {
+                    tabBarButtons[idx].isHidden = true
+                }
+            }
+            for (_, container) in containers.enumerated(){
+                container.isHidden = false
+            }
+        }
+        
+        var layoutBaseSystem = true
+        if let itemCustomPositioning = itemCustomPositioning {
+            switch itemCustomPositioning {
+            case .fill, .automatic, .centered:
+                break
+            case .fillIncludeSeparator, .fillExcludeSeparator:
+                layoutBaseSystem = false
+            }
+        }
+        
+        if layoutBaseSystem {
+            // System itemPositioning
+            for (idx, container) in containers.enumerated(){
+                if !tabBarButtons[idx].frame.isEmpty {
+                    container.frame = tabBarButtons[idx].frame
+                }
+            }
+        } else {
+            // Custom itemPositioning
+            var x: CGFloat = itemEdgeInsets.left
+            var y: CGFloat = itemEdgeInsets.top
+            switch itemCustomPositioning! {
+            case .fillExcludeSeparator:
+                if y <= 0.0 {
+                    y += 1.0
+                }
+            default:
+                break
+            }
+            let width = bounds.size.width - itemEdgeInsets.left - itemEdgeInsets.right
+            let height = bounds.size.height - y - itemEdgeInsets.bottom
+            let eachWidth = itemWidth == 0.0 ? width / CGFloat(containers.count) : itemWidth
+            let eachSpacing = itemSpacing == 0.0 ? 0.0 : itemSpacing
+            
+            for container in containers {
+                container.frame = CGRect.init(x: x, y: y, width: eachWidth, height: height)
+                x += eachWidth
+                x += eachSpacing
+            }
+        }
+    }
+}
+
+internal extension ESTabBar /* Actions */ {
+    
+    func isMoreItem(_ index: Int) -> Bool {
+        return ESTabBarController.isShowingMore(tabBarController) && (index == (items?.count ?? 0) - 1)
+    }
+    
+    func removeAll() {
+        for container in containers {
+            container.removeFromSuperview()
+        }
+        containers.removeAll()
+    }
+    
+    func reload() {
+        removeAll()
+        guard let tabBarItems = self.items else {
+            ESTabBarController.printError("empty items")
+            return
+        }
+        for (idx, item) in tabBarItems.enumerated() {
+            let container = ESTabBarItemContainer.init(self, tag: 1000 + idx)
+            self.addSubview(container)
+            self.containers.append(container)
+            
+            if let item = item as? ESTabBarItem, let contentView = item.contentView {
+                container.addSubview(contentView)
+            }
+            if self.isMoreItem(idx), let moreContentView = moreContentView {
+                container.addSubview(moreContentView)
+            }
+        }
+        
+        self.updateAccessibilityLabels()
+        self.setNeedsLayout()
+    }
+    
+    @objc func highlightAction(_ sender: AnyObject?) {
+        guard let container = sender as? ESTabBarItemContainer else {
+            return
+        }
+        let newIndex = max(0, container.tag - 1000)
+        guard newIndex < items?.count ?? 0, let item = self.items?[newIndex], item.isEnabled == true else {
+            return
+        }
+        
+        if (customDelegate?.tabBar(self, shouldSelect: item) ?? true) == false {
+            return
+        }
+        
+        if let item = item as? ESTabBarItem {
+            item.contentView?.highlight(animated: true, completion: nil)
+        } else if self.isMoreItem(newIndex) {
+            moreContentView?.highlight(animated: true, completion: nil)
+        }
+    }
+    
+    @objc func dehighlightAction(_ sender: AnyObject?) {
+        guard let container = sender as? ESTabBarItemContainer else {
+            return
+        }
+        let newIndex = max(0, container.tag - 1000)
+        guard newIndex < items?.count ?? 0, let item = self.items?[newIndex], item.isEnabled == true else {
+            return
+        }
+        
+        if (customDelegate?.tabBar(self, shouldSelect: item) ?? true) == false {
+            return
+        }
+        
+        if let item = item as? ESTabBarItem {
+            item.contentView?.dehighlight(animated: true, completion: nil)
+        } else if self.isMoreItem(newIndex) {
+            moreContentView?.dehighlight(animated: true, completion: nil)
+        }
+    }
+    
+    @objc func selectAction(_ sender: AnyObject?) {
+        guard let container = sender as? ESTabBarItemContainer else {
+            return
+        }
+        select(itemAtIndex: container.tag - 1000, animated: true)
+    }
+    
+    @objc func select(itemAtIndex idx: Int, animated: Bool) {
+        let newIndex = max(0, idx)
+        let currentIndex = (selectedItem != nil) ? (items?.firstIndex(of: selectedItem!) ?? -1) : -1
+        guard newIndex < items?.count ?? 0, let item = self.items?[newIndex], item.isEnabled == true else {
+            return
+        }
+        
+        if (customDelegate?.tabBar(self, shouldSelect: item) ?? true) == false {
+            return
+        }
+        
+        if (customDelegate?.tabBar(self, shouldHijack: item) ?? false) == true {
+            customDelegate?.tabBar(self, didHijack: item)
+            if animated {
+                if let item = item as? ESTabBarItem {
+                    item.contentView?.select(animated: animated, completion: {
+                        item.contentView?.deselect(animated: false, completion: nil)
+                    })
+                } else if self.isMoreItem(newIndex) {
+                    moreContentView?.select(animated: animated, completion: {
+                        self.moreContentView?.deselect(animated: animated, completion: nil)
+                    })
+                }
+            }
+            return
+        }
+        
+        if currentIndex != newIndex {
+            if currentIndex != -1 && currentIndex < items?.count ?? 0{
+                if let currentItem = items?[currentIndex] as? ESTabBarItem {
+                    currentItem.contentView?.deselect(animated: animated, completion: nil)
+                } else if self.isMoreItem(currentIndex) {
+                    moreContentView?.deselect(animated: animated, completion: nil)
+                }
+            }
+            if let item = item as? ESTabBarItem {
+                item.contentView?.select(animated: animated, completion: nil)
+            } else if self.isMoreItem(newIndex) {
+                moreContentView?.select(animated: animated, completion: nil)
+            }
+        } else if currentIndex == newIndex {
+            if let item = item as? ESTabBarItem {
+                item.contentView?.reselect(animated: animated, completion: nil)
+            } else if self.isMoreItem(newIndex) {
+                moreContentView?.reselect(animated: animated, completion: nil)
+            }
+            
+            if let tabBarController = tabBarController {
+                var navVC: UINavigationController?
+                if let n = tabBarController.selectedViewController as? UINavigationController {
+                    navVC = n
+                } else if let n = tabBarController.selectedViewController?.navigationController {
+                    navVC = n
+                }
+                
+                if let navVC = navVC {
+                    if navVC.viewControllers.contains(tabBarController) {
+                        if navVC.viewControllers.count > 1 && navVC.viewControllers.last != tabBarController {
+                            navVC.popToViewController(tabBarController, animated: true);
+                        }
+                    } else {
+                        if navVC.viewControllers.count > 1 {
+                            navVC.popToRootViewController(animated: animated)
+                        }
+                    }
+                }
+            
+            }
+        }
+        
+        delegate?.tabBar?(self, didSelect: item)
+        self.updateAccessibilityLabels()
+    }
+    
+    func updateAccessibilityLabels() {
+        guard let tabBarItems = self.items, tabBarItems.count == self.containers.count else {
+            return
+        }
+        
+        for (idx, item) in tabBarItems.enumerated() {
+            let container = self.containers[idx]
+            container.accessibilityIdentifier = item.accessibilityIdentifier
+            container.accessibilityTraits = item.accessibilityTraits
+            
+            if item == selectedItem {
+                container.accessibilityTraits = container.accessibilityTraits.union(.selected)
+            }
+            
+            if let explicitLabel = item.accessibilityLabel {
+                container.accessibilityLabel = explicitLabel
+                container.accessibilityHint = item.accessibilityHint ?? container.accessibilityHint
+            } else {
+                var accessibilityTitle = ""
+                if let item = item as? ESTabBarItem {
+                    accessibilityTitle = item.accessibilityLabel ?? item.title ?? ""
+                }
+                if self.isMoreItem(idx) {
+                    accessibilityTitle = NSLocalizedString("More_TabBarItem", bundle: Bundle(for:ESTabBarController.self), comment: "")
+                }
+                
+                let formatString = NSLocalizedString(item == selectedItem ? "TabBarItem_Selected_AccessibilityLabel" : "TabBarItem_AccessibilityLabel",
+                                                     bundle: Bundle(for: ESTabBarController.self),
+                                                     comment: "")
+                container.accessibilityLabel = String(format: formatString, accessibilityTitle, idx + 1, tabBarItems.count)
+            }
+            
+        }
+    }
+}

+ 152 - 0
RainbowPlanet/RainbowPlanet/Tools/ESTabBarController-swift/ESTabBarController.swift

@@ -0,0 +1,152 @@
+//
+//  ESTabBarController.swift
+//
+//  Created by Vincent Li on 2017/2/8.
+//  Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import UIKit
+
+/// 是否需要自定义点击事件回调类型
+public typealias ESTabBarControllerShouldHijackHandler = ((_ tabBarController: UITabBarController, _ viewController: UIViewController, _ index: Int) -> (Bool))
+/// 自定义点击事件回调类型
+public typealias ESTabBarControllerDidHijackHandler = ((_ tabBarController: UITabBarController, _ viewController: UIViewController, _ index: Int) -> (Void))
+
+open class ESTabBarController: UITabBarController, ESTabBarDelegate {
+    
+    /// 打印异常
+    public static func printError(_ description: String) {
+        #if DEBUG
+            print("ERROR: ESTabBarController catch an error '\(description)' \n")
+        #endif
+    }
+    
+    /// 当前tabBarController是否存在"More"tab
+    public static func isShowingMore(_ tabBarController: UITabBarController?) -> Bool {
+        return tabBarController?.moreNavigationController.parent != nil
+    }
+
+    /// Ignore next selection or not.
+    fileprivate var ignoreNextSelection = false
+
+    /// Should hijack select action or not.
+    open var shouldHijackHandler: ESTabBarControllerShouldHijackHandler?
+    /// Hijack select action.
+    open var didHijackHandler: ESTabBarControllerDidHijackHandler?
+    
+    /// Observer tabBarController's selectedViewController. change its selection when it will-set.
+    open override var selectedViewController: UIViewController? {
+        willSet {
+            guard let newValue = newValue else {
+                // if newValue == nil ...
+                return
+            }
+            guard !ignoreNextSelection else {
+                ignoreNextSelection = false
+                return
+            }
+            guard let tabBar = self.tabBar as? ESTabBar, let items = tabBar.items, let index = viewControllers?.firstIndex(of: newValue) else {
+                return
+            }
+            let value = (ESTabBarController.isShowingMore(self) && index > items.count - 1) ? items.count - 1 : index
+            tabBar.select(itemAtIndex: value, animated: false)
+        }
+    }
+    
+    /// Observer tabBarController's selectedIndex. change its selection when it will-set.
+    open override var selectedIndex: Int {
+        willSet {
+            guard !ignoreNextSelection else {
+                ignoreNextSelection = false
+                return
+            }
+            guard let tabBar = self.tabBar as? ESTabBar, let items = tabBar.items else {
+                return
+            }
+            let value = (ESTabBarController.isShowingMore(self) && newValue > items.count - 1) ? items.count - 1 : newValue
+            tabBar.select(itemAtIndex: value, animated: false)
+        }
+    }
+    
+    /// Customize set tabBar use KVC.
+    open override func viewDidLoad() {
+        super.viewDidLoad()
+        let tabBar = { () -> ESTabBar in 
+            let tabBar = ESTabBar()
+            tabBar.delegate = self
+            tabBar.customDelegate = self
+            tabBar.tabBarController = self
+            return tabBar
+        }()
+        self.setValue(tabBar, forKey: "tabBar")
+    }
+
+    // MARK: - UITabBar delegate
+    open override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
+        guard let idx = tabBar.items?.firstIndex(of: item) else {
+            return;
+        }
+        if idx == tabBar.items!.count - 1, ESTabBarController.isShowingMore(self) {
+            ignoreNextSelection = true
+            selectedViewController = moreNavigationController
+            return;
+        }
+        if let vc = viewControllers?[idx] {
+            ignoreNextSelection = true
+            selectedIndex = idx
+            delegate?.tabBarController?(self, didSelect: vc)
+        }
+    }
+    
+    open override func tabBar(_ tabBar: UITabBar, willBeginCustomizing items: [UITabBarItem]) {
+        if let tabBar = tabBar as? ESTabBar {
+            tabBar.updateLayout()
+        }
+    }
+    
+    open override func tabBar(_ tabBar: UITabBar, didEndCustomizing items: [UITabBarItem], changed: Bool) {
+        if let tabBar = tabBar as? ESTabBar {
+            tabBar.updateLayout()
+        }
+    }
+    
+    // MARK: - ESTabBar delegate
+    internal func tabBar(_ tabBar: UITabBar, shouldSelect item: UITabBarItem) -> Bool {
+        if let idx = tabBar.items?.firstIndex(of: item), let vc = viewControllers?[idx] {
+            return delegate?.tabBarController?(self, shouldSelect: vc) ?? true
+        }
+        return true
+    }
+    
+    internal func tabBar(_ tabBar: UITabBar, shouldHijack item: UITabBarItem) -> Bool {
+        if let idx = tabBar.items?.firstIndex(of: item), let vc = viewControllers?[idx] {
+            return shouldHijackHandler?(self, vc, idx) ?? false
+        }
+        return false
+    }
+    
+    internal func tabBar(_ tabBar: UITabBar, didHijack item: UITabBarItem) {
+        if let idx = tabBar.items?.firstIndex(of: item), let vc = viewControllers?[idx] {
+            didHijackHandler?(self, vc, idx)
+        }
+    }
+    
+}

+ 107 - 0
RainbowPlanet/RainbowPlanet/Tools/ESTabBarController-swift/ESTabBarItem.swift

@@ -0,0 +1,107 @@
+//
+//  ESTabBarController.swift
+//
+//  Created by Vincent Li on 2017/2/8.
+//  Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import UIKit
+
+/*
+ * ESTabBarItem继承自UITabBarItem,目的是为ESTabBarItemContentView提供UITabBarItem属性的设置。
+ * 目前支持大多常用的属性,例如image, selectedImage, title, tag 等。
+ *
+ * Unsupport properties:
+ *  MARK: UIBarItem properties
+ *      1. var isEnabled: Bool
+ *      2. var landscapeImagePhone: UIImage?
+ *      3. var imageInsets: UIEdgeInsets
+ *      4.  var landscapeImagePhoneInsets: UIEdgeInsets
+ *      5. func setTitleTextAttributes(_ attributes: [String : Any]?, for state: UIControlState)
+ *      6. func titleTextAttributes(for state: UIControlState) -> [String : Any]?
+ *  MARK: UITabBarItem properties
+ *      7. var titlePositionAdjustment: UIOffset
+ *      8. func setBadgeTextAttributes(_ textAttributes: [String : Any]?, for state: UIControlState)
+ *      9. func badgeTextAttributes(for state: UIControlState) -> [String : Any]?
+ */
+@available(iOS 8.0, *)
+open class ESTabBarItem: UITabBarItem {
+    
+    /// Customize content view
+    open var contentView: ESTabBarItemContentView?
+    
+    // MARK: UIBarItem properties
+    open override var title: String? // default is nil
+        {
+        didSet { self.contentView?.title = title }
+    }
+    
+    open override var image: UIImage? // default is nil
+        {
+        didSet { self.contentView?.image = image }
+    }
+    
+    // MARK: UITabBarItem properties
+    open override var selectedImage: UIImage? // default is nil
+        {
+        didSet { self.contentView?.selectedImage = selectedImage }
+    }
+    
+    open override var badgeValue: String? // default is nil
+        {
+        get { return contentView?.badgeValue }
+        set(newValue) { contentView?.badgeValue = newValue }
+    }
+    
+    /// Override UITabBarItem.badgeColor, make it available for iOS8.0 and later.
+    /// If this item displays a badge, this color will be used for the badge's background. If set to nil, the default background color will be used instead.
+    @available(iOS 8.0, *)
+    open override var badgeColor: UIColor? {
+        get { return contentView?.badgeColor }
+        set(newValue) { contentView?.badgeColor = newValue }
+    }
+    
+    open override var tag: Int // default is 0
+        {
+        didSet { self.contentView?.tag = tag }
+    }
+    
+    /* The unselected image is autogenerated from the image argument. The selected image
+     is autogenerated from the selectedImage if provided and the image argument otherwise.
+     To prevent system coloring, provide images with UIImageRenderingModeAlwaysOriginal (see UIImage.h)
+     */
+    public init(_ contentView: ESTabBarItemContentView = ESTabBarItemContentView(), title: String? = nil, image: UIImage? = nil, selectedImage: UIImage? = nil, tag: Int = 0) {
+        super.init()
+        self.contentView = contentView
+        self.setTitle(title, image: image, selectedImage: selectedImage, tag: tag)
+    }
+    public required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    open func setTitle(_ title: String? = nil, image: UIImage? = nil, selectedImage: UIImage? = nil, tag: Int = 0) {
+        self.title = title
+        self.image = image
+        self.selectedImage = selectedImage
+        self.tag = tag
+    }
+    
+}

+ 116 - 0
RainbowPlanet/RainbowPlanet/Tools/ESTabBarController-swift/ESTabBarItemBadgeView.swift

@@ -0,0 +1,116 @@
+//
+//  ESTabBarItemBadgeView.swift
+//
+//  Created by Vincent Li on 2017/2/8.
+//  Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import UIKit
+
+/*
+ * ESTabBarItemBadgeView
+ * 这个类定义了item中使用的badge视图样式,默认为ESTabBarItemBadgeView类对象。
+ * 你可以设置ESTabBarItemContentView的badgeView属性为自定义的ESTabBarItemBadgeView子类,这样就可以轻松实现 自定义通知样式了。
+ */
+open class ESTabBarItemBadgeView: UIView {
+    
+    /// 默认颜色
+    public static var defaultBadgeColor = UIColor(red: 255.0/255.0, green: 59.0/255.0, blue: 48.0/255.0, alpha: 1.0)
+    
+    /// Badge color
+    open var badgeColor: UIColor? = defaultBadgeColor {
+        didSet {
+            imageView.backgroundColor = badgeColor
+        }
+    }
+    
+    /// Badge value, supprot nil, "", "1", "someText". Hidden when nil. Show Little dot style when "".
+    open var badgeValue: String? {
+        didSet {
+            badgeLabel.text = badgeValue
+        }
+    }
+    
+    /// Image view
+    open var imageView: UIImageView = {
+        let imageView = UIImageView.init(frame: CGRect.zero)
+        imageView.backgroundColor = .clear
+        return imageView
+    }()
+    
+    /// 显示badgeValue的Label
+    open var badgeLabel: UILabel = {
+        let badgeLabel = UILabel.init(frame: CGRect.zero)
+        badgeLabel.backgroundColor = .clear
+        badgeLabel.textColor = .white
+        badgeLabel.font = UIFont.systemFont(ofSize: 13.0)
+        badgeLabel.textAlignment = .center
+        return badgeLabel
+    }()
+    
+    /// Initializer
+    public override init(frame: CGRect) {
+        super.init(frame: frame)
+        self.addSubview(imageView)
+        self.addSubview(badgeLabel)
+        self.imageView.backgroundColor = badgeColor
+    }
+    public required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    /*
+     *  通过layoutSubviews()布局子视图,你可以通过重写此方法实现自定义布局。
+     **/
+    open override func layoutSubviews() {
+        super.layoutSubviews()
+        guard let badgeValue = badgeValue else {
+            imageView.isHidden = true
+            badgeLabel.isHidden = true
+            return
+        }
+        
+        imageView.isHidden = false
+        badgeLabel.isHidden = false
+        
+        if badgeValue == "" {
+            imageView.frame = CGRect.init(origin: CGPoint.init(x: (bounds.size.width - 8.0) / 2.0, y: (bounds.size.height - 8.0) / 2.0), size: CGSize.init(width: 8.0, height: 8.0))
+        } else {
+            imageView.frame = bounds
+        }
+        imageView.layer.cornerRadius = imageView.bounds.size.height / 2.0
+        badgeLabel.sizeToFit()
+        badgeLabel.center = imageView.center
+    }
+    
+    /*
+     *  通过此方法计算badge视图需要占用父视图的frame大小,通过重写此方法可以自定义badge视图的大小。
+     *  如果你需要自定义badge视图在Content中的位置,可以设置Content的badgeOffset属性。
+     */
+    open override func sizeThatFits(_ size: CGSize) -> CGSize {
+        guard let _ = badgeValue else {
+            return CGSize.init(width: 18.0, height: 18.0)
+        }
+        let textSize = badgeLabel.sizeThatFits(CGSize.init(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude))
+        return CGSize.init(width: max(18.0, textSize.width + 10.0), height: 18.0)
+    }
+    
+}

+ 67 - 0
RainbowPlanet/RainbowPlanet/Tools/ESTabBarController-swift/ESTabBarItemContainer.swift

@@ -0,0 +1,67 @@
+//
+//  ESTabBarItemContainer.swift
+//
+//  Created by Vincent Li on 2017/2/8.
+//  Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import UIKit
+
+internal class ESTabBarItemContainer: UIControl {
+    
+    internal init(_ target: AnyObject?, tag: Int) {
+        super.init(frame: CGRect.zero)
+        self.tag = tag
+        self.addTarget(target, action: #selector(ESTabBar.selectAction(_:)), for: .touchUpInside)
+        self.addTarget(target, action: #selector(ESTabBar.highlightAction(_:)), for: .touchDown)
+        self.addTarget(target, action: #selector(ESTabBar.highlightAction(_:)), for: .touchDragEnter)
+        self.addTarget(target, action: #selector(ESTabBar.dehighlightAction(_:)), for: .touchDragExit)
+        self.backgroundColor = .clear
+        self.isAccessibilityElement = true
+    }
+    
+    internal required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    internal override func layoutSubviews() {
+        super.layoutSubviews()
+        for subview in self.subviews {
+            if let subview = subview as? ESTabBarItemContentView {
+                subview.frame = CGRect.init(x: subview.insets.left, y: subview.insets.top, width: bounds.size.width - subview.insets.left - subview.insets.right, height: bounds.size.height - subview.insets.top - subview.insets.bottom)
+                subview.updateLayout()
+            }
+        }
+    }
+
+    internal override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
+        var b = super.point(inside: point, with: event)
+        if !b {
+            for subview in self.subviews {
+                if subview.point(inside: CGPoint.init(x: point.x - subview.frame.origin.x, y: point.y - subview.frame.origin.y), with: event) {
+                    b = true
+                }
+            }
+        }
+        return b
+    }
+    
+}

+ 394 - 0
RainbowPlanet/RainbowPlanet/Tools/ESTabBarController-swift/ESTabBarItemContentView.swift

@@ -0,0 +1,394 @@
+//
+//  ESTabBarContentView.swift
+//
+//  Created by Vincent Li on 2017/2/8.
+//  Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import UIKit
+
+public enum ESTabBarItemContentMode : Int {
+    
+    case alwaysOriginal // Always set the original image size
+    
+    case alwaysTemplate // Always set the image as a template image size
+}
+
+
+open class ESTabBarItemContentView: UIView {
+    
+    // MARK: - PROPERTY SETTING
+
+    /// 设置contentView的偏移
+    open var insets = UIEdgeInsets.zero
+    
+    /// 是否被选中
+    open var selected = false
+    
+    /// 是否处于高亮状态
+    open var highlighted = false
+    
+    /// 是否支持高亮
+    open var highlightEnabled = true
+    
+    /// 文字颜色
+    open var textColor = UIColor(white: 0.57254902, alpha: 1.0) {
+        didSet {
+            if !selected { titleLabel.textColor = textColor }
+        }
+    }
+    
+    /// 高亮时文字颜色
+    open var highlightTextColor = UIColor(red: 0.0, green: 0.47843137, blue: 1.0, alpha: 1.0) {
+        didSet {
+            if selected { titleLabel.textColor = highlightTextColor }
+        }
+    }
+//
+//    /// icon颜色
+//    open var iconColor = UIColor(white: 0.57254902, alpha: 1.0) {
+//        didSet {
+//            if !selected { imageView.tintColor = iconColor }
+//        }
+//    }
+//
+//    /// 高亮时icon颜色
+//    open var highlightIconColor = UIColor(red: 0.0, green: 0.47843137, blue: 1.0, alpha: 1.0) {
+//        didSet {
+//            if selected { imageView.tintColor = highlightIconColor }
+//        }
+//    }
+    
+    /// 背景颜色
+    open var backdropColor = UIColor.clear {
+        didSet {
+            if !selected { backgroundColor = backdropColor }
+        }
+    }
+    
+    /// 高亮时背景颜色
+    open var highlightBackdropColor = UIColor.clear {
+        didSet {
+            if selected { backgroundColor = highlightBackdropColor }
+        }
+    }
+    
+    open var title: String? {
+        didSet {
+            self.titleLabel.text = title
+            self.updateLayout()
+        }
+    }
+    
+    /// Icon imageView renderingMode, default is .alwaysTemplate like UITabBarItem
+    open var renderingMode: UIImage.RenderingMode = .alwaysOriginal {
+        didSet {
+            self.updateDisplay()
+        }
+    }
+    
+    /// Item content mode, default is .alwaysTemplate like UITabBarItem
+    open var itemContentMode: ESTabBarItemContentMode = .alwaysTemplate {
+        didSet {
+            self.updateDisplay()
+        }
+    }
+    
+    /// Icon imageView's image
+    open var image: UIImage? {
+        didSet {
+            if !selected { self.updateDisplay() }
+        }
+    }
+    
+    open var selectedImage: UIImage? {
+        didSet {
+            if selected { self.updateDisplay() }
+        }
+    }
+    
+    open var imageView: UIImageView = {
+        let imageView = UIImageView.init(frame: CGRect.zero)
+        imageView.backgroundColor = .clear
+        return imageView
+    }()
+    
+    open var titleLabel: UILabel = {
+        let titleLabel = UILabel.init(frame: CGRect.zero)
+        titleLabel.backgroundColor = .clear
+        titleLabel.textColor = .clear
+        titleLabel.textAlignment = .center
+        return titleLabel
+    }()
+    
+    
+    /// Badge value
+    open var badgeValue: String? {
+        didSet {
+            if let _ = badgeValue {
+                self.tabBarItemBadgeView.badgeValue = badgeValue
+                self.addSubview(tabBarItemBadgeView)
+                self.updateLayout()
+            } else {
+                // Remove when nil.
+                self.tabBarItemBadgeView.removeFromSuperview()
+            }
+            badgeChanged(animated: true, completion: nil)
+        }
+    }
+    open var badgeColor: UIColor? {
+        didSet {
+            if let _ = badgeColor {
+                self.tabBarItemBadgeView.badgeColor = badgeColor
+            } else {
+                self.tabBarItemBadgeView.badgeColor = ESTabBarItemBadgeView.defaultBadgeColor
+            }
+        }
+    }
+    open var tabBarItemBadgeView: ESTabBarItemBadgeView = ESTabBarItemBadgeView() {
+        willSet {
+            if let _ = tabBarItemBadgeView.superview {
+                tabBarItemBadgeView.removeFromSuperview()
+            }
+        }
+        didSet {
+            if let _ = tabBarItemBadgeView.superview {
+                self.updateLayout()
+            }
+        }
+    }
+    open var badgeOffset: UIOffset = UIOffset.init(horizontal: 6.0, vertical: -22.0) {
+        didSet {
+            if badgeOffset != oldValue {
+                self.updateLayout()
+            }
+        }
+    }
+    
+    // MARK: -
+    public override init(frame: CGRect) {
+        super.init(frame: frame)
+        self.isUserInteractionEnabled = false
+        
+        addSubview(imageView)
+        addSubview(titleLabel)
+        
+        titleLabel.textColor = textColor
+//        imageView.tintColor = iconColor
+        backgroundColor = backdropColor
+    }
+    
+    public required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    open func updateDisplay() {
+        imageView.image = (selected ? (selectedImage ?? image) : image)?.withRenderingMode(renderingMode)
+//        imageView.tintColor = selected ? highlightIconColor : iconColor
+        titleLabel.textColor = selected ? highlightTextColor : textColor
+        backgroundColor = selected ? highlightBackdropColor : backdropColor
+    }
+    
+    open func updateLayout() {
+        let w = self.bounds.size.width
+        let h = self.bounds.size.height
+        
+        imageView.isHidden = (imageView.image == nil)
+        titleLabel.isHidden = (titleLabel.text == nil)
+
+        if self.itemContentMode == .alwaysTemplate {
+            var s: CGFloat = 0.0 // image size
+            var f: CGFloat = 0.0 // font
+            var isLandscape = false
+            if let keyWindow = UIApplication.shared.keyWindow {
+                isLandscape = keyWindow.bounds.width > keyWindow.bounds.height
+            }
+            let isWide = isLandscape || traitCollection.horizontalSizeClass == .regular // is landscape or regular
+            if #available(iOS 11.0, *), isWide {
+                s = UIScreen.main.scale == 3.0 ? 23.0 : 20.0
+                f = UIScreen.main.scale == 3.0 ? 13.0 : 12.0
+            } else {
+                s = 23.0
+                f = 10.0
+            }
+            
+            if !imageView.isHidden && !titleLabel.isHidden {
+                titleLabel.font = UIFont.systemFont(ofSize: f)
+                titleLabel.sizeToFit()
+                if #available(iOS 11.0, *), isWide {
+                    titleLabel.frame = CGRect.init(x: (w - titleLabel.bounds.size.width) / 2.0 + (UIScreen.main.scale == 3.0 ? 14.25 : 12.25),
+                                                   y: (h - titleLabel.bounds.size.height) / 2.0,
+                                                   width: titleLabel.bounds.size.width,
+                                                   height: titleLabel.bounds.size.height)
+                    imageView.frame = CGRect.init(x: titleLabel.frame.origin.x - s - (UIScreen.main.scale == 3.0 ? 6.0 : 5.0),
+                                                  y: (h - s) / 2.0,
+                                                  width: s,
+                                                  height: s)
+                } else {
+                    titleLabel.frame = CGRect.init(x: (w - titleLabel.bounds.size.width) / 2.0,
+                                                   y: h - titleLabel.bounds.size.height - 1.0,
+                                                   width: titleLabel.bounds.size.width,
+                                                   height: titleLabel.bounds.size.height)
+                    imageView.frame = CGRect.init(x: (w - s) / 2.0,
+                                                  y: (h - s) / 2.0 - 6.0,
+                                                  width: s,
+                                                  height: s)
+                }
+            } else if !imageView.isHidden {
+                imageView.frame = CGRect.init(x: (w - s) / 2.0,
+                                              y: (h - s) / 2.0,
+                                              width: s,
+                                              height: s)
+            } else if !titleLabel.isHidden {
+                titleLabel.font = UIFont.systemFont(ofSize: f)
+                titleLabel.sizeToFit()
+                titleLabel.frame = CGRect.init(x: (w - titleLabel.bounds.size.width) / 2.0,
+                                               y: (h - titleLabel.bounds.size.height) / 2.0,
+                                               width: titleLabel.bounds.size.width,
+                                               height: titleLabel.bounds.size.height)
+            }
+            
+            if let _ = tabBarItemBadgeView.superview {
+                let size = tabBarItemBadgeView.sizeThatFits(self.frame.size)
+                if #available(iOS 11.0, *), isWide {
+                    tabBarItemBadgeView.frame = CGRect.init(origin: CGPoint.init(x: imageView.frame.midX - 3 + badgeOffset.horizontal, y: imageView.frame.midY + 3 + badgeOffset.vertical), size: size)
+                } else {
+                    tabBarItemBadgeView.frame = CGRect.init(origin: CGPoint.init(x: w / 2.0 + badgeOffset.horizontal, y: h / 2.0 + badgeOffset.vertical), size: size)
+                }
+                tabBarItemBadgeView.setNeedsLayout()
+            }
+            
+        } else {
+            if !imageView.isHidden && !titleLabel.isHidden {
+                titleLabel.sizeToFit()
+                imageView.sizeToFit()
+                titleLabel.frame = CGRect.init(x: (w - titleLabel.bounds.size.width) / 2.0,
+                                               y: h - titleLabel.bounds.size.height - 1.0,
+                                               width: titleLabel.bounds.size.width,
+                                               height: titleLabel.bounds.size.height)
+                imageView.frame = CGRect.init(x: (w - imageView.bounds.size.width) / 2.0,
+                                              y: (h - imageView.bounds.size.height) / 2.0 - 6.0,
+                                              width: imageView.bounds.size.width,
+                                              height: imageView.bounds.size.height)
+            } else if !imageView.isHidden {
+                imageView.sizeToFit()
+                imageView.center = CGPoint.init(x: w / 2.0, y: h / 2.0)
+            } else if !titleLabel.isHidden {
+                titleLabel.sizeToFit()
+                titleLabel.center = CGPoint.init(x: w / 2.0, y: h / 2.0)
+            }
+            
+            if let _ = tabBarItemBadgeView.superview {
+                let size = tabBarItemBadgeView.sizeThatFits(self.frame.size)
+                tabBarItemBadgeView.frame = CGRect.init(origin: CGPoint.init(x: w / 2.0 + badgeOffset.horizontal, y: h / 2.0 + badgeOffset.vertical), size: size)
+                tabBarItemBadgeView.setNeedsLayout()
+            }
+        }
+    }
+
+    // MARK: - INTERNAL METHODS
+    internal final func select(animated: Bool, completion: (() -> ())?) {
+        selected = true
+        if highlightEnabled && highlighted {
+            highlighted = false
+            dehighlightAnimation(animated: animated, completion: { [weak self] in
+                self?.updateDisplay()
+                self?.selectAnimation(animated: animated, completion: completion)
+            })
+        } else {
+            updateDisplay()
+            selectAnimation(animated: animated, completion: completion)
+        }
+    }
+    
+    internal final func deselect(animated: Bool, completion: (() -> ())?) {
+        selected = false
+        updateDisplay()
+        self.deselectAnimation(animated: animated, completion: completion)
+    }
+    
+    internal final func reselect(animated: Bool, completion: (() -> ())?) {
+        if selected == false {
+            select(animated: animated, completion: completion)
+        } else {
+            if highlightEnabled && highlighted {
+                highlighted = false
+                dehighlightAnimation(animated: animated, completion: { [weak self] in
+                    self?.reselectAnimation(animated: animated, completion: completion)
+                })
+            } else {
+                reselectAnimation(animated: animated, completion: completion)
+            }
+        }
+    }
+    
+    internal final func highlight(animated: Bool, completion: (() -> ())?) {
+        if !highlightEnabled {
+            return
+        }
+        if highlighted == true {
+            return
+        }
+        highlighted = true
+        self.highlightAnimation(animated: animated, completion: completion)
+    }
+    
+    internal final func dehighlight(animated: Bool, completion: (() -> ())?) {
+        if !highlightEnabled {
+            return
+        }
+        if !highlighted {
+            return
+        }
+        highlighted = false
+        self.dehighlightAnimation(animated: animated, completion: completion)
+    }
+    
+    internal func badgeChanged(animated: Bool, completion: (() -> ())?) {
+        self.badgeChangedAnimation(animated: animated, completion: completion)
+    }
+    
+    // MARK: - ANIMATION METHODS
+    open func selectAnimation(animated: Bool, completion: (() -> ())?) {
+        completion?()
+    }
+    
+    open func deselectAnimation(animated: Bool, completion: (() -> ())?) {
+        completion?()
+    }
+    
+    open func reselectAnimation(animated: Bool, completion: (() -> ())?) {
+        completion?()
+    }
+    
+    open func highlightAnimation(animated: Bool, completion: (() -> ())?) {
+        completion?()
+    }
+    
+    open func dehighlightAnimation(animated: Bool, completion: (() -> ())?) {
+        completion?()
+    }
+    
+    open func badgeChangedAnimation(animated: Bool, completion: (() -> ())?) {
+        completion?()
+    }
+    
+}

+ 71 - 0
RainbowPlanet/RainbowPlanet/Tools/ESTabBarController-swift/ESTabBarItemMoreContentView.swift

@@ -0,0 +1,71 @@
+//
+//  ESTabBarItemMoreContentView.swift
+//
+//  Created by Vincent Li on 2017/2/8.
+//  Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import UIKit
+
+open class ESTabBarItemMoreContentView: ESTabBarItemContentView {
+    
+    public override init(frame: CGRect) {
+        super.init(frame: frame)
+        self.title = NSLocalizedString("More_TabBarItem", bundle: Bundle(for:ESTabBarController.self), comment: "")
+        self.image = systemMore(highlighted: false)
+        self.selectedImage = systemMore(highlighted: true)
+    }
+    
+    public required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    public func systemMore(highlighted isHighlighted: Bool) -> UIImage? {
+        let image = UIImage.init()
+        let circleDiameter  = isHighlighted ? 5.0 : 4.0
+        let scale = UIScreen.main.scale
+        
+        UIGraphicsBeginImageContextWithOptions(CGSize.init(width: 32, height: 32), false, scale)
+        
+        if let context = UIGraphicsGetCurrentContext() {
+            context.setLineWidth(1.0)
+            for index in 0...2 {
+                let tmpRect = CGRect.init(x: 5.0 + 9.0 * Double(index), y: 14.0, width: circleDiameter, height: circleDiameter)
+                context.addEllipse(in: tmpRect)
+                image.draw(in: tmpRect)
+            }
+
+            if isHighlighted {
+                context.setFillColor(UIColor.blue.cgColor)
+                context.fillPath()
+            } else {
+                context.strokePath()
+            }
+            
+            let newImage = UIGraphicsGetImageFromCurrentImageContext()
+            UIGraphicsEndImageContext()
+            return newImage
+        }
+        
+        return nil
+    }
+    
+}

+ 3 - 0
RainbowPlanet/RainbowPlanet/Tools/ESTabBarController-swift/en.lproj/Localizable.strings

@@ -0,0 +1,3 @@
+"TabBarItem_AccessibilityLabel"="%1$@ - tab - %2$i of %3$i";
+"TabBarItem_Selected_AccessibilityLabel"="Selected - %1$@ - tab - %2$i of %3$i";
+"More_TabBarItem"="More";