首页开发
@ -90,6 +90,14 @@
|
||||
BFC676992E1280E3006659E5 /* BRSpotlightRecommandCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC676982E1280E3006659E5 /* BRSpotlightRecommandCell.swift */; };
|
||||
BFC6769B2E1285C5006659E5 /* BRPagerViewTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC6769A2E1285C5006659E5 /* BRPagerViewTransformer.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 */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@ -189,6 +197,14 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -308,6 +324,7 @@
|
||||
BF692AF72E0A480E00A5C2DA /* Thirdparty */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BFC676A62E12AF04006659E5 /* FlowLayout */,
|
||||
BFC676612E0E2C8E006659E5 /* WMZBanner */,
|
||||
BF692B292E0A84F700A5C2DA /* JXUUID */,
|
||||
);
|
||||
@ -353,6 +370,7 @@
|
||||
BF692B0C2E0A7A9A00A5C2DA /* Extension */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BFC676BD2E13A8DD006659E5 /* UIScrollView+BRRefresh.swift */,
|
||||
BFC6768C2E123D67006659E5 /* AttributedString+BRAdd.swift */,
|
||||
BFC6767A2E0E9736006659E5 /* UIStackView+BRAdd.swift */,
|
||||
BFC6766E2E0E3B51006659E5 /* UIImageView+BRAdd.swift */,
|
||||
@ -517,6 +535,8 @@
|
||||
BF692B6A2E0BC85300A5C2DA /* BRHomeViewController.swift */,
|
||||
BFC676702E0E9234006659E5 /* BRSpotlightViewViewController.swift */,
|
||||
BFC6769C2E129794006659E5 /* BRHomeTop10ViewController.swift */,
|
||||
BFC676B02E137D2F006659E5 /* BRPopularPicksViewController.swift */,
|
||||
BFC676BB2E138ABB006659E5 /* BRNewReleasesViewController.swift */,
|
||||
);
|
||||
path = Controller;
|
||||
sourceTree = "<group>";
|
||||
@ -524,6 +544,9 @@
|
||||
BF692B6C2E0BD4B200A5C2DA /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BFC676BA2E138A9A006659E5 /* NewReleases */,
|
||||
BFC676AC2E137687006659E5 /* PopularPicks */,
|
||||
BFC6769E2E129CE5006659E5 /* Top10 */,
|
||||
BFC676762E0E950A006659E5 /* Spotlight */,
|
||||
BF692B6D2E0BD4CB00A5C2DA /* BRHomeHeaderView.swift */,
|
||||
BFC6766A2E0E395F006659E5 /* BRHomeHeaderBannerCell.swift */,
|
||||
@ -607,6 +630,39 @@
|
||||
path = Spotlight;
|
||||
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 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -736,7 +792,9 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
BFC676992E1280E3006659E5 /* BRSpotlightRecommandCell.swift in Sources */,
|
||||
BFC676A42E129D60006659E5 /* BRHomeTop10Cell.swift in Sources */,
|
||||
BF692B3C2E0A8D0200A5C2DA /* BRNavigationController.swift in Sources */,
|
||||
BFC676B12E137D2F006659E5 /* BRPopularPicksViewController.swift in Sources */,
|
||||
BFC676692E0E34DA006659E5 /* BRUserAPI.swift in Sources */,
|
||||
BFC676782E0E9553006659E5 /* BRSpotlightMainBaseCell.swift in Sources */,
|
||||
BFC676732E0E938B006659E5 /* BRTableView.swift in Sources */,
|
||||
@ -765,10 +823,12 @@
|
||||
BF692B102E0A7B4300A5C2DA /* BRUserDefaultsKey.swift in Sources */,
|
||||
BFC676852E122D9E006659E5 /* BRVideoDetailViewController.swift in Sources */,
|
||||
BFC676912E126248006659E5 /* BRSpotlightTopCell.swift in Sources */,
|
||||
BFC676B72E137DFC006659E5 /* BRPopularPicksCell.swift in Sources */,
|
||||
BF692B422E0A8FB500A5C2DA /* UIFont+BRAdd.swift in Sources */,
|
||||
BF692AEC2E0A475D00A5C2DA /* SceneDelegate.swift in Sources */,
|
||||
BF692B492E0A9D0E00A5C2DA /* UIView+BRAdd.swift in Sources */,
|
||||
BFC676812E122733006659E5 /* BRPlayerProtocol.swift in Sources */,
|
||||
BFC676BC2E138ABB006659E5 /* BRNewReleasesViewController.swift in Sources */,
|
||||
BF692B5F2E0B812800A5C2DA /* BRTabBarItemContainer.swift in Sources */,
|
||||
BF692B652E0BC53900A5C2DA /* CGMutablePath+BRRoundedCorner.swift in Sources */,
|
||||
BFC676752E0E93B3006659E5 /* BRTableViewCell.swift in Sources */,
|
||||
@ -776,6 +836,7 @@
|
||||
BF692B092E0A775500A5C2DA /* BRLoginToken.swift in Sources */,
|
||||
BF692AFC2E0A6F8000A5C2DA /* BRNetworkTarget.swift in Sources */,
|
||||
BF692B3A2E0A8C6000A5C2DA /* BRViewController.swift in Sources */,
|
||||
BFC676BE2E13A8EB006659E5 /* UIScrollView+BRRefresh.swift in Sources */,
|
||||
BF692B182E0A7D8900A5C2DA /* BRToast.swift in Sources */,
|
||||
BF692B0E2E0A7AF300A5C2DA /* UserDefaults+BRAdd.swift in Sources */,
|
||||
BF692B582E0AAA6F00A5C2DA /* UIScreen+BRAdd.swift in Sources */,
|
||||
@ -783,6 +844,7 @@
|
||||
BF692B612E0B814F00A5C2DA /* BRTabBarItemContentView.swift in Sources */,
|
||||
BF692B012E0A74A200A5C2DA /* BRDefine.swift in Sources */,
|
||||
BFC6767B2E0E973B006659E5 /* UIStackView+BRAdd.swift in Sources */,
|
||||
BFC676AB2E1372BD006659E5 /* BRHomeTop3Cell.swift in Sources */,
|
||||
BFC676892E122FDD006659E5 /* BRVideoAPI.swift in Sources */,
|
||||
BFC6769B2E1285C5006659E5 /* BRPagerViewTransformer.swift in Sources */,
|
||||
BFC676832E122CC5006659E5 /* BRPlayerViewModel.swift in Sources */,
|
||||
@ -809,8 +871,10 @@
|
||||
BF692B562E0AA92100A5C2DA /* BRCollectionViewCell.swift in Sources */,
|
||||
BF692B072E0A771C00A5C2DA /* BRModel.swift in Sources */,
|
||||
BF692B752E0D39D000A5C2DA /* BRListModel.swift in Sources */,
|
||||
BFC676B92E1385FC006659E5 /* BRPopularPicksSmallCell.swift in Sources */,
|
||||
BF692B512E0AA8C600A5C2DA /* BRPlayerListViewController.swift in Sources */,
|
||||
BFC676522E0D4EFD006659E5 /* BRHomeViewModel.swift in Sources */,
|
||||
BFC676A72E12AF04006659E5 /* WaterfallMutiSectionFlowLayout.swift in Sources */,
|
||||
BF692B2A2E0A84F700A5C2DA /* JXUUID.m in Sources */,
|
||||
BF692B2B2E0A84F700A5C2DA /* PDKeyChain.m in Sources */,
|
||||
BFC6766B2E0E395F006659E5 /* BRHomeHeaderBannerCell.swift in Sources */,
|
||||
|
@ -48,7 +48,11 @@ class BRViewController: UIViewController {
|
||||
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 {
|
||||
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.path)
|
||||
|
||||
|
||||
DispatchQueue.global().async {
|
||||
let response: BRNetworkResponse<T> = _deserialize(data: tempData)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
if response.code != BRNetworkCodeSucceed {
|
||||
if parameters.isToast {
|
||||
BRToast.show(text: response.msg)
|
||||
}
|
||||
}
|
||||
completion?(response)
|
||||
let response: BRNetworkResponse<T> = _deserialize(data: tempData)
|
||||
if response.code != BRNetworkCodeSucceed {
|
||||
if parameters.isToast {
|
||||
BRToast.show(text: response.msg)
|
||||
}
|
||||
}
|
||||
completion?(response)
|
||||
|
||||
} catch {
|
||||
var res = BRNetworkResponse<T>()
|
||||
|
@ -10,33 +10,181 @@ import UIKit
|
||||
class BRHomeTop10ViewController: BRViewController {
|
||||
|
||||
|
||||
private lazy var dataArr: [BRShortModel] = []
|
||||
private lazy var dataArr: [[BRShortModel]] = []
|
||||
|
||||
|
||||
// private lazy var collectionView: BRCollectionView = {
|
||||
// let collectionView = BRCollectionView(frame: .zero, collectionViewLayout: <#T##UICollectionViewLayout#>)
|
||||
// }()
|
||||
private lazy var collectionViewLayout: WaterfallMutiSectionFlowLayout = {
|
||||
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() {
|
||||
super.viewDidLoad()
|
||||
|
||||
requestDataArr()
|
||||
|
||||
br_setupUI()
|
||||
}
|
||||
|
||||
|
||||
|
||||
override func handleHeaderRefresh(_ completer: (() -> Void)?) {
|
||||
requestDataArr {
|
||||
completer?()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
guard let self = self else { return }
|
||||
guard let list = list else { return }
|
||||
self.dataArr = list
|
||||
guard let list = list else {
|
||||
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 [
|
||||
spotlightVC,
|
||||
BRHomeTop10ViewController(),
|
||||
BRViewController(),
|
||||
BRViewController(),
|
||||
BRPopularPicksViewController(),
|
||||
BRNewReleasesViewController(),
|
||||
BRViewController()
|
||||
]
|
||||
}()
|
||||
|
||||
private lazy var requestGroup = DispatchGroup()
|
||||
|
||||
private lazy var pageParam: WMZPageParam = {
|
||||
let param = WMZPageParam()
|
||||
param.wTitleArr = [
|
||||
@ -75,7 +77,7 @@ class BRHomeViewController: BRViewController {
|
||||
return 0
|
||||
}
|
||||
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)
|
||||
view.backgroundColor = .clear
|
||||
view.downSc?.backgroundColor = .clear
|
||||
view.downSc?.br_addRefreshHeader { [weak self] in
|
||||
self?.handleHeaderRefresh(nil)
|
||||
}
|
||||
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 {
|
||||
|
||||
private func requestHomeData() {
|
||||
private func requestHomeData(completer: (() -> Void)? = nil) {
|
||||
|
||||
BRHomeAPI.requestHomeData { [weak self] list in
|
||||
guard let self = self else { return }
|
||||
self.viewModel.homeOldDataArr = list ?? []
|
||||
|
||||
self.headerView.bannerArr = self.viewModel.bannerArr
|
||||
if let bannerArr = self.viewModel.bannerArr, bannerArr.count > 0 {
|
||||
self.bgImageView.isHidden = false
|
||||
self.pageView.updateHeadView()
|
||||
} else {
|
||||
self.bgImageView.isHidden = true
|
||||
if let list = list {
|
||||
self.viewModel.homeOldDataArr = list
|
||||
|
||||
self.headerView.bannerArr = self.viewModel.bannerArr
|
||||
if let bannerArr = self.viewModel.bannerArr, bannerArr.count > 0 {
|
||||
self.bgImageView.isHidden = false
|
||||
self.pageView.updateHeadView()
|
||||
} else {
|
||||
self.bgImageView.isHidden = true
|
||||
}
|
||||
self.spotlightVC.reloadData()
|
||||
}
|
||||
self.spotlightVC.reloadData()
|
||||
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)
|
||||
tableView.delegate = self
|
||||
tableView.dataSource = self
|
||||
tableView.contentInset = .init(top: 0, left: 0, bottom: UIScreen.customTabBarHeight, right: 0)
|
||||
tableView.register(BRSpotlightMainBaseCell.self, forCellReuseIdentifier: "cell")
|
||||
tableView.register(BRSpotlightHotMainCell.self, forCellReuseIdentifier: BRHomeModuleItem.ModuleKey.v3_recommand.rawValue)
|
||||
tableView.register(BRSpotlightTopMainCell.self, forCellReuseIdentifier: BRHomeModuleItem.ModuleKey.week_ranking.rawValue)
|
||||
@ -46,7 +47,7 @@ extension BRSpotlightViewViewController {
|
||||
|
||||
tableView.snp.makeConstraints { make in
|
||||
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 buy_type: String?
|
||||
var collect_total: Int?
|
||||
var vp_description: String?
|
||||
var br_description: String?
|
||||
var episode_total: Int?
|
||||
var horizontally_img: String?
|
||||
var image_url: String?
|
||||
@ -70,12 +70,12 @@ class BRShortModel: BRModel, SmartCodable {
|
||||
@IgnoredKey
|
||||
var titleAttributedString: NSAttributedString?
|
||||
@IgnoredKey
|
||||
var vp_isSelected: Bool?
|
||||
var br_isSelected: Bool?
|
||||
|
||||
|
||||
static func mappingForKey() -> [SmartKeyTransformer]? {
|
||||
return [
|
||||
CodingKeys.vp_description <--- ["description", "short_video_description"],
|
||||
CodingKeys.br_description <--- ["description", "short_video_description"],
|
||||
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 = {
|
||||
let imageView = BRImageView()
|
||||
@ -41,6 +58,11 @@ class BRSpotlightTopCell: BRCollectionViewCell {
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var numView: UIImageView = {
|
||||
let imageView = UIImageView()
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .fontMedium(ofSize: 12)
|
||||
@ -98,6 +120,7 @@ extension BRSpotlightTopCell {
|
||||
|
||||
|
||||
contentView.addSubview(coverImageView)
|
||||
coverImageView.addSubview(numView)
|
||||
coverImageView.addSubview(coverMarkView)
|
||||
contentView.addSubview(playImageView)
|
||||
coverImageView.addSubview(textBgView)
|
||||
@ -109,6 +132,11 @@ extension BRSpotlightTopCell {
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
|
||||
numView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(10)
|
||||
make.top.equalToSuperview().offset(10)
|
||||
}
|
||||
|
||||
coverMarkView.snp.makeConstraints { make in
|
||||
make.right.bottom.equalToSuperview()
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ extension BRSpotlightTopMainCell: UICollectionViewDelegate, UICollectionViewData
|
||||
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! BRSpotlightTopCell
|
||||
cell.model = self.moduleItem?.list?[indexPath.row]
|
||||
cell.num = indexPath.row + 1
|
||||
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.
|
||||
//
|
||||
|
||||
import MJRefresh
|
||||
|
||||
extension AppDelegate {
|
||||
|
||||
func addConfig() {
|
||||
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)
|
||||
}
|
||||
}
|