首页开发
@ -90,6 +90,14 @@
|
|||||||
BFC676992E1280E3006659E5 /* BRSpotlightRecommandCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC676982E1280E3006659E5 /* BRSpotlightRecommandCell.swift */; };
|
BFC676992E1280E3006659E5 /* BRSpotlightRecommandCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC676982E1280E3006659E5 /* BRSpotlightRecommandCell.swift */; };
|
||||||
BFC6769B2E1285C5006659E5 /* BRPagerViewTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC6769A2E1285C5006659E5 /* BRPagerViewTransformer.swift */; };
|
BFC6769B2E1285C5006659E5 /* BRPagerViewTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC6769A2E1285C5006659E5 /* BRPagerViewTransformer.swift */; };
|
||||||
BFC6769D2E129794006659E5 /* BRHomeTop10ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC6769C2E129794006659E5 /* BRHomeTop10ViewController.swift */; };
|
BFC6769D2E129794006659E5 /* BRHomeTop10ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC6769C2E129794006659E5 /* BRHomeTop10ViewController.swift */; };
|
||||||
|
BFC676A42E129D60006659E5 /* BRHomeTop10Cell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC676A32E129D5A006659E5 /* BRHomeTop10Cell.swift */; };
|
||||||
|
BFC676A72E12AF04006659E5 /* WaterfallMutiSectionFlowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC676A52E12AF04006659E5 /* WaterfallMutiSectionFlowLayout.swift */; };
|
||||||
|
BFC676AB2E1372BD006659E5 /* BRHomeTop3Cell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC676AA2E1372BD006659E5 /* BRHomeTop3Cell.swift */; };
|
||||||
|
BFC676B12E137D2F006659E5 /* BRPopularPicksViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC676B02E137D2F006659E5 /* BRPopularPicksViewController.swift */; };
|
||||||
|
BFC676B72E137DFC006659E5 /* BRPopularPicksCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC676B62E137DFC006659E5 /* BRPopularPicksCell.swift */; };
|
||||||
|
BFC676B92E1385FC006659E5 /* BRPopularPicksSmallCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC676B82E1385FC006659E5 /* BRPopularPicksSmallCell.swift */; };
|
||||||
|
BFC676BC2E138ABB006659E5 /* BRNewReleasesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC676BB2E138ABB006659E5 /* BRNewReleasesViewController.swift */; };
|
||||||
|
BFC676BE2E13A8EB006659E5 /* UIScrollView+BRRefresh.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC676BD2E13A8DD006659E5 /* UIScrollView+BRRefresh.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
@ -189,6 +197,14 @@
|
|||||||
BFC676982E1280E3006659E5 /* BRSpotlightRecommandCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRSpotlightRecommandCell.swift; sourceTree = "<group>"; };
|
BFC676982E1280E3006659E5 /* BRSpotlightRecommandCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRSpotlightRecommandCell.swift; sourceTree = "<group>"; };
|
||||||
BFC6769A2E1285C5006659E5 /* BRPagerViewTransformer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRPagerViewTransformer.swift; sourceTree = "<group>"; };
|
BFC6769A2E1285C5006659E5 /* BRPagerViewTransformer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRPagerViewTransformer.swift; sourceTree = "<group>"; };
|
||||||
BFC6769C2E129794006659E5 /* BRHomeTop10ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRHomeTop10ViewController.swift; sourceTree = "<group>"; };
|
BFC6769C2E129794006659E5 /* BRHomeTop10ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRHomeTop10ViewController.swift; sourceTree = "<group>"; };
|
||||||
|
BFC676A32E129D5A006659E5 /* BRHomeTop10Cell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRHomeTop10Cell.swift; sourceTree = "<group>"; };
|
||||||
|
BFC676A52E12AF04006659E5 /* WaterfallMutiSectionFlowLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaterfallMutiSectionFlowLayout.swift; sourceTree = "<group>"; };
|
||||||
|
BFC676AA2E1372BD006659E5 /* BRHomeTop3Cell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRHomeTop3Cell.swift; sourceTree = "<group>"; };
|
||||||
|
BFC676B02E137D2F006659E5 /* BRPopularPicksViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRPopularPicksViewController.swift; sourceTree = "<group>"; };
|
||||||
|
BFC676B62E137DFC006659E5 /* BRPopularPicksCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRPopularPicksCell.swift; sourceTree = "<group>"; };
|
||||||
|
BFC676B82E1385FC006659E5 /* BRPopularPicksSmallCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRPopularPicksSmallCell.swift; sourceTree = "<group>"; };
|
||||||
|
BFC676BB2E138ABB006659E5 /* BRNewReleasesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRNewReleasesViewController.swift; sourceTree = "<group>"; };
|
||||||
|
BFC676BD2E13A8DD006659E5 /* UIScrollView+BRRefresh.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIScrollView+BRRefresh.swift"; sourceTree = "<group>"; };
|
||||||
C8F11086BA392585E9563BA7 /* Pods-ShortBox.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShortBox.release.xcconfig"; path = "Target Support Files/Pods-ShortBox/Pods-ShortBox.release.xcconfig"; sourceTree = "<group>"; };
|
C8F11086BA392585E9563BA7 /* Pods-ShortBox.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShortBox.release.xcconfig"; path = "Target Support Files/Pods-ShortBox/Pods-ShortBox.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
F06627B1DEE86552C2A87AEC /* Pods-BeeReel.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BeeReel.debug.xcconfig"; path = "Target Support Files/Pods-BeeReel/Pods-BeeReel.debug.xcconfig"; sourceTree = "<group>"; };
|
F06627B1DEE86552C2A87AEC /* Pods-BeeReel.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BeeReel.debug.xcconfig"; path = "Target Support Files/Pods-BeeReel/Pods-BeeReel.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
F70FA1F4169364C4C53534CE /* Pods-BeeReel.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BeeReel.release.xcconfig"; path = "Target Support Files/Pods-BeeReel/Pods-BeeReel.release.xcconfig"; sourceTree = "<group>"; };
|
F70FA1F4169364C4C53534CE /* Pods-BeeReel.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BeeReel.release.xcconfig"; path = "Target Support Files/Pods-BeeReel/Pods-BeeReel.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
@ -308,6 +324,7 @@
|
|||||||
BF692AF72E0A480E00A5C2DA /* Thirdparty */ = {
|
BF692AF72E0A480E00A5C2DA /* Thirdparty */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
BFC676A62E12AF04006659E5 /* FlowLayout */,
|
||||||
BFC676612E0E2C8E006659E5 /* WMZBanner */,
|
BFC676612E0E2C8E006659E5 /* WMZBanner */,
|
||||||
BF692B292E0A84F700A5C2DA /* JXUUID */,
|
BF692B292E0A84F700A5C2DA /* JXUUID */,
|
||||||
);
|
);
|
||||||
@ -353,6 +370,7 @@
|
|||||||
BF692B0C2E0A7A9A00A5C2DA /* Extension */ = {
|
BF692B0C2E0A7A9A00A5C2DA /* Extension */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
BFC676BD2E13A8DD006659E5 /* UIScrollView+BRRefresh.swift */,
|
||||||
BFC6768C2E123D67006659E5 /* AttributedString+BRAdd.swift */,
|
BFC6768C2E123D67006659E5 /* AttributedString+BRAdd.swift */,
|
||||||
BFC6767A2E0E9736006659E5 /* UIStackView+BRAdd.swift */,
|
BFC6767A2E0E9736006659E5 /* UIStackView+BRAdd.swift */,
|
||||||
BFC6766E2E0E3B51006659E5 /* UIImageView+BRAdd.swift */,
|
BFC6766E2E0E3B51006659E5 /* UIImageView+BRAdd.swift */,
|
||||||
@ -517,6 +535,8 @@
|
|||||||
BF692B6A2E0BC85300A5C2DA /* BRHomeViewController.swift */,
|
BF692B6A2E0BC85300A5C2DA /* BRHomeViewController.swift */,
|
||||||
BFC676702E0E9234006659E5 /* BRSpotlightViewViewController.swift */,
|
BFC676702E0E9234006659E5 /* BRSpotlightViewViewController.swift */,
|
||||||
BFC6769C2E129794006659E5 /* BRHomeTop10ViewController.swift */,
|
BFC6769C2E129794006659E5 /* BRHomeTop10ViewController.swift */,
|
||||||
|
BFC676B02E137D2F006659E5 /* BRPopularPicksViewController.swift */,
|
||||||
|
BFC676BB2E138ABB006659E5 /* BRNewReleasesViewController.swift */,
|
||||||
);
|
);
|
||||||
path = Controller;
|
path = Controller;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -524,6 +544,9 @@
|
|||||||
BF692B6C2E0BD4B200A5C2DA /* View */ = {
|
BF692B6C2E0BD4B200A5C2DA /* View */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
BFC676BA2E138A9A006659E5 /* NewReleases */,
|
||||||
|
BFC676AC2E137687006659E5 /* PopularPicks */,
|
||||||
|
BFC6769E2E129CE5006659E5 /* Top10 */,
|
||||||
BFC676762E0E950A006659E5 /* Spotlight */,
|
BFC676762E0E950A006659E5 /* Spotlight */,
|
||||||
BF692B6D2E0BD4CB00A5C2DA /* BRHomeHeaderView.swift */,
|
BF692B6D2E0BD4CB00A5C2DA /* BRHomeHeaderView.swift */,
|
||||||
BFC6766A2E0E395F006659E5 /* BRHomeHeaderBannerCell.swift */,
|
BFC6766A2E0E395F006659E5 /* BRHomeHeaderBannerCell.swift */,
|
||||||
@ -607,6 +630,39 @@
|
|||||||
path = Spotlight;
|
path = Spotlight;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
BFC6769E2E129CE5006659E5 /* Top10 */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
BFC676A32E129D5A006659E5 /* BRHomeTop10Cell.swift */,
|
||||||
|
BFC676AA2E1372BD006659E5 /* BRHomeTop3Cell.swift */,
|
||||||
|
);
|
||||||
|
path = Top10;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
BFC676A62E12AF04006659E5 /* FlowLayout */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
BFC676A52E12AF04006659E5 /* WaterfallMutiSectionFlowLayout.swift */,
|
||||||
|
);
|
||||||
|
path = FlowLayout;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
BFC676AC2E137687006659E5 /* PopularPicks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
BFC676B62E137DFC006659E5 /* BRPopularPicksCell.swift */,
|
||||||
|
BFC676B82E1385FC006659E5 /* BRPopularPicksSmallCell.swift */,
|
||||||
|
);
|
||||||
|
path = PopularPicks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
BFC676BA2E138A9A006659E5 /* NewReleases */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
);
|
||||||
|
path = NewReleases;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
DF948F1E234E75684255568B /* Frameworks */ = {
|
DF948F1E234E75684255568B /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -736,7 +792,9 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
BFC676992E1280E3006659E5 /* BRSpotlightRecommandCell.swift in Sources */,
|
BFC676992E1280E3006659E5 /* BRSpotlightRecommandCell.swift in Sources */,
|
||||||
|
BFC676A42E129D60006659E5 /* BRHomeTop10Cell.swift in Sources */,
|
||||||
BF692B3C2E0A8D0200A5C2DA /* BRNavigationController.swift in Sources */,
|
BF692B3C2E0A8D0200A5C2DA /* BRNavigationController.swift in Sources */,
|
||||||
|
BFC676B12E137D2F006659E5 /* BRPopularPicksViewController.swift in Sources */,
|
||||||
BFC676692E0E34DA006659E5 /* BRUserAPI.swift in Sources */,
|
BFC676692E0E34DA006659E5 /* BRUserAPI.swift in Sources */,
|
||||||
BFC676782E0E9553006659E5 /* BRSpotlightMainBaseCell.swift in Sources */,
|
BFC676782E0E9553006659E5 /* BRSpotlightMainBaseCell.swift in Sources */,
|
||||||
BFC676732E0E938B006659E5 /* BRTableView.swift in Sources */,
|
BFC676732E0E938B006659E5 /* BRTableView.swift in Sources */,
|
||||||
@ -765,10 +823,12 @@
|
|||||||
BF692B102E0A7B4300A5C2DA /* BRUserDefaultsKey.swift in Sources */,
|
BF692B102E0A7B4300A5C2DA /* BRUserDefaultsKey.swift in Sources */,
|
||||||
BFC676852E122D9E006659E5 /* BRVideoDetailViewController.swift in Sources */,
|
BFC676852E122D9E006659E5 /* BRVideoDetailViewController.swift in Sources */,
|
||||||
BFC676912E126248006659E5 /* BRSpotlightTopCell.swift in Sources */,
|
BFC676912E126248006659E5 /* BRSpotlightTopCell.swift in Sources */,
|
||||||
|
BFC676B72E137DFC006659E5 /* BRPopularPicksCell.swift in Sources */,
|
||||||
BF692B422E0A8FB500A5C2DA /* UIFont+BRAdd.swift in Sources */,
|
BF692B422E0A8FB500A5C2DA /* UIFont+BRAdd.swift in Sources */,
|
||||||
BF692AEC2E0A475D00A5C2DA /* SceneDelegate.swift in Sources */,
|
BF692AEC2E0A475D00A5C2DA /* SceneDelegate.swift in Sources */,
|
||||||
BF692B492E0A9D0E00A5C2DA /* UIView+BRAdd.swift in Sources */,
|
BF692B492E0A9D0E00A5C2DA /* UIView+BRAdd.swift in Sources */,
|
||||||
BFC676812E122733006659E5 /* BRPlayerProtocol.swift in Sources */,
|
BFC676812E122733006659E5 /* BRPlayerProtocol.swift in Sources */,
|
||||||
|
BFC676BC2E138ABB006659E5 /* BRNewReleasesViewController.swift in Sources */,
|
||||||
BF692B5F2E0B812800A5C2DA /* BRTabBarItemContainer.swift in Sources */,
|
BF692B5F2E0B812800A5C2DA /* BRTabBarItemContainer.swift in Sources */,
|
||||||
BF692B652E0BC53900A5C2DA /* CGMutablePath+BRRoundedCorner.swift in Sources */,
|
BF692B652E0BC53900A5C2DA /* CGMutablePath+BRRoundedCorner.swift in Sources */,
|
||||||
BFC676752E0E93B3006659E5 /* BRTableViewCell.swift in Sources */,
|
BFC676752E0E93B3006659E5 /* BRTableViewCell.swift in Sources */,
|
||||||
@ -776,6 +836,7 @@
|
|||||||
BF692B092E0A775500A5C2DA /* BRLoginToken.swift in Sources */,
|
BF692B092E0A775500A5C2DA /* BRLoginToken.swift in Sources */,
|
||||||
BF692AFC2E0A6F8000A5C2DA /* BRNetworkTarget.swift in Sources */,
|
BF692AFC2E0A6F8000A5C2DA /* BRNetworkTarget.swift in Sources */,
|
||||||
BF692B3A2E0A8C6000A5C2DA /* BRViewController.swift in Sources */,
|
BF692B3A2E0A8C6000A5C2DA /* BRViewController.swift in Sources */,
|
||||||
|
BFC676BE2E13A8EB006659E5 /* UIScrollView+BRRefresh.swift in Sources */,
|
||||||
BF692B182E0A7D8900A5C2DA /* BRToast.swift in Sources */,
|
BF692B182E0A7D8900A5C2DA /* BRToast.swift in Sources */,
|
||||||
BF692B0E2E0A7AF300A5C2DA /* UserDefaults+BRAdd.swift in Sources */,
|
BF692B0E2E0A7AF300A5C2DA /* UserDefaults+BRAdd.swift in Sources */,
|
||||||
BF692B582E0AAA6F00A5C2DA /* UIScreen+BRAdd.swift in Sources */,
|
BF692B582E0AAA6F00A5C2DA /* UIScreen+BRAdd.swift in Sources */,
|
||||||
@ -783,6 +844,7 @@
|
|||||||
BF692B612E0B814F00A5C2DA /* BRTabBarItemContentView.swift in Sources */,
|
BF692B612E0B814F00A5C2DA /* BRTabBarItemContentView.swift in Sources */,
|
||||||
BF692B012E0A74A200A5C2DA /* BRDefine.swift in Sources */,
|
BF692B012E0A74A200A5C2DA /* BRDefine.swift in Sources */,
|
||||||
BFC6767B2E0E973B006659E5 /* UIStackView+BRAdd.swift in Sources */,
|
BFC6767B2E0E973B006659E5 /* UIStackView+BRAdd.swift in Sources */,
|
||||||
|
BFC676AB2E1372BD006659E5 /* BRHomeTop3Cell.swift in Sources */,
|
||||||
BFC676892E122FDD006659E5 /* BRVideoAPI.swift in Sources */,
|
BFC676892E122FDD006659E5 /* BRVideoAPI.swift in Sources */,
|
||||||
BFC6769B2E1285C5006659E5 /* BRPagerViewTransformer.swift in Sources */,
|
BFC6769B2E1285C5006659E5 /* BRPagerViewTransformer.swift in Sources */,
|
||||||
BFC676832E122CC5006659E5 /* BRPlayerViewModel.swift in Sources */,
|
BFC676832E122CC5006659E5 /* BRPlayerViewModel.swift in Sources */,
|
||||||
@ -809,8 +871,10 @@
|
|||||||
BF692B562E0AA92100A5C2DA /* BRCollectionViewCell.swift in Sources */,
|
BF692B562E0AA92100A5C2DA /* BRCollectionViewCell.swift in Sources */,
|
||||||
BF692B072E0A771C00A5C2DA /* BRModel.swift in Sources */,
|
BF692B072E0A771C00A5C2DA /* BRModel.swift in Sources */,
|
||||||
BF692B752E0D39D000A5C2DA /* BRListModel.swift in Sources */,
|
BF692B752E0D39D000A5C2DA /* BRListModel.swift in Sources */,
|
||||||
|
BFC676B92E1385FC006659E5 /* BRPopularPicksSmallCell.swift in Sources */,
|
||||||
BF692B512E0AA8C600A5C2DA /* BRPlayerListViewController.swift in Sources */,
|
BF692B512E0AA8C600A5C2DA /* BRPlayerListViewController.swift in Sources */,
|
||||||
BFC676522E0D4EFD006659E5 /* BRHomeViewModel.swift in Sources */,
|
BFC676522E0D4EFD006659E5 /* BRHomeViewModel.swift in Sources */,
|
||||||
|
BFC676A72E12AF04006659E5 /* WaterfallMutiSectionFlowLayout.swift in Sources */,
|
||||||
BF692B2A2E0A84F700A5C2DA /* JXUUID.m in Sources */,
|
BF692B2A2E0A84F700A5C2DA /* JXUUID.m in Sources */,
|
||||||
BF692B2B2E0A84F700A5C2DA /* PDKeyChain.m in Sources */,
|
BF692B2B2E0A84F700A5C2DA /* PDKeyChain.m in Sources */,
|
||||||
BFC6766B2E0E395F006659E5 /* BRHomeHeaderBannerCell.swift in Sources */,
|
BFC6766B2E0E395F006659E5 /* BRHomeHeaderBannerCell.swift in Sources */,
|
||||||
|
@ -48,7 +48,11 @@ class BRViewController: UIViewController {
|
|||||||
return statusBarStyle
|
return statusBarStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleHeaderRefresh(_ completer: (() -> Void)?) {}
|
func handleHeaderRefresh(_ completer: (() -> Void)?) {
|
||||||
|
completer?()
|
||||||
|
}
|
||||||
|
|
||||||
func handleFooterRefresh(_ completer: (() -> Void)?) {}
|
func handleFooterRefresh(_ completer: (() -> Void)?) {
|
||||||
|
completer?()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,4 +50,12 @@ extension UIColor {
|
|||||||
static func colorFF7489(alpha: CGFloat = 1) -> UIColor {
|
static func colorFF7489(alpha: CGFloat = 1) -> UIColor {
|
||||||
return UIColor(rgb: 0xFF7489, alpha: alpha)
|
return UIColor(rgb: 0xFF7489, alpha: alpha)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func color777777(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return UIColor(rgb: 0x777777, alpha: alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func colorE3FC37(alpha: CGFloat = 1) -> UIColor {
|
||||||
|
return UIColor(rgb: 0xE3FC37, alpha: alpha)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
57
BeeReel/Base/Extension/UIScrollView+BRRefresh.swift
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// UIScrollView+BRRefresh.swift
|
||||||
|
// BeeReel
|
||||||
|
//
|
||||||
|
// Created by 湖南秦九 on 2025/7/1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import MJRefresh
|
||||||
|
|
||||||
|
extension UIScrollView {
|
||||||
|
|
||||||
|
func br_addRefreshHeader(insetTop: CGFloat = 0, block: (() -> Void)?) {
|
||||||
|
|
||||||
|
|
||||||
|
self.mj_header = MJRefreshNormalHeader(refreshingBlock: {
|
||||||
|
block?()
|
||||||
|
})
|
||||||
|
self.mj_header?.ignoredScrollViewContentInsetTop = insetTop
|
||||||
|
}
|
||||||
|
|
||||||
|
func br_addRefreshFooter(insetBottom: CGFloat = 0, block: (() -> Void)?) {
|
||||||
|
let footer = MJRefreshAutoNormalFooter(refreshingBlock: {
|
||||||
|
block?()
|
||||||
|
})
|
||||||
|
footer.ignoredScrollViewContentInsetBottom = insetBottom
|
||||||
|
|
||||||
|
self.mj_footer = footer
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func br_addRefreshBackFooter(insetBottom: CGFloat = 0, block: (() -> Void)?) {
|
||||||
|
self.mj_footer = MJRefreshBackNormalFooter(refreshingBlock: {
|
||||||
|
block?()
|
||||||
|
})
|
||||||
|
|
||||||
|
self.mj_footer?.ignoredScrollViewContentInsetBottom = insetBottom
|
||||||
|
}
|
||||||
|
|
||||||
|
func br_endHeaderRefreshing() {
|
||||||
|
self.mj_header?.endRefreshing()
|
||||||
|
}
|
||||||
|
|
||||||
|
func br_endFooterRefreshing() {
|
||||||
|
if self.mj_footer?.state == .noMoreData { return }
|
||||||
|
self.mj_footer?.endRefreshing()
|
||||||
|
}
|
||||||
|
|
||||||
|
///重置没有更多
|
||||||
|
func br_resetNoMoreData() {
|
||||||
|
self.mj_footer?.resetNoMoreData()
|
||||||
|
}
|
||||||
|
|
||||||
|
func br_endRefreshingWithNoMoreData() {
|
||||||
|
self.mj_footer?.endRefreshingWithNoMoreData()
|
||||||
|
}
|
||||||
|
}
|
@ -28,5 +28,31 @@ class BRHomeAPI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///受欢迎的短剧
|
||||||
|
static func requestPopularPicksList(completer: ((_ list: [BRShortModel]?) -> Void)?) {
|
||||||
|
var param = BRNetworkParameters(path: "/highestPaymentAndHottestVideo")
|
||||||
|
param.method = .get
|
||||||
|
param.parameters = [
|
||||||
|
"buy_count_num" : "0",
|
||||||
|
"hottest_num" : "20"
|
||||||
|
]
|
||||||
|
|
||||||
|
BRNetwork.request(parameters: param) { (response: BRNetworkResponse<BRListModel<BRShortModel>>) in
|
||||||
|
completer?(response.data?.list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func requestNewReleasesList(page: Int, completer: ((_ list: [BRShortModel]?) -> Void)?) {
|
||||||
|
var param = BRNetworkParameters(path: "/newShortPlayList")
|
||||||
|
param.method = .get
|
||||||
|
param.parameters = [
|
||||||
|
"current_page" : page,
|
||||||
|
"page_size" : "20"
|
||||||
|
]
|
||||||
|
|
||||||
|
BRNetwork.request(parameters: param) { (response: BRNetworkResponse<BRListModel<BRShortModel>>) in
|
||||||
|
completer?(response.data?.list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -117,19 +117,13 @@ struct BRNetwork {
|
|||||||
brLog(message: parameters.parameters)
|
brLog(message: parameters.parameters)
|
||||||
brLog(message: parameters.path)
|
brLog(message: parameters.path)
|
||||||
|
|
||||||
|
let response: BRNetworkResponse<T> = _deserialize(data: tempData)
|
||||||
DispatchQueue.global().async {
|
if response.code != BRNetworkCodeSucceed {
|
||||||
let response: BRNetworkResponse<T> = _deserialize(data: tempData)
|
if parameters.isToast {
|
||||||
|
BRToast.show(text: response.msg)
|
||||||
DispatchQueue.main.async {
|
|
||||||
if response.code != BRNetworkCodeSucceed {
|
|
||||||
if parameters.isToast {
|
|
||||||
BRToast.show(text: response.msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
completion?(response)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
completion?(response)
|
||||||
|
|
||||||
} catch {
|
} catch {
|
||||||
var res = BRNetworkResponse<T>()
|
var res = BRNetworkResponse<T>()
|
||||||
|
@ -10,33 +10,181 @@ import UIKit
|
|||||||
class BRHomeTop10ViewController: BRViewController {
|
class BRHomeTop10ViewController: BRViewController {
|
||||||
|
|
||||||
|
|
||||||
private lazy var dataArr: [BRShortModel] = []
|
private lazy var dataArr: [[BRShortModel]] = []
|
||||||
|
|
||||||
|
|
||||||
// private lazy var collectionView: BRCollectionView = {
|
private lazy var collectionViewLayout: WaterfallMutiSectionFlowLayout = {
|
||||||
// let collectionView = BRCollectionView(frame: .zero, collectionViewLayout: <#T##UICollectionViewLayout#>)
|
let layout = WaterfallMutiSectionFlowLayout()
|
||||||
// }()
|
layout.delegate = self
|
||||||
|
return layout
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var collectionView: BRCollectionView = {
|
||||||
|
let collectionView = BRCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
|
||||||
|
collectionView.contentInset = .init(top: 0, left: 0, bottom: UIScreen.customTabBarHeight + 10, right: 0)
|
||||||
|
collectionView.delegate = self
|
||||||
|
collectionView.dataSource = self
|
||||||
|
collectionView.register(BRHomeTop10Cell.self, forCellWithReuseIdentifier: "cell")
|
||||||
|
collectionView.register(BRHomeTop3Cell.self, forCellWithReuseIdentifier: "BRHomeTop3Cell")
|
||||||
|
return collectionView
|
||||||
|
}()
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
requestDataArr()
|
requestDataArr()
|
||||||
|
|
||||||
|
br_setupUI()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override func handleHeaderRefresh(_ completer: (() -> Void)?) {
|
||||||
|
requestDataArr {
|
||||||
|
completer?()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension BRHomeTop10ViewController {
|
extension BRHomeTop10ViewController {
|
||||||
|
|
||||||
private func requestDataArr() {
|
private func br_setupUI() {
|
||||||
|
view.addSubview(collectionView)
|
||||||
|
|
||||||
|
collectionView.snp.makeConstraints { make in
|
||||||
|
make.left.right.equalToSuperview()
|
||||||
|
make.bottom.equalToSuperview()
|
||||||
|
make.top.equalToSuperview().offset(20)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: -------------- WMZPageProtocol --------------
|
||||||
|
extension BRHomeTop10ViewController: WMZPageProtocol {
|
||||||
|
|
||||||
|
func getMyScrollView() -> UIScrollView {
|
||||||
|
return self.collectionView
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//MARK: -------------- UICollectionViewDelegate UICollectionViewDataSource --------------
|
||||||
|
extension BRHomeTop10ViewController: UICollectionViewDelegate, UICollectionViewDataSource {
|
||||||
|
|
||||||
|
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||||
|
let model = self.dataArr[indexPath.section][indexPath.row]
|
||||||
|
|
||||||
|
if indexPath.section == 0 {
|
||||||
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "BRHomeTop3Cell", for: indexPath) as! BRHomeTop3Cell
|
||||||
|
cell.model = model
|
||||||
|
cell.num = indexPath.row + 1
|
||||||
|
return cell
|
||||||
|
} else {
|
||||||
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! BRHomeTop10Cell
|
||||||
|
cell.model = model
|
||||||
|
cell.num = indexPath.row + 4
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func numberOfSections(in collectionView: UICollectionView) -> Int {
|
||||||
|
return self.dataArr.count
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||||
|
return self.dataArr[section].count
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||||
|
let model = self.dataArr[indexPath.section][indexPath.row]
|
||||||
|
|
||||||
|
let vc = BRVideoDetailViewController()
|
||||||
|
vc.shortPlayId = model.short_play_id
|
||||||
|
self.navigationController?.pushViewController(vc, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: -------------- WaterfallMutiSectionDelegate --------------
|
||||||
|
extension BRHomeTop10ViewController: WaterfallMutiSectionDelegate {
|
||||||
|
|
||||||
|
func heightForRowAtIndexPath(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, indexPath: IndexPath, itemWidth: CGFloat) -> CGFloat {
|
||||||
|
if indexPath.section == 0 {
|
||||||
|
if indexPath.row == 0 {
|
||||||
|
return 240
|
||||||
|
} else {
|
||||||
|
return 115
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 126
|
||||||
|
}
|
||||||
|
|
||||||
|
func columnNumber(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> Int {
|
||||||
|
if section == 0 {
|
||||||
|
return 2
|
||||||
|
} else {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func lineSpacing(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGFloat {
|
||||||
|
if section == 0 {
|
||||||
|
return 10
|
||||||
|
} else {
|
||||||
|
return 12
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func interitemSpacing(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGFloat {
|
||||||
|
return 10
|
||||||
|
}
|
||||||
|
|
||||||
|
func referenceSizeForHeader(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGSize {
|
||||||
|
if section > 0 {
|
||||||
|
return .init(width: UIScreen.width, height: 10)
|
||||||
|
} else {
|
||||||
|
return .zero
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func insetForSection(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> UIEdgeInsets {
|
||||||
|
return .init(top: 0, left: 15, bottom: 0, right: 15)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension BRHomeTop10ViewController {
|
||||||
|
|
||||||
|
private func requestDataArr(completer: (() -> Void)? = nil) {
|
||||||
|
|
||||||
BRHomeAPI.requestTop10List { [weak self] list in
|
BRHomeAPI.requestTop10List { [weak self] list in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
guard let list = list else { return }
|
guard let list = list else {
|
||||||
self.dataArr = list
|
completer?()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.dataArr.removeAll()
|
||||||
|
|
||||||
|
var arr1: [BRShortModel] = []
|
||||||
|
var arr2: [BRShortModel] = []
|
||||||
|
|
||||||
|
list.enumerated().forEach {
|
||||||
|
if $0 < 3 {
|
||||||
|
arr1.append($1)
|
||||||
|
} else {
|
||||||
|
arr2.append($1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if arr1.count > 0 {
|
||||||
|
self.dataArr.append(arr1)
|
||||||
|
}
|
||||||
|
if arr2.count > 0 {
|
||||||
|
self.dataArr.append(arr2)
|
||||||
|
}
|
||||||
|
self.collectionView.reloadData()
|
||||||
|
|
||||||
|
completer?()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,12 +23,14 @@ class BRHomeViewController: BRViewController {
|
|||||||
return [
|
return [
|
||||||
spotlightVC,
|
spotlightVC,
|
||||||
BRHomeTop10ViewController(),
|
BRHomeTop10ViewController(),
|
||||||
BRViewController(),
|
BRPopularPicksViewController(),
|
||||||
BRViewController(),
|
BRNewReleasesViewController(),
|
||||||
BRViewController()
|
BRViewController()
|
||||||
]
|
]
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
private lazy var requestGroup = DispatchGroup()
|
||||||
|
|
||||||
private lazy var pageParam: WMZPageParam = {
|
private lazy var pageParam: WMZPageParam = {
|
||||||
let param = WMZPageParam()
|
let param = WMZPageParam()
|
||||||
param.wTitleArr = [
|
param.wTitleArr = [
|
||||||
@ -75,7 +77,7 @@ class BRHomeViewController: BRViewController {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
param.wCustomTabbarY = { _ in
|
param.wCustomTabbarY = { _ in
|
||||||
return UIScreen.customTabBarHeight
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -96,6 +98,9 @@ class BRHomeViewController: BRViewController {
|
|||||||
let view = WMZPageView(frame: self.view.bounds, autoFix: true, param: pageParam, parentReponder: self)
|
let view = WMZPageView(frame: self.view.bounds, autoFix: true, param: pageParam, parentReponder: self)
|
||||||
view.backgroundColor = .clear
|
view.backgroundColor = .clear
|
||||||
view.downSc?.backgroundColor = .clear
|
view.downSc?.backgroundColor = .clear
|
||||||
|
view.downSc?.br_addRefreshHeader { [weak self] in
|
||||||
|
self?.handleHeaderRefresh(nil)
|
||||||
|
}
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -162,6 +167,25 @@ class BRHomeViewController: BRViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func handleHeaderRefresh(_ completer: (() -> Void)?) {
|
||||||
|
|
||||||
|
self.requestGroup.enter()
|
||||||
|
requestHomeData { [weak self] in
|
||||||
|
self?.requestGroup.leave()
|
||||||
|
}
|
||||||
|
|
||||||
|
if let vc = self.pageView.upSc.currentVC as? BRViewController {
|
||||||
|
self.requestGroup.enter()
|
||||||
|
vc.handleHeaderRefresh { [weak self] in
|
||||||
|
self?.requestGroup.leave()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.requestGroup.notify(queue: .main) { [weak self] in
|
||||||
|
self?.pageView.downSc?.br_endHeaderRefreshing()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,21 +239,24 @@ extension BRHomeViewController {
|
|||||||
|
|
||||||
extension BRHomeViewController {
|
extension BRHomeViewController {
|
||||||
|
|
||||||
private func requestHomeData() {
|
private func requestHomeData(completer: (() -> Void)? = nil) {
|
||||||
|
|
||||||
BRHomeAPI.requestHomeData { [weak self] list in
|
BRHomeAPI.requestHomeData { [weak self] list in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.viewModel.homeOldDataArr = list ?? []
|
if let list = list {
|
||||||
|
self.viewModel.homeOldDataArr = list
|
||||||
|
|
||||||
self.headerView.bannerArr = self.viewModel.bannerArr
|
self.headerView.bannerArr = self.viewModel.bannerArr
|
||||||
if let bannerArr = self.viewModel.bannerArr, bannerArr.count > 0 {
|
if let bannerArr = self.viewModel.bannerArr, bannerArr.count > 0 {
|
||||||
self.bgImageView.isHidden = false
|
self.bgImageView.isHidden = false
|
||||||
self.pageView.updateHeadView()
|
self.pageView.updateHeadView()
|
||||||
} else {
|
} else {
|
||||||
self.bgImageView.isHidden = true
|
self.bgImageView.isHidden = true
|
||||||
|
}
|
||||||
|
self.spotlightVC.reloadData()
|
||||||
}
|
}
|
||||||
self.spotlightVC.reloadData()
|
|
||||||
self.updateStatusBarStyle()
|
self.updateStatusBarStyle()
|
||||||
|
completer?()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
125
BeeReel/Class/Home/Controller/BRNewReleasesViewController.swift
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
//
|
||||||
|
// BRNewReleasesViewController.swift
|
||||||
|
// BeeReel
|
||||||
|
//
|
||||||
|
// Created by 湖南秦九 on 2025/7/1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class BRNewReleasesViewController: BRViewController {
|
||||||
|
|
||||||
|
|
||||||
|
private lazy var dataArr: [BRShortModel] = []
|
||||||
|
|
||||||
|
private lazy var page: Int = 1
|
||||||
|
|
||||||
|
private lazy var collectionViewLayout: UICollectionViewFlowLayout = {
|
||||||
|
let width = floor((UIScreen.width - 30 - 10) / 2)
|
||||||
|
|
||||||
|
let layout = UICollectionViewFlowLayout()
|
||||||
|
layout.itemSize = .init(width: width, height: 222)
|
||||||
|
layout.minimumLineSpacing = 10
|
||||||
|
layout.minimumInteritemSpacing = 10
|
||||||
|
layout.sectionInset = .init(top: 0, left: 15, bottom: 0, right: 15)
|
||||||
|
return layout
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var collectionView: BRCollectionView = {
|
||||||
|
let collectionView = BRCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
|
||||||
|
collectionView.delegate = self
|
||||||
|
collectionView.dataSource = self
|
||||||
|
collectionView.contentInset = .init(top: 0, left: 0, bottom: UIScreen.customTabBarHeight + 10, right: 0)
|
||||||
|
collectionView.br_addRefreshBackFooter(insetBottom: 0) { [weak self] in
|
||||||
|
self?.handleFooterRefresh(nil)
|
||||||
|
}
|
||||||
|
collectionView.register(BRSpotlightNewCell.self, forCellWithReuseIdentifier: "cell")
|
||||||
|
return collectionView
|
||||||
|
}()
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
requestDataArr(page: 1)
|
||||||
|
|
||||||
|
br_setupUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func handleHeaderRefresh(_ completer: (() -> Void)?) {
|
||||||
|
requestDataArr(page: 1) {
|
||||||
|
completer?()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func handleFooterRefresh(_ completer: (() -> Void)?) {
|
||||||
|
requestDataArr(page: self.page + 1) { [weak self] in
|
||||||
|
self?.collectionView.br_endFooterRefreshing()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension BRNewReleasesViewController {
|
||||||
|
|
||||||
|
private func br_setupUI() {
|
||||||
|
view.addSubview(collectionView)
|
||||||
|
|
||||||
|
collectionView.snp.makeConstraints { make in
|
||||||
|
make.left.right.equalToSuperview()
|
||||||
|
make.top.equalToSuperview().offset(20)
|
||||||
|
make.bottom.equalToSuperview()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: -------------- WMZPageProtocol --------------
|
||||||
|
extension BRNewReleasesViewController: WMZPageProtocol {
|
||||||
|
func getMyScrollView() -> UIScrollView {
|
||||||
|
return self.collectionView
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: -------------- UICollectionViewDelegate UICollectionViewDataSource --------------
|
||||||
|
extension BRNewReleasesViewController: UICollectionViewDelegate, UICollectionViewDataSource {
|
||||||
|
|
||||||
|
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||||
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! BRSpotlightNewCell
|
||||||
|
cell.model = self.dataArr[indexPath.row]
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||||
|
return dataArr.count
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||||
|
let model = dataArr[indexPath.row]
|
||||||
|
|
||||||
|
let vc = BRVideoDetailViewController()
|
||||||
|
vc.shortPlayId = model.short_play_id
|
||||||
|
self.navigationController?.pushViewController(vc, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension BRNewReleasesViewController {
|
||||||
|
|
||||||
|
private func requestDataArr(page: Int, completer: (() -> Void)? = nil) {
|
||||||
|
|
||||||
|
BRHomeAPI.requestNewReleasesList(page: page) { [weak self] list in
|
||||||
|
guard let self = self else { return }
|
||||||
|
if let list = list {
|
||||||
|
if page == 1 {
|
||||||
|
self.dataArr.removeAll()
|
||||||
|
}
|
||||||
|
self.dataArr += list
|
||||||
|
self.page = page
|
||||||
|
|
||||||
|
self.collectionView.reloadData()
|
||||||
|
}
|
||||||
|
completer?()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
174
BeeReel/Class/Home/Controller/BRPopularPicksViewController.swift
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
//
|
||||||
|
// BRPopularPicksViewController.swift
|
||||||
|
// BeeReel
|
||||||
|
//
|
||||||
|
// Created by 湖南秦九 on 2025/7/1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class BRPopularPicksViewController: BRViewController {
|
||||||
|
|
||||||
|
|
||||||
|
private lazy var dataArr: [BRShortModel] = []
|
||||||
|
|
||||||
|
private lazy var contentView: UIView = {
|
||||||
|
let view = UIView()
|
||||||
|
view.backgroundColor = .colorFFFFFF()
|
||||||
|
view.layer.cornerRadius = 10
|
||||||
|
view.layer.masksToBounds = true
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var collectionViewLayout: UICollectionViewFlowLayout = {
|
||||||
|
let layout = UICollectionViewFlowLayout()
|
||||||
|
layout.itemSize = .init(width: UIScreen.width - 90 - 20, height: 196)
|
||||||
|
layout.sectionInset = .init(top: 10, left: 10, bottom: 0, right: 10)
|
||||||
|
layout.minimumLineSpacing = 10
|
||||||
|
return layout
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var collectionView: BRCollectionView = {
|
||||||
|
let collectionView = BRCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
|
||||||
|
collectionView.delegate = self
|
||||||
|
collectionView.dataSource = self
|
||||||
|
collectionView.contentInset = .init(top: 0, left: 0, bottom: 10, right: 0)
|
||||||
|
collectionView.register(BRPopularPicksCell.self, forCellWithReuseIdentifier: "cell")
|
||||||
|
return collectionView
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var smallCollectionViewLayout: UICollectionViewFlowLayout = {
|
||||||
|
let layout = UICollectionViewFlowLayout()
|
||||||
|
layout.itemSize = .init(width: 44, height: 58)
|
||||||
|
layout.minimumLineSpacing = 10
|
||||||
|
return layout
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var smallCollectionView: BRCollectionView = {
|
||||||
|
let collectionView = BRCollectionView(frame: .zero, collectionViewLayout: smallCollectionViewLayout)
|
||||||
|
collectionView.delegate = self
|
||||||
|
collectionView.dataSource = self
|
||||||
|
collectionView.showsVerticalScrollIndicator = false
|
||||||
|
collectionView.register(BRPopularPicksSmallCell.self, forCellWithReuseIdentifier: "cell")
|
||||||
|
return collectionView
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var topButton: UIButton = {
|
||||||
|
let button = UIButton(type: .custom)
|
||||||
|
button.setImage(UIImage(named: "top_button_01"), for: .normal)
|
||||||
|
button.addTarget(self, action: #selector(handleTopButton), for: .touchUpInside)
|
||||||
|
return button
|
||||||
|
}()
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
br_setupUI()
|
||||||
|
|
||||||
|
requestDataArr()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@objc private func handleTopButton() {
|
||||||
|
|
||||||
|
collectionView.scrollToTop(animated: true)
|
||||||
|
smallCollectionView.scrollToTop(animated: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func handleHeaderRefresh(_ completer: (() -> Void)?) {
|
||||||
|
requestDataArr {
|
||||||
|
completer?()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension BRPopularPicksViewController {
|
||||||
|
|
||||||
|
private func br_setupUI() {
|
||||||
|
view.addSubview(contentView)
|
||||||
|
contentView.addSubview(collectionView)
|
||||||
|
view.addSubview(smallCollectionView)
|
||||||
|
view.addSubview(topButton)
|
||||||
|
|
||||||
|
contentView.snp.makeConstraints { make in
|
||||||
|
make.left.equalToSuperview().offset(15)
|
||||||
|
make.right.equalToSuperview().offset(-75)
|
||||||
|
make.top.equalToSuperview().offset(20)
|
||||||
|
make.bottom.equalToSuperview().offset(-(UIScreen.customTabBarHeight + 15))
|
||||||
|
}
|
||||||
|
|
||||||
|
collectionView.snp.makeConstraints { make in
|
||||||
|
make.edges.equalToSuperview()
|
||||||
|
}
|
||||||
|
|
||||||
|
smallCollectionView.snp.makeConstraints { make in
|
||||||
|
make.top.equalTo(contentView)
|
||||||
|
make.right.equalToSuperview().offset(-15)
|
||||||
|
make.width.equalTo(self.smallCollectionViewLayout.itemSize.width)
|
||||||
|
// make.bottom.equalTo(contentView)
|
||||||
|
make.bottom.equalTo(topButton.snp.top).offset(-10)
|
||||||
|
}
|
||||||
|
|
||||||
|
topButton.snp.makeConstraints { make in
|
||||||
|
make.centerX.equalTo(smallCollectionView)
|
||||||
|
make.bottom.equalTo(contentView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: -------------- WMZPageProtocol --------------
|
||||||
|
extension BRPopularPicksViewController: WMZPageProtocol {
|
||||||
|
func getMyScrollViews() -> [UIScrollView] {
|
||||||
|
return [self.collectionView, self.smallCollectionView]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: -------------- UICollectionViewDelegate UICollectionViewDataSource --------------
|
||||||
|
extension BRPopularPicksViewController: UICollectionViewDelegate, UICollectionViewDataSource {
|
||||||
|
|
||||||
|
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||||
|
let model = self.dataArr[indexPath.row]
|
||||||
|
if collectionView == self.collectionView {
|
||||||
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! BRPopularPicksCell
|
||||||
|
cell.model = model
|
||||||
|
return cell
|
||||||
|
} else {
|
||||||
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! BRPopularPicksSmallCell
|
||||||
|
cell.model = model
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||||
|
return self.dataArr.count
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||||
|
let model = self.dataArr[indexPath.row]
|
||||||
|
|
||||||
|
let vc = BRVideoDetailViewController()
|
||||||
|
vc.shortPlayId = model.short_play_id
|
||||||
|
self.navigationController?.pushViewController(vc, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extension BRPopularPicksViewController {
|
||||||
|
|
||||||
|
private func requestDataArr(completer: (() -> Void)? = nil) {
|
||||||
|
|
||||||
|
BRHomeAPI.requestPopularPicksList { [weak self] list in
|
||||||
|
guard let self = self else { return }
|
||||||
|
|
||||||
|
if let list = list {
|
||||||
|
self.dataArr = list
|
||||||
|
self.collectionView.reloadData()
|
||||||
|
self.smallCollectionView.reloadData()
|
||||||
|
}
|
||||||
|
completer?()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -15,6 +15,7 @@ class BRSpotlightViewViewController: BRViewController, WMZPageProtocol {
|
|||||||
let tableView = BRTableView(frame: .zero, style: .plain)
|
let tableView = BRTableView(frame: .zero, style: .plain)
|
||||||
tableView.delegate = self
|
tableView.delegate = self
|
||||||
tableView.dataSource = self
|
tableView.dataSource = self
|
||||||
|
tableView.contentInset = .init(top: 0, left: 0, bottom: UIScreen.customTabBarHeight, right: 0)
|
||||||
tableView.register(BRSpotlightMainBaseCell.self, forCellReuseIdentifier: "cell")
|
tableView.register(BRSpotlightMainBaseCell.self, forCellReuseIdentifier: "cell")
|
||||||
tableView.register(BRSpotlightHotMainCell.self, forCellReuseIdentifier: BRHomeModuleItem.ModuleKey.v3_recommand.rawValue)
|
tableView.register(BRSpotlightHotMainCell.self, forCellReuseIdentifier: BRHomeModuleItem.ModuleKey.v3_recommand.rawValue)
|
||||||
tableView.register(BRSpotlightTopMainCell.self, forCellReuseIdentifier: BRHomeModuleItem.ModuleKey.week_ranking.rawValue)
|
tableView.register(BRSpotlightTopMainCell.self, forCellReuseIdentifier: BRHomeModuleItem.ModuleKey.week_ranking.rawValue)
|
||||||
@ -46,7 +47,7 @@ extension BRSpotlightViewViewController {
|
|||||||
|
|
||||||
tableView.snp.makeConstraints { make in
|
tableView.snp.makeConstraints { make in
|
||||||
make.left.right.bottom.equalToSuperview()
|
make.left.right.bottom.equalToSuperview()
|
||||||
make.top.equalToSuperview().offset(15)
|
make.top.equalToSuperview().offset(20)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ class BRShortModel: BRModel, SmartCodable {
|
|||||||
var all_coins: String?
|
var all_coins: String?
|
||||||
var buy_type: String?
|
var buy_type: String?
|
||||||
var collect_total: Int?
|
var collect_total: Int?
|
||||||
var vp_description: String?
|
var br_description: String?
|
||||||
var episode_total: Int?
|
var episode_total: Int?
|
||||||
var horizontally_img: String?
|
var horizontally_img: String?
|
||||||
var image_url: String?
|
var image_url: String?
|
||||||
@ -70,12 +70,12 @@ class BRShortModel: BRModel, SmartCodable {
|
|||||||
@IgnoredKey
|
@IgnoredKey
|
||||||
var titleAttributedString: NSAttributedString?
|
var titleAttributedString: NSAttributedString?
|
||||||
@IgnoredKey
|
@IgnoredKey
|
||||||
var vp_isSelected: Bool?
|
var br_isSelected: Bool?
|
||||||
|
|
||||||
|
|
||||||
static func mappingForKey() -> [SmartKeyTransformer]? {
|
static func mappingForKey() -> [SmartKeyTransformer]? {
|
||||||
return [
|
return [
|
||||||
CodingKeys.vp_description <--- ["description", "short_video_description"],
|
CodingKeys.br_description <--- ["description", "short_video_description"],
|
||||||
CodingKeys.name <--- ["short_video_title", "name"]
|
CodingKeys.name <--- ["short_video_title", "name"]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
125
BeeReel/Class/Home/View/PopularPicks/BRPopularPicksCell.swift
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
//
|
||||||
|
// BRPopularPicksCell.swift
|
||||||
|
// BeeReel
|
||||||
|
//
|
||||||
|
// Created by 湖南秦九 on 2025/7/1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class BRPopularPicksCell: BRCollectionViewCell {
|
||||||
|
|
||||||
|
var model: BRShortModel? {
|
||||||
|
didSet {
|
||||||
|
coverImageView.br_setImage(url: model?.image_url)
|
||||||
|
titleLabel.text = model?.name
|
||||||
|
categoryLabel.text = model?.category?.first
|
||||||
|
desLabel.text = model?.br_description
|
||||||
|
|
||||||
|
hotView.setNeedsUpdateConfiguration()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private lazy var coverImageView: BRImageView = {
|
||||||
|
let imageView = BRImageView()
|
||||||
|
imageView.layer.cornerRadius = 8
|
||||||
|
imageView.layer.masksToBounds = true
|
||||||
|
return imageView
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var titleLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .fontMedium(ofSize: 14)
|
||||||
|
label.textColor = .color1C1C1C()
|
||||||
|
label.numberOfLines = 3
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var categoryLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .fontRegular(ofSize: 10)
|
||||||
|
label.textColor = .color899D00()
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var desLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .fontRegular(ofSize: 10)
|
||||||
|
label.textColor = .color777777()
|
||||||
|
label.numberOfLines = 4
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var hotView: UIButton = {
|
||||||
|
var config = UIButton.Configuration.plain()
|
||||||
|
config.image = UIImage(named: "hot_icon_02")
|
||||||
|
config.imagePlacement = .leading
|
||||||
|
config.imagePadding = 2
|
||||||
|
config.contentInsets = .init(top: 0, leading: 0, bottom: 0, trailing: 0)
|
||||||
|
|
||||||
|
let button = UIButton(configuration: config)
|
||||||
|
button.isUserInteractionEnabled = false
|
||||||
|
button.configurationUpdateHandler = { [weak self] button in
|
||||||
|
guard let self = self else { return }
|
||||||
|
let count = model?.watch_total ?? 0
|
||||||
|
var string = "\(count)"
|
||||||
|
if count > 100 {
|
||||||
|
string = String(format: "%.1fk", Float(count) / 1000)
|
||||||
|
}
|
||||||
|
button.configuration?.attributedTitle = AttributedString.br_createAttributedString(string: string, color: .colorFF7489(), font: .fontRegular(ofSize: 10))
|
||||||
|
|
||||||
|
}
|
||||||
|
return button
|
||||||
|
}()
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
br_setupUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainActor required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension BRPopularPicksCell {
|
||||||
|
|
||||||
|
private func br_setupUI() {
|
||||||
|
contentView.addSubview(coverImageView)
|
||||||
|
contentView.addSubview(titleLabel)
|
||||||
|
contentView.addSubview(categoryLabel)
|
||||||
|
contentView.addSubview(desLabel)
|
||||||
|
contentView.addSubview(hotView)
|
||||||
|
|
||||||
|
coverImageView.snp.makeConstraints { make in
|
||||||
|
make.left.top.bottom.equalToSuperview()
|
||||||
|
make.width.equalTo(152)
|
||||||
|
}
|
||||||
|
|
||||||
|
titleLabel.snp.makeConstraints { make in
|
||||||
|
make.left.equalTo(coverImageView.snp.right).offset(10)
|
||||||
|
make.right.lessThanOrEqualToSuperview().offset(-10)
|
||||||
|
make.centerY.equalTo(self.contentView.snp.top).offset(30)
|
||||||
|
}
|
||||||
|
|
||||||
|
categoryLabel.snp.makeConstraints { make in
|
||||||
|
make.left.equalTo(titleLabel)
|
||||||
|
make.top.equalToSuperview().offset(75)
|
||||||
|
}
|
||||||
|
|
||||||
|
desLabel.snp.makeConstraints { make in
|
||||||
|
make.left.equalTo(titleLabel)
|
||||||
|
make.right.lessThanOrEqualToSuperview().offset(-10)
|
||||||
|
make.centerY.equalTo(self.contentView.snp.top).offset(27.5 + 94)
|
||||||
|
}
|
||||||
|
|
||||||
|
hotView.snp.makeConstraints { make in
|
||||||
|
make.left.equalTo(titleLabel)
|
||||||
|
make.bottom.equalToSuperview().offset(-17)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
//
|
||||||
|
// BRPopularPicksSmallCell.swift
|
||||||
|
// BeeReel
|
||||||
|
//
|
||||||
|
// Created by 湖南秦九 on 2025/7/1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class BRPopularPicksSmallCell: BRCollectionViewCell {
|
||||||
|
|
||||||
|
var model: BRShortModel? {
|
||||||
|
didSet {
|
||||||
|
coverImageView.br_setImage(url: model?.image_url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private lazy var coverImageView: BRImageView = {
|
||||||
|
let imageView = BRImageView()
|
||||||
|
imageView.layer.cornerRadius = 4
|
||||||
|
imageView.layer.masksToBounds = true
|
||||||
|
return imageView
|
||||||
|
}()
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
contentView.addSubview(coverImageView)
|
||||||
|
|
||||||
|
coverImageView.snp.makeConstraints { make in
|
||||||
|
make.edges.equalToSuperview()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainActor required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
}
|
@ -20,6 +20,23 @@ class BRSpotlightTopCell: BRCollectionViewCell {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var num: Int = 0 {
|
||||||
|
didSet {
|
||||||
|
switch num {
|
||||||
|
case 1:
|
||||||
|
numView.image = UIImage(named: "number_icon_01")
|
||||||
|
numView.isHidden = false
|
||||||
|
case 2:
|
||||||
|
numView.image = UIImage(named: "number_icon_02")
|
||||||
|
numView.isHidden = false
|
||||||
|
case 3:
|
||||||
|
numView.image = UIImage(named: "number_icon_03")
|
||||||
|
numView.isHidden = false
|
||||||
|
default:
|
||||||
|
numView.isHidden = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private lazy var coverImageView: BRImageView = {
|
private lazy var coverImageView: BRImageView = {
|
||||||
let imageView = BRImageView()
|
let imageView = BRImageView()
|
||||||
@ -41,6 +58,11 @@ class BRSpotlightTopCell: BRCollectionViewCell {
|
|||||||
return imageView
|
return imageView
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
private lazy var numView: UIImageView = {
|
||||||
|
let imageView = UIImageView()
|
||||||
|
return imageView
|
||||||
|
}()
|
||||||
|
|
||||||
private lazy var titleLabel: UILabel = {
|
private lazy var titleLabel: UILabel = {
|
||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.font = .fontMedium(ofSize: 12)
|
label.font = .fontMedium(ofSize: 12)
|
||||||
@ -98,6 +120,7 @@ extension BRSpotlightTopCell {
|
|||||||
|
|
||||||
|
|
||||||
contentView.addSubview(coverImageView)
|
contentView.addSubview(coverImageView)
|
||||||
|
coverImageView.addSubview(numView)
|
||||||
coverImageView.addSubview(coverMarkView)
|
coverImageView.addSubview(coverMarkView)
|
||||||
contentView.addSubview(playImageView)
|
contentView.addSubview(playImageView)
|
||||||
coverImageView.addSubview(textBgView)
|
coverImageView.addSubview(textBgView)
|
||||||
@ -109,6 +132,11 @@ extension BRSpotlightTopCell {
|
|||||||
make.edges.equalToSuperview()
|
make.edges.equalToSuperview()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
numView.snp.makeConstraints { make in
|
||||||
|
make.left.equalToSuperview().offset(10)
|
||||||
|
make.top.equalToSuperview().offset(10)
|
||||||
|
}
|
||||||
|
|
||||||
coverMarkView.snp.makeConstraints { make in
|
coverMarkView.snp.makeConstraints { make in
|
||||||
make.right.bottom.equalToSuperview()
|
make.right.bottom.equalToSuperview()
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,7 @@ extension BRSpotlightTopMainCell: UICollectionViewDelegate, UICollectionViewData
|
|||||||
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! BRSpotlightTopCell
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! BRSpotlightTopCell
|
||||||
cell.model = self.moduleItem?.list?[indexPath.row]
|
cell.model = self.moduleItem?.list?[indexPath.row]
|
||||||
|
cell.num = indexPath.row + 1
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
|
|
||||||
|
167
BeeReel/Class/Home/View/Top10/BRHomeTop10Cell.swift
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
//
|
||||||
|
// BRHomeTop10Cell.swift
|
||||||
|
// BeeReel
|
||||||
|
//
|
||||||
|
// Created by 湖南秦九 on 2025/6/30.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
|
||||||
|
class BRHomeTop10Cell: BRCollectionViewCell {
|
||||||
|
|
||||||
|
|
||||||
|
var model: BRShortModel? {
|
||||||
|
didSet {
|
||||||
|
coverImageView.br_setImage(url: model?.image_url)
|
||||||
|
titleLabel.text = model?.name
|
||||||
|
categoryLabel.text = model?.category?.first
|
||||||
|
desLabel.text = model?.br_description
|
||||||
|
|
||||||
|
hotView.setNeedsUpdateConfiguration()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var num: Int = 0 {
|
||||||
|
didSet {
|
||||||
|
numLabel.text = "\(num)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private lazy var bgImageView: UIImageView = {
|
||||||
|
let imageView = UIImageView(image: UIImage(named: "top_bg_image_01"))
|
||||||
|
return imageView
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var coverImageView: BRImageView = {
|
||||||
|
let imageView = BRImageView()
|
||||||
|
imageView.layer.cornerRadius = 8
|
||||||
|
imageView.layer.masksToBounds = true
|
||||||
|
return imageView
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var titleLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .fontMedium(ofSize: 14)
|
||||||
|
label.textColor = .color1C1C1C()
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var categoryLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .fontRegular(ofSize: 10)
|
||||||
|
label.textColor = .color899D00()
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var desLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.numberOfLines = 2
|
||||||
|
label.font = .fontRegular(ofSize: 10)
|
||||||
|
label.textColor = .color777777()
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var hotView: UIButton = {
|
||||||
|
var config = UIButton.Configuration.plain()
|
||||||
|
config.image = UIImage(named: "hot_icon_02")
|
||||||
|
config.imagePlacement = .leading
|
||||||
|
config.imagePadding = 2
|
||||||
|
config.contentInsets = .init(top: 0, leading: 0, bottom: 0, trailing: 0)
|
||||||
|
|
||||||
|
let button = UIButton(configuration: config)
|
||||||
|
button.isUserInteractionEnabled = false
|
||||||
|
button.configurationUpdateHandler = { [weak self] button in
|
||||||
|
guard let self = self else { return }
|
||||||
|
let count = model?.watch_total ?? 0
|
||||||
|
var string = "\(count)"
|
||||||
|
if count > 100 {
|
||||||
|
string = String(format: "%.1fk", Float(count) / 1000)
|
||||||
|
}
|
||||||
|
button.configuration?.attributedTitle = AttributedString.br_createAttributedString(string: string, color: .colorFF7489(), font: .fontRegular(ofSize: 10))
|
||||||
|
|
||||||
|
}
|
||||||
|
return button
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var numBgView: UIImageView = {
|
||||||
|
let imageView = UIImageView(image: UIImage(named: "number_bg_icon_01"))
|
||||||
|
return imageView
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var numLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .fontMedium(ofSize: 15)
|
||||||
|
label.textColor = .color000000()
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
br_setupUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainActor required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension BRHomeTop10Cell {
|
||||||
|
|
||||||
|
private func br_setupUI() {
|
||||||
|
contentView.addSubview(bgImageView)
|
||||||
|
bgImageView.addSubview(coverImageView)
|
||||||
|
bgImageView.addSubview(titleLabel)
|
||||||
|
bgImageView.addSubview(categoryLabel)
|
||||||
|
bgImageView.addSubview(desLabel)
|
||||||
|
bgImageView.addSubview(hotView)
|
||||||
|
bgImageView.addSubview(numBgView)
|
||||||
|
bgImageView.addSubview(numLabel)
|
||||||
|
|
||||||
|
bgImageView.snp.makeConstraints { make in
|
||||||
|
make.edges.equalToSuperview()
|
||||||
|
}
|
||||||
|
|
||||||
|
coverImageView.snp.makeConstraints { make in
|
||||||
|
make.centerY.equalToSuperview()
|
||||||
|
make.left.equalToSuperview().offset(7)
|
||||||
|
make.width.equalTo(90)
|
||||||
|
make.height.equalTo(112)
|
||||||
|
}
|
||||||
|
|
||||||
|
titleLabel.snp.makeConstraints { make in
|
||||||
|
make.left.equalTo(coverImageView.snp.right).offset(20)
|
||||||
|
make.top.equalToSuperview().offset(16)
|
||||||
|
make.right.lessThanOrEqualToSuperview().offset(-48)
|
||||||
|
}
|
||||||
|
|
||||||
|
categoryLabel.snp.makeConstraints { make in
|
||||||
|
make.left.equalTo(titleLabel)
|
||||||
|
make.top.equalToSuperview().offset(41)
|
||||||
|
}
|
||||||
|
|
||||||
|
desLabel.snp.makeConstraints { make in
|
||||||
|
make.left.equalTo(titleLabel)
|
||||||
|
make.top.equalToSuperview().offset(60)
|
||||||
|
make.right.lessThanOrEqualToSuperview().offset(-48)
|
||||||
|
}
|
||||||
|
|
||||||
|
hotView.snp.makeConstraints { make in
|
||||||
|
make.left.equalTo(titleLabel)
|
||||||
|
make.bottom.equalToSuperview().offset(-17)
|
||||||
|
}
|
||||||
|
|
||||||
|
numBgView.snp.makeConstraints { make in
|
||||||
|
make.centerX.equalTo(self.bgImageView.snp.right).offset(-15)
|
||||||
|
make.centerY.equalToSuperview().offset(-3)
|
||||||
|
}
|
||||||
|
|
||||||
|
numLabel.snp.makeConstraints { make in
|
||||||
|
make.centerX.equalTo(numBgView)
|
||||||
|
make.centerY.equalToSuperview().offset(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
110
BeeReel/Class/Home/View/Top10/BRHomeTop3Cell.swift
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
//
|
||||||
|
// BRHomeTop3Cell.swift
|
||||||
|
// BeeReel
|
||||||
|
//
|
||||||
|
// Created by 湖南秦九 on 2025/6/30.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class BRHomeTop3Cell: BRCollectionViewCell {
|
||||||
|
|
||||||
|
|
||||||
|
var model: BRShortModel? {
|
||||||
|
didSet {
|
||||||
|
coverImageView.br_setImage(url: model?.image_url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var num: Int = 0 {
|
||||||
|
didSet {
|
||||||
|
numLabel.text = "NO.\(num)"
|
||||||
|
if num == 1 {
|
||||||
|
coverImageView.snp.updateConstraints { make in
|
||||||
|
make.top.equalToSuperview().offset(32)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
coverImageView.snp.updateConstraints { make in
|
||||||
|
make.top.equalToSuperview().offset(28)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private lazy var coverImageView: BRImageView = {
|
||||||
|
let imageView = BRImageView()
|
||||||
|
imageView.layer.cornerRadius = 8
|
||||||
|
imageView.layer.masksToBounds = true
|
||||||
|
return imageView
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var numLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .fontMedium(ofSize: 14)
|
||||||
|
label.textColor = .colorE3FC37()
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var numIconImageView: UIImageView = {
|
||||||
|
let imageView = UIImageView(image: UIImage(named: "num_icon_01"))
|
||||||
|
return imageView
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var dotView: UIView = {
|
||||||
|
let view = UIView()
|
||||||
|
view.backgroundColor = .colorE3FC37()
|
||||||
|
view.layer.cornerRadius = 3
|
||||||
|
view.layer.masksToBounds = true
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
self.contentView.backgroundColor = .color1C1C1C()
|
||||||
|
self.contentView.layer.cornerRadius = 12
|
||||||
|
self.contentView.layer.masksToBounds = true
|
||||||
|
|
||||||
|
br_setupUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainActor required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension BRHomeTop3Cell {
|
||||||
|
|
||||||
|
private func br_setupUI() {
|
||||||
|
contentView.addSubview(coverImageView)
|
||||||
|
contentView.addSubview(dotView)
|
||||||
|
contentView.addSubview(numLabel)
|
||||||
|
contentView.addSubview(numIconImageView)
|
||||||
|
|
||||||
|
coverImageView.snp.makeConstraints { make in
|
||||||
|
make.left.equalToSuperview().offset(5)
|
||||||
|
make.centerX.equalToSuperview()
|
||||||
|
make.bottom.equalToSuperview().offset(-5)
|
||||||
|
make.top.equalToSuperview().offset(32)
|
||||||
|
}
|
||||||
|
|
||||||
|
dotView.snp.makeConstraints { make in
|
||||||
|
make.right.equalToSuperview().offset(-5)
|
||||||
|
make.top.equalToSuperview().offset(12)
|
||||||
|
make.width.height.equalTo(6)
|
||||||
|
}
|
||||||
|
|
||||||
|
numLabel.snp.makeConstraints { make in
|
||||||
|
make.left.equalToSuperview().offset(5)
|
||||||
|
make.centerY.equalTo(dotView)
|
||||||
|
}
|
||||||
|
|
||||||
|
numIconImageView.snp.makeConstraints { make in
|
||||||
|
make.centerY.equalTo(numLabel)
|
||||||
|
make.left.equalTo(numLabel.snp.right).offset(10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -5,10 +5,15 @@
|
|||||||
// Created by 湖南秦九 on 2025/6/25.
|
// Created by 湖南秦九 on 2025/6/25.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import MJRefresh
|
||||||
|
|
||||||
extension AppDelegate {
|
extension AppDelegate {
|
||||||
|
|
||||||
func addConfig() {
|
func addConfig() {
|
||||||
UIView.vp_Awake()
|
UIView.vp_Awake()
|
||||||
|
|
||||||
|
//设置刷新控件的语言
|
||||||
|
MJRefreshConfig.default.languageCode = BRLocalizedManager.manager.mjLocalizedKey
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
22
BeeReel/Sources/Assets.xcassets/icon/num_icon_01.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "箭头@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "箭头@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/num_icon_01.imageset/箭头@2x.png
vendored
Normal file
After Width: | Height: | Size: 304 B |
BIN
BeeReel/Sources/Assets.xcassets/icon/num_icon_01.imageset/箭头@3x.png
vendored
Normal file
After Width: | Height: | Size: 413 B |
22
BeeReel/Sources/Assets.xcassets/icon/number_bg_icon_01.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Ellipse 9@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Ellipse 9@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/number_bg_icon_01.imageset/Ellipse 9@2x.png
vendored
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
BeeReel/Sources/Assets.xcassets/icon/number_bg_icon_01.imageset/Ellipse 9@3x.png
vendored
Normal file
After Width: | Height: | Size: 7.3 KiB |
22
BeeReel/Sources/Assets.xcassets/icon/number_icon_01.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "金 1@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "金 1@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/number_icon_01.imageset/金 1@2x.png
vendored
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
BeeReel/Sources/Assets.xcassets/icon/number_icon_01.imageset/金 1@3x.png
vendored
Normal file
After Width: | Height: | Size: 12 KiB |
22
BeeReel/Sources/Assets.xcassets/icon/number_icon_02.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "金 2@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "金 2@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/number_icon_02.imageset/金 2@2x.png
vendored
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
BeeReel/Sources/Assets.xcassets/icon/number_icon_02.imageset/金 2@3x.png
vendored
Normal file
After Width: | Height: | Size: 12 KiB |
22
BeeReel/Sources/Assets.xcassets/icon/number_icon_03.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "铜 1@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "铜 1@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/number_icon_03.imageset/铜 1@2x.png
vendored
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
BeeReel/Sources/Assets.xcassets/icon/number_icon_03.imageset/铜 1@3x.png
vendored
Normal file
After Width: | Height: | Size: 13 KiB |
22
BeeReel/Sources/Assets.xcassets/icon/top_button_01.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Frame 21@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Frame 21@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/top_button_01.imageset/Frame 21@2x.png
vendored
Normal file
After Width: | Height: | Size: 473 B |
BIN
BeeReel/Sources/Assets.xcassets/icon/top_button_01.imageset/Frame 21@3x.png
vendored
Normal file
After Width: | Height: | Size: 683 B |
44
BeeReel/Sources/Assets.xcassets/image/top_bg_image_01.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "bg@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"resizing" : {
|
||||||
|
"cap-insets" : {
|
||||||
|
"left" : 300,
|
||||||
|
"right" : 94
|
||||||
|
},
|
||||||
|
"center" : {
|
||||||
|
"mode" : "tile",
|
||||||
|
"width" : 1
|
||||||
|
},
|
||||||
|
"mode" : "3-part-horizontal"
|
||||||
|
},
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "bg@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"resizing" : {
|
||||||
|
"cap-insets" : {
|
||||||
|
"left" : 431,
|
||||||
|
"right" : 127
|
||||||
|
},
|
||||||
|
"center" : {
|
||||||
|
"mode" : "tile",
|
||||||
|
"width" : 1
|
||||||
|
},
|
||||||
|
"mode" : "3-part-horizontal"
|
||||||
|
},
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
BeeReel/Sources/Assets.xcassets/image/top_bg_image_01.imageset/bg@2x.png
vendored
Normal file
After Width: | Height: | Size: 5.0 KiB |
BIN
BeeReel/Sources/Assets.xcassets/image/top_bg_image_01.imageset/bg@3x.png
vendored
Normal file
After Width: | Height: | Size: 7.4 KiB |
193
BeeReel/Thirdparty/FlowLayout/WaterfallMutiSectionFlowLayout.swift
vendored
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
//
|
||||||
|
// WaterfallMutiSectionFlowLayout.swift
|
||||||
|
// gymbo
|
||||||
|
//
|
||||||
|
// Created by drogan Zheng on 2020/5/7.
|
||||||
|
// Copyright © 2020 Gymbo.co. All rights reserved.
|
||||||
|
// https://github.com/RoganZheng/WaterfallMultiSectionFlowLayout
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
@objc protocol WaterfallMutiSectionDelegate: NSObjectProtocol {
|
||||||
|
// 必选delegate实现
|
||||||
|
/// collectionItem高度
|
||||||
|
func heightForRowAtIndexPath(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, indexPath: IndexPath, itemWidth: CGFloat) -> CGFloat
|
||||||
|
|
||||||
|
// 可选delegate实现
|
||||||
|
/// 每个section 列数(默认2列)
|
||||||
|
@objc optional func columnNumber(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> Int
|
||||||
|
|
||||||
|
/// header高度(默认为0)
|
||||||
|
@objc optional func referenceSizeForHeader(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGSize
|
||||||
|
|
||||||
|
/// footer高度(默认为0)
|
||||||
|
@objc optional func referenceSizeForFooter(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGSize
|
||||||
|
|
||||||
|
/// 每个section 边距(默认为0)
|
||||||
|
@objc optional func insetForSection(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> UIEdgeInsets
|
||||||
|
|
||||||
|
/// 每个section item上下间距(默认为0)
|
||||||
|
@objc optional func lineSpacing(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGFloat
|
||||||
|
|
||||||
|
/// 每个section item左右间距(默认为0)
|
||||||
|
@objc optional func interitemSpacing(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGFloat
|
||||||
|
|
||||||
|
/// section头部header与上个section尾部footer间距(默认为0)
|
||||||
|
@objc optional func spacingWithLastSection(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGFloat
|
||||||
|
}
|
||||||
|
|
||||||
|
class WaterfallMutiSectionFlowLayout: UICollectionViewFlowLayout {
|
||||||
|
weak var delegate: WaterfallMutiSectionDelegate?
|
||||||
|
|
||||||
|
private var sectionInsets: UIEdgeInsets = .zero
|
||||||
|
private var columnCount: Int = 2
|
||||||
|
private var lineSpacing: CGFloat = 0
|
||||||
|
private var interitemSpacing: CGFloat = 0
|
||||||
|
private var headerSize: CGSize = .zero
|
||||||
|
private var footerSize: CGSize = .zero
|
||||||
|
|
||||||
|
//存放attribute的数组
|
||||||
|
private var attrsArray: [UICollectionViewLayoutAttributes] = []
|
||||||
|
//存放每个section中各个列的最后一个高度
|
||||||
|
private var columnHeights: [CGFloat] = []
|
||||||
|
//collectionView的Content的高度
|
||||||
|
private var contentHeight: CGFloat = 0
|
||||||
|
//记录上个section高度最高一列的高度
|
||||||
|
private var lastContentHeight: CGFloat = 0
|
||||||
|
//每个section的header与上个section的footer距离
|
||||||
|
private var spacingWithLastSection: CGFloat = 0
|
||||||
|
|
||||||
|
|
||||||
|
override func prepare() {
|
||||||
|
super.prepare()
|
||||||
|
self.contentHeight = 0
|
||||||
|
self.lastContentHeight = 0
|
||||||
|
self.spacingWithLastSection = 0
|
||||||
|
self.lineSpacing = 0
|
||||||
|
self.sectionInsets = .zero
|
||||||
|
self.headerSize = .zero
|
||||||
|
self.footerSize = .zero
|
||||||
|
self.columnHeights.removeAll()
|
||||||
|
self.attrsArray.removeAll()
|
||||||
|
|
||||||
|
let sectionCount = self.collectionView!.numberOfSections
|
||||||
|
// 遍历section
|
||||||
|
for idx in 0..<sectionCount {
|
||||||
|
let indexPath = IndexPath(item: 0, section: idx)
|
||||||
|
if let columnCount = self.delegate?.columnNumber?(collectionView: self.collectionView!, layout: self, section: indexPath.section) {
|
||||||
|
self.columnCount = columnCount
|
||||||
|
}
|
||||||
|
if let inset = self.delegate?.insetForSection?(collectionView: self.collectionView!, layout: self, section: indexPath.section) {
|
||||||
|
self.sectionInsets = inset
|
||||||
|
}
|
||||||
|
if let spacingLastSection = self.delegate?.spacingWithLastSection?(collectionView: self.collectionView!, layout: self, section: indexPath.section) {
|
||||||
|
self.spacingWithLastSection = spacingLastSection
|
||||||
|
}
|
||||||
|
// 生成header
|
||||||
|
let itemCount = self.collectionView!.numberOfItems(inSection: idx)
|
||||||
|
let headerAttri = self.layoutAttributesForSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, at: indexPath)
|
||||||
|
if let header = headerAttri {
|
||||||
|
self.attrsArray.append(header)
|
||||||
|
self.columnHeights.removeAll()
|
||||||
|
}
|
||||||
|
self.lastContentHeight = self.contentHeight
|
||||||
|
// 初始化区 y值
|
||||||
|
for _ in 0..<self.columnCount {
|
||||||
|
self.columnHeights.append(self.contentHeight)
|
||||||
|
}
|
||||||
|
// 多少个item
|
||||||
|
for item in 0..<itemCount {
|
||||||
|
let indexPat = IndexPath(item: item, section: idx)
|
||||||
|
let attri = self.layoutAttributesForItem(at: indexPat)
|
||||||
|
if let attri = attri {
|
||||||
|
self.attrsArray.append(attri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化footer
|
||||||
|
let footerAttri = self.layoutAttributesForSupplementaryView(ofKind: UICollectionView.elementKindSectionFooter, at: indexPath)
|
||||||
|
if let footer = footerAttri {
|
||||||
|
self.attrsArray.append(footer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
|
||||||
|
return self.attrsArray
|
||||||
|
}
|
||||||
|
|
||||||
|
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
|
||||||
|
if let column = self.delegate?.columnNumber?(collectionView: self.collectionView!, layout: self, section: indexPath.section) {
|
||||||
|
self.columnCount = column
|
||||||
|
}
|
||||||
|
if let lineSpacing = self.delegate?.lineSpacing?(collectionView: self.collectionView!, layout: self, section: indexPath.section) {
|
||||||
|
self.lineSpacing = lineSpacing
|
||||||
|
}
|
||||||
|
if let interitem = self.delegate?.interitemSpacing?(collectionView: self.collectionView!, layout: self, section: indexPath.section) {
|
||||||
|
self.interitemSpacing = interitem
|
||||||
|
}
|
||||||
|
|
||||||
|
let attri = UICollectionViewLayoutAttributes(forCellWith: indexPath)
|
||||||
|
let weight = self.collectionView!.frame.size.width
|
||||||
|
let itemSpacing = CGFloat(self.columnCount - 1) * self.interitemSpacing
|
||||||
|
let allWeight = weight - self.sectionInsets.left - self.sectionInsets.right - itemSpacing
|
||||||
|
let cellWeight = allWeight / CGFloat(self.columnCount)
|
||||||
|
let cellHeight: CGFloat = (self.delegate?.heightForRowAtIndexPath(collectionView: self.collectionView!, layout: self, indexPath: indexPath, itemWidth: cellWeight))!
|
||||||
|
|
||||||
|
var tmpMinColumn = 0
|
||||||
|
var minColumnHeight = self.columnHeights[0]
|
||||||
|
for i in 0..<self.columnCount {
|
||||||
|
let columnH = self.columnHeights[i]
|
||||||
|
if minColumnHeight > columnH {
|
||||||
|
minColumnHeight = columnH
|
||||||
|
tmpMinColumn = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let cellX = self.sectionInsets.left + CGFloat(tmpMinColumn) * (cellWeight + self.interitemSpacing)
|
||||||
|
var cellY: CGFloat = 0
|
||||||
|
cellY = minColumnHeight
|
||||||
|
if cellY != self.lastContentHeight {
|
||||||
|
cellY += self.lineSpacing
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.contentHeight < minColumnHeight {
|
||||||
|
self.contentHeight = minColumnHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
attri.frame = CGRect(x: cellX, y: cellY, width: cellWeight, height: cellHeight)
|
||||||
|
self.columnHeights[tmpMinColumn] = attri.frame.maxY
|
||||||
|
//取最大的
|
||||||
|
for i in 0..<self.columnHeights.count {
|
||||||
|
if self.contentHeight < self.columnHeights[i] {
|
||||||
|
self.contentHeight = self.columnHeights[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return attri
|
||||||
|
}
|
||||||
|
override func layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
|
||||||
|
let attri = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: elementKind, with: indexPath)
|
||||||
|
if elementKind == UICollectionView.elementKindSectionHeader {
|
||||||
|
if let headerSize = self.delegate?.referenceSizeForHeader?(collectionView: self.collectionView!, layout: self, section: indexPath.section) {
|
||||||
|
self.headerSize = headerSize
|
||||||
|
}
|
||||||
|
self.contentHeight += self.spacingWithLastSection
|
||||||
|
attri.frame = CGRect(x: 0, y: self.contentHeight, width: self.headerSize.width, height: self.headerSize.height)
|
||||||
|
self.contentHeight += self.headerSize.height
|
||||||
|
self.contentHeight += self.sectionInsets.top
|
||||||
|
} else if elementKind == UICollectionView.elementKindSectionFooter {
|
||||||
|
if let footerSize = self.delegate?.referenceSizeForFooter?(collectionView: self.collectionView!, layout: self, section: indexPath.section) {
|
||||||
|
self.footerSize = footerSize
|
||||||
|
}
|
||||||
|
self.contentHeight += self.sectionInsets.bottom
|
||||||
|
attri.frame = CGRect(x: 0, y: self.contentHeight, width: self.footerSize.width, height: self.footerSize.height)
|
||||||
|
self.contentHeight += self.footerSize.height
|
||||||
|
}
|
||||||
|
return attri
|
||||||
|
}
|
||||||
|
|
||||||
|
override var collectionViewContentSize: CGSize {
|
||||||
|
return CGSize(width: self.collectionView!.frame.size.width, height: self.contentHeight)
|
||||||
|
}
|
||||||
|
}
|