diff --git a/Podfile b/Podfile index 6956a6f..2a66bc7 100644 --- a/Podfile +++ b/Podfile @@ -24,6 +24,7 @@ target 'ShortPlay' do pod 'Toast' #吐司提示 pod 'ZFPlayer/AVPlayer' #播放器 pod 'KTVHTTPCache' #视频缓存 + pod 'HWPanModal' #底部弹出控制器 target 'ShortPlayTests' do diff --git a/Podfile.lock b/Podfile.lock index cb053ea..1478dd5 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,6 +1,7 @@ PODS: - Alamofire (5.10.2) - CocoaAsyncSocket (7.6.5) + - HWPanModal (0.9.9) - KTVHTTPCache (3.0.2): - CocoaAsyncSocket - MJRefresh (3.7.9) @@ -19,6 +20,7 @@ PODS: - ZFPlayer/Core (4.1.4) DEPENDENCIES: + - HWPanModal - KTVHTTPCache - MJRefresh - Moya @@ -32,6 +34,7 @@ SPEC REPOS: trunk: - Alamofire - CocoaAsyncSocket + - HWPanModal - KTVHTTPCache - MJRefresh - Moya @@ -44,6 +47,7 @@ SPEC REPOS: SPEC CHECKSUMS: Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 + HWPanModal: b57a6717d3cdcd666bff44f9dd2a5be9f4d6f5d2 KTVHTTPCache: 5711692cdf9a5ecfe829b1e16577deb3ffe3dc86 MJRefresh: ff9e531227924c84ce459338414550a05d2aea78 Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee @@ -53,6 +57,6 @@ SPEC CHECKSUMS: YYKit: 7cda43304a8dc3696c449041e2cb3107b4e236e7 ZFPlayer: 5cf39e8d9f0c2394a014b0db4767b5b5a6bffe13 -PODFILE CHECKSUM: 422706ab4a12e286d2106acff478496d948912e8 +PODFILE CHECKSUM: 6b8807090aa7efc034949fa4dae871806b3d46fd COCOAPODS: 1.16.2 diff --git a/ShortPlay.xcodeproj/project.pbxproj b/ShortPlay.xcodeproj/project.pbxproj index 488d0d9..d765401 100644 --- a/ShortPlay.xcodeproj/project.pbxproj +++ b/ShortPlay.xcodeproj/project.pbxproj @@ -444,6 +444,7 @@ ENABLE_USER_SCRIPT_SANDBOXING = NO; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = ShortPlay/Source/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = ZyreoTV; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIMainStoryboardFile = ""; @@ -478,6 +479,7 @@ ENABLE_USER_SCRIPT_SANDBOXING = NO; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = ShortPlay/Source/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = ZyreoTV; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIMainStoryboardFile = ""; diff --git a/ShortPlay/AppDelegate/AppDelegate+Config.swift b/ShortPlay/AppDelegate/AppDelegate+Config.swift index b0a41df..25c7553 100644 --- a/ShortPlay/AppDelegate/AppDelegate+Config.swift +++ b/ShortPlay/AppDelegate/AppDelegate+Config.swift @@ -10,7 +10,7 @@ import UIKit extension AppDelegate { func appConfig() { -// UIView.et_Awake() + UIView.sp_Awake() tabBarConfig() // keyBoardStyle() diff --git a/ShortPlay/Base/Controller/SPViewController.swift b/ShortPlay/Base/Controller/SPViewController.swift index 936869a..7c10fc3 100644 --- a/ShortPlay/Base/Controller/SPViewController.swift +++ b/ShortPlay/Base/Controller/SPViewController.swift @@ -22,12 +22,19 @@ class SPViewController: UIViewController, JYPageChildContollerProtocol { private(set) var isViewDidLoad = false private(set) var isDidAppear = false - + + private(set) lazy var _bgImageView: UIImageView = { + let imageView = UIImageView(image: UIImage(named: "main_bg_image_01")) + imageView.isUserInteractionEnabled = true + return imageView; + }() + override func viewDidLoad() { super.viewDidLoad() self.isViewDidLoad = true self.edgesForExtendedLayout = [] - self.view.backgroundColor = .black + + setBgImageView() if let navi = navigationController { if navi.visibleViewController == self { @@ -38,6 +45,11 @@ class SPViewController: UIViewController, JYPageChildContollerProtocol { } } + func setBgImageView() { + self.view = self._bgImageView + self.view.backgroundColor = .black + } + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) isDidAppear = true diff --git a/ShortPlay/Base/Define/SPDefine.swift b/ShortPlay/Base/Define/SPDefine.swift index 573126a..2cd9769 100644 --- a/ShortPlay/Base/Define/SPDefine.swift +++ b/ShortPlay/Base/Define/SPDefine.swift @@ -56,3 +56,21 @@ public func spLog(message:Any? , file: String = #file, function: String = #funct print("\n\(Date(timeIntervalSinceNow: 8 * 60 * 60)) \(file.components(separatedBy: "/").last ?? "") \(function) \(line): \(message ?? "")") #endif } + + +public func sp_swizzled_instanceMethod(_ prefix: String, oldClass: Swift.AnyClass!, oldSelector: String, newClass: Swift.AnyClass) { + let newSelector = prefix + "_" + oldSelector; + let originalSelector = NSSelectorFromString(oldSelector) + let swizzledSelector = NSSelectorFromString(newSelector) + + let originalMethod = class_getInstanceMethod(oldClass, originalSelector) + let swizzledMethod = class_getInstanceMethod(newClass, swizzledSelector) + + let isAdd = class_addMethod(oldClass, originalSelector, method_getImplementation(swizzledMethod!), method_getTypeEncoding(swizzledMethod!)) + + if isAdd { + class_replaceMethod(newClass, swizzledSelector, method_getImplementation(originalMethod!), method_getTypeEncoding(originalMethod!)) + }else { + method_exchangeImplementations(originalMethod!, swizzledMethod!) + } +} diff --git a/ShortPlay/Base/Extension/CGMutablePath+SPAdd.swift b/ShortPlay/Base/Extension/CGMutablePath+SPAdd.swift new file mode 100644 index 0000000..f8c4682 --- /dev/null +++ b/ShortPlay/Base/Extension/CGMutablePath+SPAdd.swift @@ -0,0 +1,66 @@ +// +// CGMutablePath+SPAdd.swift +// ShortPlay +// +// Created by 曾觉新 on 2025/4/14. +// + +import UIKit + +/** 圆角大小 */ +struct SPCirculars { + var topLeft:CGFloat = 0 + var topRight:CGFloat = 0 + var bottomLeft:CGFloat = 0 + var bottomRight:CGFloat = 0 + + public static let zero = SPCirculars(topLeft: 0, topRight: 0, bottomLeft: 0, bottomRight: 0) + public init(topLeft: CGFloat, topRight:CGFloat, bottomLeft:CGFloat, bottomRight:CGFloat) { + self.topLeft = topLeft + self.topRight = topRight + self.bottomLeft = bottomLeft + self.bottomRight = bottomRight + } + static func ==(v1:SPCirculars, v2:SPCirculars) -> Bool { + return v1.bottomLeft == v2.bottomLeft + && v1.bottomRight == v2.bottomRight + && v1.topLeft == v2.topLeft + && v1.topRight == v2.topRight + } + static func !=(v1:SPCirculars, v2:SPCirculars) -> Bool { + return !(v1 == v2) + } +} + +extension CGMutablePath { + func addRadiusRectangle(_ circulars: SPCirculars, rect: CGRect) { + let minX = rect.minX + let minY = rect.minY + let maxX = rect.maxX + let maxY = rect.maxY + + //获取四个圆心 + let topLeftCenterX = minX + circulars.topLeft + let topLeftCenterY = minY + circulars.topLeft + + let topRightCenterX = maxX - circulars.topRight + let topRightCenterY = minY + circulars.topRight + + let bottomLeftCenterX = minX + circulars.bottomLeft + let bottomLeftCenterY = maxY - circulars.bottomLeft + + let bottomRightCenterX = maxX - circulars.bottomRight + let bottomRightCenterY = maxY - circulars.bottomRight + + //顶 左 + addArc(center: CGPoint(x: topLeftCenterX, y: topLeftCenterY), radius: circulars.topLeft, startAngle: CGFloat.pi, endAngle: CGFloat.pi * 3 / 2, clockwise: false) + //顶右 + addArc(center: CGPoint(x: topRightCenterX, y: topRightCenterY), radius: circulars.topRight, startAngle: CGFloat.pi * 3 / 2, endAngle: 0, clockwise: false) + //底右 + addArc(center: CGPoint(x: bottomRightCenterX, y: bottomRightCenterY), radius: circulars.bottomRight, startAngle: 0, endAngle: CGFloat.pi / 2, clockwise: false) + //底左 + addArc(center: CGPoint(x: bottomLeftCenterX, y: bottomLeftCenterY), radius: circulars.bottomLeft, startAngle: CGFloat.pi / 2, endAngle: CGFloat.pi, clockwise: false) + closeSubpath(); + + } +} diff --git a/ShortPlay/Base/Extension/UIColor+SPAdd.swift b/ShortPlay/Base/Extension/UIColor+SPAdd.swift index 0204cc0..8b47eca 100644 --- a/ShortPlay/Base/Extension/UIColor+SPAdd.swift +++ b/ShortPlay/Base/Extension/UIColor+SPAdd.swift @@ -43,5 +43,25 @@ extension UIColor { static func color7F7F80(alpha: CGFloat = 1) -> UIColor { return color(hex: 0x7F7F80, alpha: alpha) } + + static func colorD2D2D2(alpha: CGFloat = 1) -> UIColor { + return color(hex: 0xD2D2D2, alpha: alpha) + } + + static func colorBF6BFF(alpha: CGFloat = 1) -> UIColor { + return color(hex: 0xBF6BFF, alpha: alpha) + } + + static func color121418(alpha: CGFloat = 1) -> UIColor { + return color(hex: 0x121418, alpha: alpha) + } + + static func colorF564B6(alpha: CGFloat = 1) -> UIColor { + return color(hex: 0xF564B6, alpha: alpha) + } + + static func colorF56490(alpha: CGFloat = 1) -> UIColor { + return color(hex: 0xF56490, alpha: alpha) + } } diff --git a/ShortPlay/Base/Extension/UIFont+SPAdd.swift b/ShortPlay/Base/Extension/UIFont+SPAdd.swift index 069b9d4..51175c8 100644 --- a/ShortPlay/Base/Extension/UIFont+SPAdd.swift +++ b/ShortPlay/Base/Extension/UIFont+SPAdd.swift @@ -20,4 +20,8 @@ extension UIFont { static func fontBold(ofSize: CGFloat) -> UIFont { return .systemFont(ofSize: ofSize, weight: .bold) } + + static func fontLight(ofSize: CGFloat) -> UIFont { + return .systemFont(ofSize: ofSize, weight: .light) + } } diff --git a/ShortPlay/Base/Extension/UIStackView+SPAdd.swift b/ShortPlay/Base/Extension/UIStackView+SPAdd.swift new file mode 100644 index 0000000..667c217 --- /dev/null +++ b/ShortPlay/Base/Extension/UIStackView+SPAdd.swift @@ -0,0 +1,19 @@ +// +// UIStackView+SPAdd.swift +// ShortPlay +// +// Created by 曾觉新 on 2025/4/14. +// + +import UIKit + +extension UIStackView { + func removeAllArrangedSubview() { + let arrangedSubviews = self.arrangedSubviews + + arrangedSubviews.forEach { + self.removeArrangedSubview($0) + $0.removeFromSuperview() + } + } +} diff --git a/ShortPlay/Base/Extension/UIView+SPAdd.swift b/ShortPlay/Base/Extension/UIView+SPAdd.swift index a5a8d66..7b0f08f 100644 --- a/ShortPlay/Base/Extension/UIView+SPAdd.swift +++ b/ShortPlay/Base/Extension/UIView+SPAdd.swift @@ -9,7 +9,103 @@ import UIKit import SnapKit extension UIView { + fileprivate struct AssociatedKeys { + static var sp_tapGesture: Int? + static var sp_effect: Int? + static var sp_circulars: Int? + } + @objc public static func sp_Awake() { + sp_swizzled_instanceMethod("sp", oldClass: self, oldSelector: "layoutSubviews", newClass: self) + } + @objc func sp_layoutSubviews() { + sp_layoutSubviews() + _updateRadius() + + if let effectView = effectView, effectView.frame != self.bounds { + effectView.frame = self.bounds + } + } + ///获得当前的响应视图 + func getFirstResponderView() -> UIView? { + var resultView: UIView? = nil + + for view in self.subviews { + if view.isFirstResponder { + resultView = view + break + } else { + resultView = view.getFirstResponderView() + if resultView != nil { + break + } + } + } + return resultView + } +} + + +//MARK: -------------- 模糊效果 -------------- +extension UIView { + private var effectView: UIVisualEffectView? { + get { + return objc_getAssociatedObject(self, &AssociatedKeys.sp_effect) as? UIVisualEffectView + } + set { + objc_setAssociatedObject(self, &AssociatedKeys.sp_effect, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + } + + ///添加模糊效果 + func addEffectView(style: UIBlurEffect.Style = .dark) { + if self.effectView == nil { + let blur = UIBlurEffect(style: style) + let effectView = UIVisualEffectView(effect: blur) + self.addSubview(effectView) + self.sendSubviewToBack(effectView) + + self.effectView = effectView + } + } + ///删除模糊效果 + func removeEffectView() { + self.effectView?.removeFromSuperview() + self.effectView = nil + } +} + +//MARK: -------------- 圆角 -------------- +extension UIView { + + + private var circulars: SPCirculars? { + get { + return objc_getAssociatedObject(self, &AssociatedKeys.sp_circulars) as? SPCirculars + } + set { + objc_setAssociatedObject(self, &AssociatedKeys.sp_circulars, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + } + + func addRadius(topLeft: CGFloat, topRight: CGFloat, bottomLeft: CGFloat, bottomRight: CGFloat) { + //清空其它设置方法 + self.circulars = SPCirculars(topLeft: topLeft, topRight: topRight, bottomLeft: bottomLeft, bottomRight: bottomRight) + _updateRadius() + } + + private func _updateRadius() { + guard let circulars = self.circulars else { return } + let rect = self.bounds + + let path = CGMutablePath() + path.addRadiusRectangle(circulars, rect: rect) + + let maskLayer = CAShapeLayer() + maskLayer.frame = self.bounds + maskLayer.path = path + self.layer.mask = maskLayer + } } diff --git a/ShortPlay/Base/Networking/API/SPHomeAPI.swift b/ShortPlay/Base/Networking/API/SPHomeAPI.swift index b13bc16..e29989b 100644 --- a/ShortPlay/Base/Networking/API/SPHomeAPI.swift +++ b/ShortPlay/Base/Networking/API/SPHomeAPI.swift @@ -25,4 +25,26 @@ class SPHomeAPI: NSObject { } + ///首页顶部数据 + static func requestHomeTopData(completer: ((_ model: SPHomeTopModel?) -> Void)?) { + let param = SPNetworkParameters(path: "/homeTop") +// param.method = .get + + SPNetwork.request(parameters: param) { (response: SPNetworkResponse) in + completer?(response.data) + } + } + + ///首页模块接口 + static func requestHomeModuleData(completer: ((_ model: SPHomeModuleModel?) -> Void)?) { + var param = SPNetworkParameters(path: "/homeModuleData") + param.method = .get + + SPNetwork.request(parameters: param) { (response: SPNetworkResponse) in + completer?(response.data) + } + + } + + } diff --git a/ShortPlay/Base/Networking/API/SPVideoAPI.swift b/ShortPlay/Base/Networking/API/SPVideoAPI.swift index ab80bcb..b28d529 100644 --- a/ShortPlay/Base/Networking/API/SPVideoAPI.swift +++ b/ShortPlay/Base/Networking/API/SPVideoAPI.swift @@ -10,15 +10,18 @@ import UIKit class SPVideoAPI: NSObject { ///获取视频详情 - static func requestVideoDetail(videoId: String, shortPlayId: String, completer: ((_ model: SPVideoDetailModel?) -> Void)?) { - - var param = SPNetworkParameters(path: "/getVideoDetails") - param.method = .get - param.parameters = [ - "video_id" : videoId, + static func requestVideoDetail(videoId: String?, shortPlayId: String, completer: ((_ model: SPVideoDetailModel?) -> Void)?) { + var parameters: [String : Any] = [ "short_play_id" : shortPlayId ] + if let videoId = videoId { + parameters["video_id"] = videoId + } + var param = SPNetworkParameters(path: "/getVideoDetails") + param.method = .get + param.parameters = parameters + SPNetwork.request(parameters: param) { (response: SPNetworkResponse) in completer?(response.data) } diff --git a/ShortPlay/Base/Networking/Base/SPURLPath.swift b/ShortPlay/Base/Networking/Base/SPURLPath.swift index 8e4f58b..e88ad32 100644 --- a/ShortPlay/Base/Networking/Base/SPURLPath.swift +++ b/ShortPlay/Base/Networking/Base/SPURLPath.swift @@ -9,10 +9,26 @@ import UIKit #if DEBUG let SPBaseURL = "https://test1-api.guyantv.com" -let SPWebBaseURL = "https://test1-api.guyantv.com" +let SPWebBaseURL = "https://www.guyantv.com" #else let SPBaseURL = "https://test1-api.guyantv.com" -let SPWebBaseURL = "https://test1-api.guyantv.com" +let SPWebBaseURL = "https://www.guyantv.com" #endif +///用户协议 +let SPUserAgreementWebUrl = SPWebBaseURL + "/user_policy.htm" +///隐私协议 +let SPPrivacyPolicyWebUrl = SPWebBaseURL + "/private.htm" +///儿童个人信息保护规则 +let SPInformationProtectionWebUrl = SPWebBaseURL + "/information_protection.html" +///第三方共享清单 +let SPInformationSharingWebUrl = SPWebBaseURL + "/information_sharing.html" +///收集个人信息明示清单 +let SPPersoInforDisclosureWebUrl = SPWebBaseURL + "/persoInfor_disclosure.html" +///全国青少年互联网文明公约 +let SPCivizatioConventionWebUrl = SPWebBaseURL + "/civizatio_convention.html" +///全国青少年互联网文明公约 +let SPMemberShipAgreementWebUrl = SPWebBaseURL + "/member_ship_agreement.html" + + diff --git a/ShortPlay/Base/View/SPGradientView.swift b/ShortPlay/Base/View/SPGradientView.swift new file mode 100644 index 0000000..f6e7b41 --- /dev/null +++ b/ShortPlay/Base/View/SPGradientView.swift @@ -0,0 +1,44 @@ +// +// SPGradientView.swift +// ShortPlay +// +// Created by 曾觉新 on 2025/4/14. +// + +import UIKit + +class SPGradientView: UIView { + + override class var layerClass: AnyClass { + return CAGradientLayer.self + } + + var gradientLayer: CAGradientLayer { + return self.layer as! CAGradientLayer + } + + var locations: [NSNumber]? { + didSet { + self.gradientLayer.locations = locations + } + } + + var colors: [CGColor]? { + didSet { + self.gradientLayer.colors = colors + } + } + + var startPoint: CGPoint = .zero { + didSet { + self.gradientLayer.startPoint = startPoint + } + } + + var endPoint: CGPoint = .zero { + didSet { + self.gradientLayer.endPoint = endPoint + } + } + +} diff --git a/ShortPlay/Base/View/SPTableView.swift b/ShortPlay/Base/View/SPTableView.swift new file mode 100644 index 0000000..3dd43fe --- /dev/null +++ b/ShortPlay/Base/View/SPTableView.swift @@ -0,0 +1,51 @@ +// +// SPTableView.swift +// ShortPlay +// +// Created by 曾觉新 on 2025/4/14. +// + +import UIKit + +class SPTableView: UITableView { + + var insetGroupedMargins: CGFloat = 12 + + override init(frame: CGRect, style: UITableView.Style) { + super.init(frame: frame, style: style) +// separatorColor = .lineColor() + self.backgroundColor = .clear + self.contentInsetAdjustmentBehavior = .never + + if style == .insetGrouped { + sectionFooterHeight = 12 + sectionHeaderHeight = 0.1 + } else if style == .plain { + if #available(iOS 15.0, *) { + sectionHeaderTopPadding = 0 + } + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + ///修改 insetGrouped 的边距 参考https://github.com/QMUI/QMUIDemo_iOS/blob/master/QMUI/QMUIKit/UIKitExtensions/UITableView%2BQMUI.m + override var layoutMargins: UIEdgeInsets { + set { + super.layoutMargins = newValue + } + get { + var margins = super.layoutMargins + if #available(iOS 13.0, *) { + if self.style == .insetGrouped { + margins.left = self.safeAreaInsets.left + insetGroupedMargins + margins.right = self.safeAreaInsets.right + insetGroupedMargins + } + } + return margins + } + } + +} diff --git a/ShortPlay/Base/View/SPTableViewCell.swift b/ShortPlay/Base/View/SPTableViewCell.swift new file mode 100644 index 0000000..f4a537d --- /dev/null +++ b/ShortPlay/Base/View/SPTableViewCell.swift @@ -0,0 +1,83 @@ +// +// SPTableViewCell.swift +// ShortPlay +// +// Created by 曾觉新 on 2025/4/14. +// + +import UIKit + +class SPTableViewCell: UITableViewCell { + + var indicatorMargin: CGFloat = 7.5 { + didSet { + indicatorImageView.snp.updateConstraints { make in + make.right.equalToSuperview().offset(-indicatorMargin) + } + } + } + + var showIndicator = false { + didSet { + indicatorImageView.isHidden = !showIndicator + } + } + + private(set) lazy var indicatorImageView: UIImageView = { + let imageView = UIImageView(image: UIImage(named: "right_arrow_icon_01")) + imageView.isHidden = !showIndicator + return imageView + }() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + + self.layer.rasterizationScale = UIScreen.main.scale + self.layer.shouldRasterize = true + self.selectionStyle = .none + self.backgroundColor = .clear + + contentView.addSubview(indicatorImageView) + indicatorImageView.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.right.equalToSuperview().offset(-indicatorMargin) + } + + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } +} + +extension UITableViewCell { + + var sp_tableView: UITableView? { + return self.value(forKey: "_tableView") as? UITableView + } + + // MARK: - 注册 + public static func registerCell(tableView: UITableView, _ reuseIdentifier: String? = nil) { + let reuseIdentifier = reuseIdentifier == nil ? NSStringFromClass(self) : reuseIdentifier + tableView.register(self, forCellReuseIdentifier: reuseIdentifier!) + } + + // MARK: - 复用取值 + public static func dequeueReusableCell(tableView: UITableView, indexPath: IndexPath, _ reuseIdentifier: String? = nil) -> Self { + + let reuseIdentifier = reuseIdentifier == nil ? NSStringFromClass(self) : reuseIdentifier + let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier!, for: indexPath) + return cell as! Self + } +} diff --git a/ShortPlay/Base/WebView/SPWebView.swift b/ShortPlay/Base/WebView/SPWebView.swift new file mode 100644 index 0000000..2659e42 --- /dev/null +++ b/ShortPlay/Base/WebView/SPWebView.swift @@ -0,0 +1,201 @@ +// +// SPWebView.swift +// ShortPlay +// +// Created by 曾觉新 on 2025/4/14. +// + +import UIKit +@preconcurrency import WebKit + +class SPWebView: WKWebView { + + weak var delegate: SPWebViewDelegate? + + deinit { + + self.removeObserver(self, forKeyPath: "estimatedProgress") + self.removeObserver(self, forKeyPath: "title") + + } + + override init(frame: CGRect, configuration: WKWebViewConfiguration) { + super.init(frame: frame, configuration: configuration) +// addScriptMessageHandler() + _setupInit() + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + private func _setupInit() { + + self.isOpaque = false + self.uiDelegate = self + self.navigationDelegate = self + self.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil) + self.addObserver(self, forKeyPath: "title", options: .new, context: nil) + +// var userAgent = (self.value(forKey: "userAgent") as? String) ?? "" +// if !userAgent.contains(";jxdbBrowser") { +// userAgent = userAgent + ";jxdbBrowser|V\(kYDAPPVersion)" +// self.customUserAgent = userAgent +// } + } + + override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { + if object as? SPWebView == self { + if keyPath == "estimatedProgress", let progress = change?[NSKeyValueChangeKey.newKey] as? CGFloat { + self.delegate?.webView?(webView: self, didChangeProgress: progress) + } else if keyPath == "title", let title = change?[NSKeyValueChangeKey.newKey] as? String { + self.delegate?.webView?(webView: self, didChangeTitle: title) + } + } + } + + func load(urlStr: String) { + guard let url = URL(string: urlStr) else { return } + var request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 30) + self.load(request) + } + +} + +//MARK:-------------- WKUIDelegate -------------- +extension SPWebView: WKUIDelegate { + + func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) { + let alertController = UIAlertController(title: "提示", message: message, preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: "确认", style: .default, handler: { (action) in + completionHandler() + })) + self.viewController?.present(alertController, animated: true, completion: nil) + } + + func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) { + let alertController = UIAlertController(title: "提示", message: message, preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: "取消", style: .cancel, handler: { (action) in + completionHandler(false) + })) + alertController.addAction(UIAlertAction(title: "确认", style: .default, handler: { (action) in + completionHandler(true) + })) + self.viewController?.present(alertController, animated: true, completion: nil) + } + + func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) { + let alertController = UIAlertController(title: prompt, message: "", preferredStyle: .alert) + alertController.addTextField { (textField) in + textField.text = defaultText + } + alertController.addAction(UIAlertAction(title: "完成", style: .default, handler: { (action) in + completionHandler(alertController.textFields?.first?.text) + })) + self.viewController?.present(alertController, animated: true, completion: nil) + } +} + +//MARK:-------------- WKNavigationDelegate -------------- +extension SPWebView: WKNavigationDelegate { + + func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) { + /*同步cookie*/ +// let cookies = JXCookiesManager.getAllCookies() +// for cookie in cookies { +// setCookie(cookie: cookie) +// } + + decisionHandler(.allow); + } + + func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { + spLog(message: navigationAction.request.url) + +// if navigationAction.request.url?.scheme == "tel" { +// UIApplication.shared.openURL(navigationAction.request.url!) +// decisionHandler(.cancel) +// return +// } + if let url = navigationAction.request.url, + url.scheme != "http", + url.scheme != "https" + { + UIApplication.shared.open(url) + decisionHandler(.cancel) + return + } + + //防止抓包 +// if JXRequestHttpProxy.isIntercept() { +// decisionHandler(.cancel) +// return +// } + + + if let result = self.delegate?.webView?(self, shouldStartLoadWith: navigationAction) { + if result { + decisionHandler(.allow) + } else { + decisionHandler(.cancel) + } + } else { + decisionHandler(.allow) + } + } + + func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) { + self.delegate?.webViewDidStartLoad?(self) + } + + func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { + +// ///禁用长按展示长图 +// webView.evaluateJavaScript("document.documentElement.style.webkitTouchCallout='none';", completionHandler: nil) +// ///禁用长按选择图片文字 +// webView.evaluateJavaScript("document.documentElement.style.webkitUserSelect='none';", completionHandler: nil) + + + + self.delegate?.webViewDidFinishLoad?(self) + } + + func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { + self.delegate?.webView?(self, didFailLoadWithError: error) + } + + func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { + self.delegate?.webView?(self, didFailLoadWithError: error) + } + + +} + +//MARK:-------------- WKScriptMessageHandler -------------- +extension SPWebView: WKScriptMessageHandler { + + func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { + self.delegate?.userContentController?(userContentController, didReceive: message) + } + +} + + +//MARK:-------------- YDWebViewDelegate -------------- +@objc protocol SPWebViewDelegate: NSObjectProtocol { + + @objc optional func webView(_ webView: SPWebView, shouldStartLoadWith navigationAction: WKNavigationAction) -> Bool + + @objc optional func webViewDidStartLoad(_ webView: SPWebView) + + @objc optional func webViewDidFinishLoad(_ webView: SPWebView) + + @objc optional func webView(_ webView: SPWebView, didFailLoadWithError error: Error) + + ///进度 + @objc optional func webView(webView: SPWebView, didChangeProgress progress: CGFloat) + ///标题 + @objc optional func webView(webView: SPWebView, didChangeTitle title: String) + + ///web交互用 + @objc optional func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) + +} diff --git a/ShortPlay/Base/WebView/SPWebViewController.swift b/ShortPlay/Base/WebView/SPWebViewController.swift new file mode 100644 index 0000000..035f334 --- /dev/null +++ b/ShortPlay/Base/WebView/SPWebViewController.swift @@ -0,0 +1,89 @@ +// +// SPWebViewController.swift +// ShortPlay +// +// Created by 曾觉新 on 2025/4/14. +// + +import UIKit +import WebKit + +class SPWebViewController: SPViewController { + + var urlStr: String? + + private lazy var webView: SPWebView = { + let controller = WKUserContentController() + + let config = WKWebViewConfiguration() + config.userContentController = controller + config.preferences.javaScriptEnabled = true + /** 默认是不能通过JS自动打开窗口的,必须通过用户交互才能打开 */ + config.preferences.javaScriptCanOpenWindowsAutomatically = true + let webView = SPWebView(frame: self.view.bounds, configuration: config) + webView.delegate = self + return webView + }() + + override func viewDidLoad() { + super.viewDidLoad() + configNavigationBack() + + _setupUI() + + if let url = urlStr { + self.load(urlString: url) + } + } + + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.navigationController?.setNavigationBarHidden(false, animated: true) + self.setNavigationNormalStyle() + } + + func load(urlString: String) { +// guard let url = URL(string: "https://www.baidu.com") else { return } + var str: String = urlString +// if let userToken = ETLoginManager.manager.userInfo?.userToken { +// if urlString.contains("?") { +// str = urlString + "&userToken=\(userToken)" +// } else { +// str = urlString + "?userToken=\(userToken)" +// } +// } + + guard let url = URL(string: str) else { return } + var request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 30) + +// if ETLoginManager.manager.isLogin, let userToken = ETLoginManager.manager.userInfo?.userToken { +// request.setValue(userToken, forHTTPHeaderField: "userToken") +// } + + self.webView.load(request) + } + +} + +extension SPWebViewController { + + private func _setupUI() { + self.view.addSubview(webView) + self.webView.frame = self.view.bounds + self.webView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + } + +} + +//MARK: -------------- ETWebViewDelegate -------------- +extension SPWebViewController: SPWebViewDelegate { + + func webView(webView: SPWebView, didChangeTitle title: String) { + self.title = title + } + + func webView(_ webView: SPWebView, didFailLoadWithError error: any Error) { + spLog(message: error) + } +} diff --git a/ShortPlay/Class/Home/Controller/SPHomeChildController.swift b/ShortPlay/Class/Home/Controller/SPHomeChildController.swift new file mode 100644 index 0000000..b74e232 --- /dev/null +++ b/ShortPlay/Class/Home/Controller/SPHomeChildController.swift @@ -0,0 +1,24 @@ +// +// SPHomeChildController.swift +// ShortPlay +// +// Created by 曾觉新 on 2025/4/14. +// + +import UIKit + +class SPHomeChildController: SPViewController { + + var topMargins: CGFloat = 10 + + override func viewDidLoad() { + super.viewDidLoad() + + + } + + override func setBgImageView() { } + + + +} diff --git a/ShortPlay/Class/Home/Controller/SPHomePageController.swift b/ShortPlay/Class/Home/Controller/SPHomePageController.swift index f5c85e5..0d62450 100644 --- a/ShortPlay/Class/Home/Controller/SPHomePageController.swift +++ b/ShortPlay/Class/Home/Controller/SPHomePageController.swift @@ -9,23 +9,56 @@ import UIKit class SPHomePageController: SPViewController { + private var topModel: SPHomeTopModel? + + private lazy var categoryArr: [SPHomeCategoryModel] = { + let arr = [ + SPHomeCategoryModel(category_name: "Hot Picks".localized, category_id: nil, viewController: SPHomeViewController()), + SPHomeCategoryModel(category_name: "Top 10".localized, category_id: nil, viewController: nil), + SPHomeCategoryModel(category_name: "Fresh Drops".localized, category_id: nil, viewController: nil), + SPHomeCategoryModel(category_name: "Free".localized, category_id: nil, viewController: nil), + ] + return arr + }() + private lazy var pageView: JYPageController = { + let customIndicatorImage = UIImage(named: "page_indicator_icon_01") + let customIndicator = UIImageView(image: customIndicatorImage) + let pageView = JYPageController() pageView.delegate = self pageView.dataSource = self + pageView.config.normalTitleColor = .colorD2D2D2() + pageView.config.selectedTitleColor = .colorBF6BFF() + pageView.config.normalTitleFont = 14 + pageView.config.selectedTitleFont = 16 + pageView.config.normalTitleFontWeight = .regular + pageView.config.selectedTitleFontWeight = .medium + pageView.config.alignment = .scatter + pageView.config.customIndicator = customIndicator + pageView.config.indicatorStyle = .customView + pageView.config.indicatorWidth = customIndicatorImage?.size.width ?? 0 + pageView.config.indicatorHeight = customIndicatorImage?.size.height ?? 0 + pageView.config.leftPadding = 15 + pageView.config.rightPadding = 15 + pageView.config.itemsMargin = 24 return pageView }() + + override func viewDidLoad() { super.viewDidLoad() sp_setupUI() + + requestData() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - self.navigationController?.setNavigationBarHidden(false, animated: true) + self.navigationController?.setNavigationBarHidden(true, animated: true) } } @@ -37,7 +70,9 @@ extension SPHomePageController { view.addSubview(pageView.view) pageView.view.snp.makeConstraints { make in - make.edges.equalToSuperview() +// make.edges.equalToSuperview() + make.top.equalToSuperview().offset(kSPStatusbarHeight + 66) + make.left.right.bottom.equalToSuperview() } } } @@ -45,26 +80,47 @@ extension SPHomePageController { //MARK: -------------- JYPageControllerDelegate & JYPageControllerDataSource -------------- extension SPHomePageController: JYPageControllerDelegate, JYPageControllerDataSource { func pageController(_ pageController: JYPageController, frameForSegmentedView segmentedView: JYSegmentedView) -> CGRect { - return .init(x: 0, y: kSPStatusbarHeight + 10, width: kSPScreenWidth, height: 40) + return .init(x: 0, y: 0, width: kSPScreenWidth, height: 40) } func pageController(_ pageController: JYPageController, frameForContainerView container: UIScrollView) -> CGRect { - return .init(x: 0, y: 0, width: kSPScreenWidth, height: kSPScreenHeight - kSPTabBarHeight) + return .init(x: 0, y: 40, width: kSPScreenWidth, height: kSPScreenHeight - kSPTabBarHeight - kSPStatusbarHeight - 66 - 40) } func pageController(_ pageController: JYPageController, titleAt index: Int) -> String { - return "123" + return self.categoryArr[index].category_name ?? "" } func childController(atIndex index: Int) -> any JYPageChildContollerProtocol { - return SPViewController() + let vc = SPHomeViewController() + vc.topMargins = 15 + return vc } func numberOfChildControllers() -> Int { - return 0 + return self.categoryArr.count + } +} + + +extension SPHomePageController { + + private func requestData() { + if self.topModel != nil { return } + + + SPHomeAPI.requestHomeTopData { [weak self] model in + guard let self = self else { return } + if let model = model { + self.topModel = model + if let category = self.topModel?.category { + self.categoryArr += category + } + self.pageView.reload() + } + } + } - - } diff --git a/ShortPlay/Class/Home/Controller/SPHomeViewController.swift b/ShortPlay/Class/Home/Controller/SPHomeViewController.swift index 33c6ee6..12c42de 100644 --- a/ShortPlay/Class/Home/Controller/SPHomeViewController.swift +++ b/ShortPlay/Class/Home/Controller/SPHomeViewController.swift @@ -7,15 +7,88 @@ import UIKit -class SPHomeViewController: SPViewController { - +class SPHomeViewController: SPHomeChildController { + + ///模版数据 + private var moduleModel: SPHomeModuleModel? + + + private lazy var layout: UICollectionViewFlowLayout = { + let layout = UICollectionViewFlowLayout() + return layout + }() + + private lazy var collectionView: SPCollectionView = { + let collectionView = SPCollectionView(frame: .zero, collectionViewLayout: layout) + collectionView.delegate = self + collectionView.dataSource = self + collectionView.register(SPHomeHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "headerView") + SPCollectionViewCell.registerCell(collectionView: collectionView) + return collectionView + }() + override func viewDidLoad() { super.viewDidLoad() - +// view.backgroundColor = .clear + requestModuleData() + _setupUI() } - + override func fetchChildControllerScrollView() -> UIScrollView? { + return self.collectionView + } + +} + +extension SPHomeViewController { + + private func _setupUI() { + view.addSubview(self.collectionView); + + self.collectionView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + make.top.equalToSuperview().offset(topMargins) + } + } +} + +//MARK: -------------- UICollectionViewDelegate & UICollectionViewDataSource -------------- +extension SPHomeViewController: UICollectionViewDelegate, UICollectionViewDataSource { + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = SPCollectionViewCell.dequeueReusableCell(collectionView: collectionView, indexPath: indexPath) + return cell + } + + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return 0 + } + + func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { + if let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerView", for: indexPath) as? SPHomeHeaderView { + headerView.moduleModel = self.moduleModel + return headerView + } + return UICollectionReusableView() + } + + +} + + +extension SPHomeViewController { + + private func requestModuleData() { + SPHomeAPI.requestHomeModuleData { [weak self] model in + guard let self = self else { return } + if let model = model { + self.moduleModel = model + self.layout.headerReferenceSize = CGSize(width: kSPScreenWidth, height: SPHomeHeaderView.contentHeight(model: model)) + self.collectionView.reloadData() + } + } + } - } diff --git a/ShortPlay/Class/Home/Model/SPHomeCategoryModel.swift b/ShortPlay/Class/Home/Model/SPHomeCategoryModel.swift index bb63fb3..bf0aa35 100644 --- a/ShortPlay/Class/Home/Model/SPHomeCategoryModel.swift +++ b/ShortPlay/Class/Home/Model/SPHomeCategoryModel.swift @@ -6,11 +6,33 @@ // import UIKit +import SmartCodable -class SPHomeCategoryModel: SPModel { - +//class SPHomeCategoryModel: SPModel, SmartCodable { +// +// var category_name: String? +// var category_id: String? +// +// @IgnoredKey +// var viewController: SPViewController? +// +// +// init(category_name: String? = nil, category_id: String? = nil, viewController: SPViewController? = nil) { +// self.category_name = category_name +// self.category_id = category_id +// self.viewController = viewController +// } +// +// required init() { +// fatalError("init() has not been implemented") +// } +//} + +struct SPHomeCategoryModel: SmartCodable { var category_name: String? var category_id: String? + @IgnoredKey + var viewController: SPViewController? } diff --git a/ShortPlay/Class/Home/Model/SPHomeModuleModel.swift b/ShortPlay/Class/Home/Model/SPHomeModuleModel.swift new file mode 100644 index 0000000..1eea304 --- /dev/null +++ b/ShortPlay/Class/Home/Model/SPHomeModuleModel.swift @@ -0,0 +1,23 @@ +// +// SPHomeModuleModel.swift +// ShortPlay +// +// Created by 曾觉新 on 2025/4/14. +// + +import UIKit +import SmartCodable + +class SPHomeModuleModel: SPModel, SmartCodable { + + var bannerData: [SPShortModel]? + ///首页九宫格数据 + var recommandData: [SPShortModel]? + ///新剧列表 + var manualNewestRecommand: [SPShortModel]? + ///热门排行 + var hotData: [SPShortModel]? + + + +} diff --git a/ShortPlay/Class/Home/Model/SPHomeTopModel.swift b/ShortPlay/Class/Home/Model/SPHomeTopModel.swift new file mode 100644 index 0000000..3199ea1 --- /dev/null +++ b/ShortPlay/Class/Home/Model/SPHomeTopModel.swift @@ -0,0 +1,15 @@ +// +// SPHomeTopModel.swift +// ShortPlay +// +// Created by 曾觉新 on 2025/4/14. +// + +import UIKit +import SmartCodable + +class SPHomeTopModel: SPModel, SmartCodable { + + var category: [SPHomeCategoryModel]? + +} diff --git a/ShortPlay/Class/Home/View/SPHomeBannerCell.swift b/ShortPlay/Class/Home/View/SPHomeBannerCell.swift new file mode 100644 index 0000000..ba1b005 --- /dev/null +++ b/ShortPlay/Class/Home/View/SPHomeBannerCell.swift @@ -0,0 +1,78 @@ +// +// SPHomeBannerCell.swift +// ShortPlay +// +// Created by 曾觉新 on 2025/4/14. +// + +import UIKit + +class SPHomeBannerCell: ZKCycleScrollViewCell { + + + var model: SPShortModel? { + didSet { + coverImageView.sp_setImage(url: model?.horizontally_img) + titleLabel.text = model?.name + } + } + + private lazy var coverImageView: SPImageView = { + let imageView = SPImageView() + return imageView + }() + + private lazy var bottomView: SPGradientView = { + let view = SPGradientView() + view.colors = [UIColor.color121418(alpha: 0).cgColor, UIColor.color121418(alpha: 0.8).cgColor] + view.startPoint = CGPoint(x: 0.5, y: 0) + view.endPoint = CGPoint(x: 0.5, y: 1) + view.locations = [0, 1] + return view + }() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.font = .fontLight(ofSize: 14) + label.textColor = .colorFFFFFF(alpha: 0.9) + return label + }() + + override init(frame: CGRect) { + super.init(frame: frame) + contentView.layer.cornerRadius = 12 + contentView.layer.masksToBounds = true + + _setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +extension SPHomeBannerCell { + + private func _setupUI() { + contentView.addSubview(coverImageView) + contentView.addSubview(bottomView) + contentView.addSubview(titleLabel) + + coverImageView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + + bottomView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + make.height.equalTo(65) + } + + titleLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(7) + make.bottom.equalToSuperview().offset(-12) + make.right.lessThanOrEqualToSuperview().offset(-7) + } + + } + +} diff --git a/ShortPlay/Class/Home/View/SPHomeDataItemView.swift b/ShortPlay/Class/Home/View/SPHomeDataItemView.swift new file mode 100644 index 0000000..72b90f9 --- /dev/null +++ b/ShortPlay/Class/Home/View/SPHomeDataItemView.swift @@ -0,0 +1,87 @@ +// +// SPHomeDataItemView.swift +// ShortPlay +// +// Created by 曾觉新 on 2025/4/14. +// + +import UIKit + +class SPHomeDataItemView: UIView { + + ///内容距离顶部位置 + static let contentToTop: CGFloat = 36 + + + class func contentHeight(dataArr: [SPShortModel]) -> CGFloat { + return contentToTop + } + + override var intrinsicContentSize: CGSize { + let height = Self.contentHeight(dataArr: dataArr ?? []) + return CGSize(width: kSPScreenWidth, height: height) + } + + var dataArr: [SPShortModel]? { + didSet { + self.invalidateIntrinsicContentSize() + } + } + + private(set) lazy var titleLabel: UILabel = { + let label = UILabel() + label.font = .fontMedium(ofSize: 15) + label.textColor = .colorFFFFFF() + return label + }() + + private lazy var moreButton: UIButton = { + let button = UIButton(type: .custom) + button.setTitle("More", for: .normal) + button.setTitleColor(.colorF564B6(), for: .normal) + button.titleLabel?.font = .fontLight(ofSize: 12) + return button + }() + + private(set) lazy var contentView: UIView = { + let view = UIView() + return view + }() + + override init(frame: CGRect) { + super.init(frame: frame) + + _setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +extension SPHomeDataItemView { + + private func _setupUI() { + addSubview(titleLabel) + addSubview(moreButton) + addSubview(contentView) + + titleLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(15) + make.top.equalToSuperview() + make.height.equalTo(21) + } + + moreButton.snp.makeConstraints { make in + make.centerY.equalTo(moreButton) + make.right.equalToSuperview().offset(-15) + } + + contentView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + make.top.equalTo(Self.contentToTop) + } + } + +} diff --git a/ShortPlay/Class/Home/View/SPHomeHeaderView.swift b/ShortPlay/Class/Home/View/SPHomeHeaderView.swift new file mode 100644 index 0000000..28c2d0e --- /dev/null +++ b/ShortPlay/Class/Home/View/SPHomeHeaderView.swift @@ -0,0 +1,141 @@ +// +// SPHomeHeaderView.swift +// ShortPlay +// +// Created by 曾觉新 on 2025/4/14. +// + +import UIKit + +class SPHomeHeaderView: UICollectionReusableView { + + var moduleModel: SPHomeModuleModel? { + didSet { + stackView.removeAllArrangedSubview() + + stackView.addArrangedSubview(bannerView) + bannerView.reloadData() + +// if (moduleModel?.recommandData?.count ?? 0) > 0 { +// } + stackView.addArrangedSubview(trendingView) + trendingView.dataArr = moduleModel?.bannerData + + stackView.addArrangedSubview(hotView) + hotView.dataArr = moduleModel?.bannerData + + stackView.addArrangedSubview(shortsForYouView) + shortsForYouView.dataArr = moduleModel?.bannerData + + } + } + + private lazy var stackView: UIStackView = { + let view = UIStackView() + view.axis = .vertical + view.spacing = 25 + return view + }() + + private lazy var bannerView: ZKCycleScrollView = { + let bannerView = ZKCycleScrollView(frame: .zero, shouldInfiniteLoop: true); + bannerView.delegate = self + bannerView.dataSource = self + bannerView.itemSpacing = 10 + bannerView.itemSize = CGSize(width: kSPScreenWidth - 30, height: Self.bannerHeight()) + bannerView.register(SPHomeBannerCell.self, forCellWithReuseIdentifier: "bannerCell") + bannerView.hidesPageControl = true + bannerView.snp.makeConstraints { make in + make.width.equalTo(kSPScreenWidth) + make.height.equalTo(Self.bannerHeight()) + } + return bannerView + }() + + private lazy var trendingView: SPHomeTrendingView = { + let view = SPHomeTrendingView() + return view + }() + + private lazy var hotView: SPHomeHotView = { + let view = SPHomeHotView() + return view + }() + + private lazy var shortsForYouView: SPHomeShortsForYouView = { + let view = SPHomeShortsForYouView() + return view + }() + + override init(frame: CGRect) { + super.init(frame: frame) + _setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +extension SPHomeHeaderView { + + private func _setupUI() { + addSubview(stackView) + + stackView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + } + +} + +//MARK: -------------- ZKCycleScrollViewDelegate & ZKCycleScrollViewDataSource -------------- +extension SPHomeHeaderView: ZKCycleScrollViewDelegate, ZKCycleScrollViewDataSource { + + func numberOfItems(in cycleScrollView: ZKCycleScrollView) -> Int { + return moduleModel?.bannerData?.count ?? 0 + } + + func cycleScrollView(_ cycleScrollView: ZKCycleScrollView, cellForItemAt index: Int) -> ZKCycleScrollViewCell { + let cell = cycleScrollView.dequeueReusableCell(withReuseIdentifier: "bannerCell", for: index) as! SPHomeBannerCell + cell.model = moduleModel?.bannerData?[index] + return cell + } + + func cycleScrollView(_ cycleScrollView: ZKCycleScrollView, didSelectItemAt index: Int) { + let model = moduleModel?.bannerData?[index] + + let vc = SPTVPlayerListViewController() + vc.shortPlayId = model?.short_play_id + self.viewController?.navigationController?.pushViewController(vc, animated: true) + } + + +} + + +extension SPHomeHeaderView { + + static func contentHeight(model: SPHomeModuleModel) -> CGFloat { + var height = bannerHeight() + +// if (model.recommandData?.count ?? 0) > 0 { +// } + height = height + SPHomeTrendingView.contentHeight(dataArr: model.bannerData ?? []) + 25 + + + height = height + SPHomeHotView.contentHeight(dataArr: model.bannerData ?? []) + 25 + + height = height + SPHomeShortsForYouView.contentHeight(dataArr: model.bannerData ?? []) + 25 + + return height + } + + static func bannerHeight() -> CGFloat { + return 183 + } + + + +} diff --git a/ShortPlay/Class/Home/View/SPHomeHotCell.swift b/ShortPlay/Class/Home/View/SPHomeHotCell.swift new file mode 100644 index 0000000..0684219 --- /dev/null +++ b/ShortPlay/Class/Home/View/SPHomeHotCell.swift @@ -0,0 +1,96 @@ +// +// SPHomeHotCell.swift +// ShortPlay +// +// Created by 曾觉新 on 2025/4/14. +// + +import UIKit + +class SPHomeHotCell: SPCollectionViewCell { + + + var model: SPShortModel? { + didSet { + coverImageView.sp_setImage(url: model?.image_url) + titleLabel.text = model?.name + desLabel.text = model?.sp_description + } + } + + private lazy var bgView: UIView = { + let view = UIView() + view.backgroundColor = .colorFFFFFF(alpha: 0.1) + view.layer.cornerRadius = 12 + view.layer.masksToBounds = true + return view + }() + + private lazy var coverImageView: SPImageView = { + let imageView = SPImageView() + imageView.layer.cornerRadius = 6 + imageView.layer.masksToBounds = true + return imageView + }() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.font = .fontLight(ofSize: 14) + label.textColor = .colorFFFFFF(alpha: 0.9) + label.numberOfLines = 2 + return label + }() + + private lazy var desLabel: UILabel = { + let label = UILabel() + label.font = .fontLight(ofSize: 14) + label.textColor = .colorFFFFFF(alpha: 0.28) + label.numberOfLines = 2 + return label + }() + + override init(frame: CGRect) { + super.init(frame: frame) + _setupUI() + } + + @MainActor required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +extension SPHomeHotCell { + + private func _setupUI() { + contentView.addSubview(bgView) + contentView.addSubview(coverImageView) + contentView.addSubview(titleLabel) + contentView.addSubview(desLabel) + + bgView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + make.height.equalTo(116) + } + + coverImageView.snp.makeConstraints { make in + make.left.equalToSuperview().offset(15) + make.top.equalToSuperview() + make.width.equalTo(94) + make.height.equalTo(124) + } + + titleLabel.snp.makeConstraints { make in + make.left.equalTo(coverImageView.snp.right).offset(13) + make.top.equalTo(bgView).offset(10) + make.right.lessThanOrEqualToSuperview().offset(-10) + } + + desLabel.snp.makeConstraints { make in + make.left.equalTo(titleLabel) + make.bottom.equalTo(coverImageView) + make.right.lessThanOrEqualToSuperview().offset(-10) + } + } + +} diff --git a/ShortPlay/Class/Home/View/SPHomeHotView.swift b/ShortPlay/Class/Home/View/SPHomeHotView.swift new file mode 100644 index 0000000..41203db --- /dev/null +++ b/ShortPlay/Class/Home/View/SPHomeHotView.swift @@ -0,0 +1,91 @@ +// +// SPHomeHotView.swift +// ShortPlay +// +// Created by 曾觉新 on 2025/4/14. +// + +import UIKit + +class SPHomeHotView: SPHomeDataItemView { + + + override class func contentHeight(dataArr: [SPShortModel]) -> CGFloat { + if dataArr.count == 1 { + return 139 + contentToTop + } else { + return 139 * 2 + 15 + contentToTop + } + } + + override var dataArr: [SPShortModel]? { + didSet { + self.collectionView.reloadData() + } + } + + private lazy var collectionViewLayout: UICollectionViewFlowLayout = { + let layout = UICollectionViewFlowLayout() + layout.scrollDirection = .horizontal + layout.itemSize = CGSize(width: kSPScreenWidth - 15 - 20, height: 139) + layout.sectionInset = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15) + layout.minimumLineSpacing = 10 + layout.minimumInteritemSpacing = 15 + return layout + }() + + private lazy var collectionView: SPCollectionView = { + let collectionView = SPCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) + collectionView.delegate = self + collectionView.dataSource = self + collectionView.showsVerticalScrollIndicator = false + collectionView.showsHorizontalScrollIndicator = false + SPHomeHotCell.registerCell(collectionView: collectionView) + return collectionView + }() + + override init(frame: CGRect) { + super.init(frame: frame) + self.titleLabel.text = "Editor's Hotlist".localized + _setupUI() + } + + @MainActor required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +extension SPHomeHotView { + private func _setupUI() { + contentView.addSubview(collectionView) + + collectionView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + + } + +} + +//MARK: -------------- UICollectionViewDelegate & UICollectionViewDataSource -------------- +extension SPHomeHotView: UICollectionViewDelegate, UICollectionViewDataSource { + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = SPHomeHotCell.dequeueReusableCell(collectionView: collectionView, indexPath: indexPath) + cell.model = dataArr?[indexPath.row] + return cell + } + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return dataArr?.count ?? 0 + } + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + let model = self.dataArr?[indexPath.row] + + let vc = SPTVPlayerListViewController() + vc.shortPlayId = model?.short_play_id + self.viewController?.navigationController?.pushViewController(vc, animated: true) + } + +} diff --git a/ShortPlay/Class/Home/View/SPHomeShortsForYouCell.swift b/ShortPlay/Class/Home/View/SPHomeShortsForYouCell.swift new file mode 100644 index 0000000..ebaaa1e --- /dev/null +++ b/ShortPlay/Class/Home/View/SPHomeShortsForYouCell.swift @@ -0,0 +1,80 @@ +// +// SPHomeShortsForYouCell.swift +// ShortPlay +// +// Created by 曾觉新 on 2025/4/14. +// + +import UIKit + +class SPHomeShortsForYouCell: SPCollectionViewCell { + + + var model: SPShortModel? { + didSet { + coverImageView.sp_setImage(url: model?.horizontally_img) + titleLabel.text = model?.name + } + } + + private lazy var coverImageView: SPImageView = { + let imageView = SPImageView() + return imageView + }() + + private lazy var bottomView: SPGradientView = { + let view = SPGradientView() + view.colors = [UIColor.color121418(alpha: 0).cgColor, UIColor.color121418(alpha: 0.8).cgColor] + view.startPoint = CGPoint(x: 0.5, y: 0) + view.endPoint = CGPoint(x: 0.5, y: 1) + view.locations = [0, 1] + return view + }() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.font = .fontLight(ofSize: 14) + label.textColor = .colorFFFFFF(alpha: 0.9) + return label + }() + + override init(frame: CGRect) { + super.init(frame: frame) + + contentView.layer.cornerRadius = 12 + contentView.layer.masksToBounds = true + + _setupUI() + } + + @MainActor required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +extension SPHomeShortsForYouCell { + + private func _setupUI() { + contentView.addSubview(coverImageView) + contentView.addSubview(bottomView) + contentView.addSubview(titleLabel) + + coverImageView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + + bottomView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + make.height.equalTo(65) + } + + titleLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(7) + make.bottom.equalToSuperview().offset(-12) + make.right.lessThanOrEqualToSuperview().offset(-7) + } + + } + +} diff --git a/ShortPlay/Class/Home/View/SPHomeShortsForYouView.swift b/ShortPlay/Class/Home/View/SPHomeShortsForYouView.swift new file mode 100644 index 0000000..a797f22 --- /dev/null +++ b/ShortPlay/Class/Home/View/SPHomeShortsForYouView.swift @@ -0,0 +1,81 @@ +// +// SPHomeShortsForYouView.swift +// ShortPlay +// +// Created by 曾觉新 on 2025/4/14. +// + +import UIKit + +class SPHomeShortsForYouView: SPHomeDataItemView { + + + override class func contentHeight(dataArr: [SPShortModel]) -> CGFloat { + return 271 + contentToTop + } + + override var dataArr: [SPShortModel]? { + didSet { + self.collectionView.reloadData() + } + } + + + private lazy var collectionViewLayout: UICollectionViewFlowLayout = { + let layout = UICollectionViewFlowLayout() + layout.scrollDirection = .horizontal + layout.itemSize = CGSize(width: 204, height: 271) + layout.sectionInset = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15) + layout.minimumLineSpacing = 15 + layout.minimumInteritemSpacing = 15 + return layout + }() + + private lazy var collectionView: SPCollectionView = { + let collectionView = SPCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) + collectionView.delegate = self + collectionView.dataSource = self + collectionView.showsVerticalScrollIndicator = false + collectionView.showsHorizontalScrollIndicator = false + SPHomeShortsForYouCell.registerCell(collectionView: collectionView) + return collectionView + }() + + override init(frame: CGRect) { + super.init(frame: frame) + self.titleLabel.text = "Shorts for You".localized + + _setupUI() + } + + @MainActor required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +extension SPHomeShortsForYouView { + + private func _setupUI() { + contentView.addSubview(collectionView) + + collectionView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + } + +} + +//MARK: -------------- UICollectionViewDelegate & UICollectionViewDataSource -------------- +extension SPHomeShortsForYouView: UICollectionViewDelegate, UICollectionViewDataSource { + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = SPHomeShortsForYouCell.dequeueReusableCell(collectionView: collectionView, indexPath: indexPath) + return cell + } + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return dataArr?.count ?? 0 + } + +} diff --git a/ShortPlay/Class/Home/View/SPHomeTrendingCell.swift b/ShortPlay/Class/Home/View/SPHomeTrendingCell.swift new file mode 100644 index 0000000..9fa06cb --- /dev/null +++ b/ShortPlay/Class/Home/View/SPHomeTrendingCell.swift @@ -0,0 +1,91 @@ +// +// SPHomeTrendingCell.swift +// ShortPlay +// +// Created by 曾觉新 on 2025/4/14. +// + +import UIKit + +class SPHomeTrendingCell: SPCollectionViewCell { + + var model: SPShortModel? { + didSet { + coverImageView.sp_setImage(url: model?.image_url) + titleLabel.text = model?.name + } + } + + private lazy var coverImageView: SPImageView = { + let imageView = SPImageView() + imageView.layer.cornerRadius = 10 + imageView.layer.masksToBounds = true + return imageView + }() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.font = .fontLight(ofSize: 13) + label.textColor = .colorFFFFFF(alpha: 0.9) + label.numberOfLines = 2 + return label + }() + + private lazy var hotBgView: SPGradientView = { + let view = SPGradientView() + view.colors = [UIColor.colorF56490().cgColor, UIColor.colorBF6BFF().cgColor] + view.startPoint = .init(x: 0.5, y: 0) + view.endPoint = .init(x: 0.5, y: 1) + view.locations = [0, 1] + view.addRadius(topLeft: 0, topRight: 0, bottomLeft: 0, bottomRight: 6) + return view + }() + + private lazy var hotIconImageView: UIImageView = { + let imageView = UIImageView(image: UIImage(named: "hot_icon_01")) + return imageView + }() + + override init(frame: CGRect) { + super.init(frame: frame) + + _setupUI() + } + + @MainActor required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +extension SPHomeTrendingCell { + + private func _setupUI() { + contentView.addSubview(coverImageView) + contentView.addSubview(titleLabel) + coverImageView.addSubview(hotBgView) + hotBgView.addSubview(hotIconImageView) + + coverImageView.snp.makeConstraints { make in + make.left.right.top.equalToSuperview() + make.bottom.equalToSuperview().offset(-38) + } + + titleLabel.snp.makeConstraints { make in + make.left.equalToSuperview() + make.right.lessThanOrEqualToSuperview() + make.top.equalTo(coverImageView.snp.bottom).offset(5) + } + + hotBgView.snp.makeConstraints { make in + make.left.top.equalToSuperview() + make.width.equalTo(22) + make.height.equalTo(16) + } + + hotIconImageView.snp.makeConstraints { make in + make.center.equalToSuperview() + } + } + +} diff --git a/ShortPlay/Class/Home/View/SPHomeTrendingView.swift b/ShortPlay/Class/Home/View/SPHomeTrendingView.swift new file mode 100644 index 0000000..1fd9a23 --- /dev/null +++ b/ShortPlay/Class/Home/View/SPHomeTrendingView.swift @@ -0,0 +1,108 @@ +// +// SPHomeTrendingView.swift +// ShortPlay +// +// Created by 曾觉新 on 2025/4/14. +// + +import UIKit + +class SPHomeTrendingView: SPHomeDataItemView { + + private static func itemSize() -> CGSize { + let width = floor((kSPScreenWidth - 15 * 2 - 12 * 2) / 3) + let imageScale: CGFloat = 153 / 107 + let height = width * imageScale + 38 + + return CGSize(width: width, height: height) + } + + override class func contentHeight(dataArr: [SPShortModel]) -> CGFloat { + + var height = self.contentToTop + + var lineCount = dataArr.count / 3 + if dataArr.count % 3 > 0 { + lineCount += 1 + } + + let contentHeight = itemSize().height * CGFloat(lineCount) + 12 * CGFloat(lineCount - 1) + if contentHeight > 0 { + height += contentHeight + } else { + height += 1 + } + + return height + } + + override var dataArr: [SPShortModel]? { + didSet { + self.collectionView.reloadData() + } + } + + private lazy var collectionViewLayout: UICollectionViewFlowLayout = { + let layout = UICollectionViewFlowLayout() + layout.minimumLineSpacing = 12 + layout.minimumInteritemSpacing = 12 + layout.itemSize = Self.itemSize() + layout.sectionInset = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15) + return layout + }() + + private lazy var collectionView: SPCollectionView = { + let collectionView = SPCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) + collectionView.delegate = self + collectionView.dataSource = self + collectionView.isScrollEnabled = false + SPHomeTrendingCell.registerCell(collectionView: collectionView) + return collectionView + }() + + + override init(frame: CGRect) { + super.init(frame: frame) + + self.titleLabel.text = "Trending Now".localized + + _setupUI() + } + + @MainActor required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +extension SPHomeTrendingView { + + private func _setupUI() { + contentView.addSubview(collectionView) + + collectionView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + } + +} + +//MARK: -------------- UICollectionViewDataSource & UICollectionViewDelegate -------------- +extension SPHomeTrendingView: UICollectionViewDataSource, UICollectionViewDelegate { + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = SPHomeTrendingCell.dequeueReusableCell(collectionView: collectionView, indexPath: indexPath) + cell.model = dataArr?[indexPath.row] + return cell + } + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return dataArr?.count ?? 0 + } + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + let model = self.dataArr?[indexPath.row] + + let vc = SPTVPlayerListViewController() + vc.shortPlayId = model?.short_play_id + self.viewController?.navigationController?.pushViewController(vc, animated: true) + } +} diff --git a/ShortPlay/Class/Mine/Controller/SPMineViewController.swift b/ShortPlay/Class/Mine/Controller/SPMineViewController.swift index 84696af..b897a5d 100644 --- a/ShortPlay/Class/Mine/Controller/SPMineViewController.swift +++ b/ShortPlay/Class/Mine/Controller/SPMineViewController.swift @@ -8,10 +8,12 @@ import UIKit class SPMineViewController: SPViewController { - + + + override func viewDidLoad() { super.viewDidLoad() - + } diff --git a/ShortPlay/Class/Player/Controller/SPPlayerListViewController.swift b/ShortPlay/Class/Player/Controller/SPPlayerListViewController.swift index 909fe7f..81d437f 100644 --- a/ShortPlay/Class/Player/Controller/SPPlayerListViewController.swift +++ b/ShortPlay/Class/Player/Controller/SPPlayerListViewController.swift @@ -160,7 +160,10 @@ extension SPPlayerListViewController { view.addSubview(collectionView) collectionView.snp.makeConstraints { make in - make.edges.equalToSuperview() +// make.edges.equalToSuperview() + make.center.equalToSuperview() + make.width.equalTo(self.contentSize.width) + make.height.equalTo(self.contentSize.height) } } diff --git a/ShortPlay/Class/Player/Controller/SPTVPlayerListViewController.swift b/ShortPlay/Class/Player/Controller/SPTVPlayerListViewController.swift index f1b4aa8..9eae165 100644 --- a/ShortPlay/Class/Player/Controller/SPTVPlayerListViewController.swift +++ b/ShortPlay/Class/Player/Controller/SPTVPlayerListViewController.swift @@ -69,7 +69,7 @@ extension SPTVPlayerListViewController: SPPlayerListViewControllerDataSource { extension SPTVPlayerListViewController { private func requestDetailData() { - guard let videoId = self.videoId, let shortPlayId = self.shortPlayId else { return } + guard let shortPlayId = self.shortPlayId else { return } SPVideoAPI.requestVideoDetail(videoId: videoId, shortPlayId: shortPlayId) { [weak self] model in guard let self = self else { return } diff --git a/ShortPlay/Class/Player/Model/SPShortModel.swift b/ShortPlay/Class/Player/Model/SPShortModel.swift index a86003b..c25c34a 100644 --- a/ShortPlay/Class/Player/Model/SPShortModel.swift +++ b/ShortPlay/Class/Player/Model/SPShortModel.swift @@ -10,13 +10,13 @@ import SmartCodable class SPShortModel: SPModel, SmartCodable { + var id: String? var all_coins: String? var buy_type: String? var collect_total: String? var sp_description: String? var episode_total: Int? var horizontally_img: String? - var id: String? var image_url: String? var is_collect: Bool? var name: String? diff --git a/ShortPlay/Class/Player/View/SPPlayerControlView.swift b/ShortPlay/Class/Player/View/SPPlayerControlView.swift index fe3aa95..4403040 100644 --- a/ShortPlay/Class/Player/View/SPPlayerControlView.swift +++ b/ShortPlay/Class/Player/View/SPPlayerControlView.swift @@ -123,13 +123,13 @@ extension SPPlayerControlView { } @objc private func hadlePlayAndOrPaused() { -// self.viewModel?.handlePauseOrPlay?() + self.viewModel?.handlePauseOrPlay?() - guard let model = model as? SPShortModel else { return } - let vc = SPTVPlayerListViewController() - vc.shortPlayId = model.short_play_id - vc.videoId = model.video_info?.short_play_video_id - SPAPPTool.topViewController()?.navigationController?.pushViewController(vc, animated: true) +// guard let model = model as? SPShortModel else { return } +// let vc = SPTVPlayerListViewController() +// vc.shortPlayId = model.short_play_id +// vc.videoId = model.video_info?.short_play_video_id +// SPAPPTool.topViewController()?.navigationController?.pushViewController(vc, animated: true) } diff --git a/ShortPlay/Libs/Player/SPPlayer.swift b/ShortPlay/Libs/Player/SPPlayer.swift index fb89ef2..bd9bd3f 100644 --- a/ShortPlay/Libs/Player/SPPlayer.swift +++ b/ShortPlay/Libs/Player/SPPlayer.swift @@ -243,7 +243,7 @@ extension SPPlayer { player.playerDidToEnd = { [weak self] (asset) in guard let self = self else { return } if isLoop { - self.player.replay() + self.replay() } else { self.isPlaying = false self.delegate?.sp_playCompletion?(self) diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01.imageset/Contents.json b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01.imageset/Contents.json index 6aa90f6..b60f645 100644 --- a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01.imageset/Contents.json +++ b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01.imageset/Contents.json @@ -5,12 +5,12 @@ "scale" : "1x" }, { - "filename" : "Frame@2x.png", + "filename" : "home@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "Frame@3x.png", + "filename" : "home@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01.imageset/Frame@2x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01.imageset/Frame@2x.png deleted file mode 100644 index 57cf447..0000000 Binary files a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01.imageset/Frame@2x.png and /dev/null differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01.imageset/Frame@3x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01.imageset/Frame@3x.png deleted file mode 100644 index 1a09822..0000000 Binary files a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01.imageset/Frame@3x.png and /dev/null differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01.imageset/home@2x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01.imageset/home@2x.png new file mode 100644 index 0000000..c2c1c52 Binary files /dev/null and b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01.imageset/home@2x.png differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01.imageset/home@3x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01.imageset/home@3x.png new file mode 100644 index 0000000..ffe5557 Binary files /dev/null and b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01.imageset/home@3x.png differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01_selected.imageset/Contents.json b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01_selected.imageset/Contents.json index 6aa90f6..b60f645 100644 --- a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01_selected.imageset/Contents.json +++ b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01_selected.imageset/Contents.json @@ -5,12 +5,12 @@ "scale" : "1x" }, { - "filename" : "Frame@2x.png", + "filename" : "home@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "Frame@3x.png", + "filename" : "home@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01_selected.imageset/Frame@2x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01_selected.imageset/Frame@2x.png deleted file mode 100644 index 18132fe..0000000 Binary files a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01_selected.imageset/Frame@2x.png and /dev/null differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01_selected.imageset/Frame@3x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01_selected.imageset/Frame@3x.png deleted file mode 100644 index d46c83d..0000000 Binary files a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01_selected.imageset/Frame@3x.png and /dev/null differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01_selected.imageset/home@2x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01_selected.imageset/home@2x.png new file mode 100644 index 0000000..c41c38c Binary files /dev/null and b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01_selected.imageset/home@2x.png differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01_selected.imageset/home@3x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01_selected.imageset/home@3x.png new file mode 100644 index 0000000..e346704 Binary files /dev/null and b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_01_selected.imageset/home@3x.png differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02.imageset/Contents.json b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02.imageset/Contents.json index 6aa90f6..08d1e99 100644 --- a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02.imageset/Contents.json +++ b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02.imageset/Contents.json @@ -5,12 +5,12 @@ "scale" : "1x" }, { - "filename" : "Frame@2x.png", + "filename" : "Explore@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "Frame@3x.png", + "filename" : "Explore@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02.imageset/Explore@2x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02.imageset/Explore@2x.png new file mode 100644 index 0000000..86d500b Binary files /dev/null and b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02.imageset/Explore@2x.png differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02.imageset/Explore@3x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02.imageset/Explore@3x.png new file mode 100644 index 0000000..9feb3f6 Binary files /dev/null and b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02.imageset/Explore@3x.png differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02.imageset/Frame@2x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02.imageset/Frame@2x.png deleted file mode 100644 index a086e35..0000000 Binary files a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02.imageset/Frame@2x.png and /dev/null differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02.imageset/Frame@3x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02.imageset/Frame@3x.png deleted file mode 100644 index 4fdb930..0000000 Binary files a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02.imageset/Frame@3x.png and /dev/null differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02_selected.imageset/Contents.json b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02_selected.imageset/Contents.json index 6aa90f6..08d1e99 100644 --- a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02_selected.imageset/Contents.json +++ b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02_selected.imageset/Contents.json @@ -5,12 +5,12 @@ "scale" : "1x" }, { - "filename" : "Frame@2x.png", + "filename" : "Explore@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "Frame@3x.png", + "filename" : "Explore@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02_selected.imageset/Explore@2x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02_selected.imageset/Explore@2x.png new file mode 100644 index 0000000..8acae82 Binary files /dev/null and b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02_selected.imageset/Explore@2x.png differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02_selected.imageset/Explore@3x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02_selected.imageset/Explore@3x.png new file mode 100644 index 0000000..04d80d0 Binary files /dev/null and b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02_selected.imageset/Explore@3x.png differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02_selected.imageset/Frame@2x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02_selected.imageset/Frame@2x.png deleted file mode 100644 index 0c62624..0000000 Binary files a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02_selected.imageset/Frame@2x.png and /dev/null differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02_selected.imageset/Frame@3x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02_selected.imageset/Frame@3x.png deleted file mode 100644 index bbe4d51..0000000 Binary files a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_02_selected.imageset/Frame@3x.png and /dev/null differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05.imageset/Contents.json b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05.imageset/Contents.json index 6aa90f6..ceb7e15 100644 --- a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05.imageset/Contents.json +++ b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05.imageset/Contents.json @@ -5,12 +5,12 @@ "scale" : "1x" }, { - "filename" : "Frame@2x.png", + "filename" : "Me@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "Frame@3x.png", + "filename" : "Me@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05.imageset/Frame@2x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05.imageset/Frame@2x.png deleted file mode 100644 index 67dad40..0000000 Binary files a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05.imageset/Frame@2x.png and /dev/null differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05.imageset/Frame@3x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05.imageset/Frame@3x.png deleted file mode 100644 index 5876884..0000000 Binary files a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05.imageset/Frame@3x.png and /dev/null differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05.imageset/Me@2x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05.imageset/Me@2x.png new file mode 100644 index 0000000..f0c1586 Binary files /dev/null and b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05.imageset/Me@2x.png differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05.imageset/Me@3x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05.imageset/Me@3x.png new file mode 100644 index 0000000..77446bd Binary files /dev/null and b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05.imageset/Me@3x.png differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05_selected.imageset/Contents.json b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05_selected.imageset/Contents.json index 6aa90f6..ceb7e15 100644 --- a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05_selected.imageset/Contents.json +++ b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05_selected.imageset/Contents.json @@ -5,12 +5,12 @@ "scale" : "1x" }, { - "filename" : "Frame@2x.png", + "filename" : "Me@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "Frame@3x.png", + "filename" : "Me@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05_selected.imageset/Frame@2x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05_selected.imageset/Frame@2x.png deleted file mode 100644 index d2b8c94..0000000 Binary files a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05_selected.imageset/Frame@2x.png and /dev/null differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05_selected.imageset/Frame@3x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05_selected.imageset/Frame@3x.png deleted file mode 100644 index d4c523a..0000000 Binary files a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05_selected.imageset/Frame@3x.png and /dev/null differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05_selected.imageset/Me@2x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05_selected.imageset/Me@2x.png new file mode 100644 index 0000000..c6518d0 Binary files /dev/null and b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05_selected.imageset/Me@2x.png differ diff --git a/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05_selected.imageset/Me@3x.png b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05_selected.imageset/Me@3x.png new file mode 100644 index 0000000..8998f5e Binary files /dev/null and b/ShortPlay/Source/Assets.xcassets/TabBar/tabbar_icon_05_selected.imageset/Me@3x.png differ diff --git a/ShortPlay/Source/Assets.xcassets/icon/Contents.json b/ShortPlay/Source/Assets.xcassets/icon/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/ShortPlay/Source/Assets.xcassets/icon/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ShortPlay/Source/Assets.xcassets/icon/hot_icon_01.imageset/Contents.json b/ShortPlay/Source/Assets.xcassets/icon/hot_icon_01.imageset/Contents.json new file mode 100644 index 0000000..5472a49 --- /dev/null +++ b/ShortPlay/Source/Assets.xcassets/icon/hot_icon_01.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "hot@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "hot@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ShortPlay/Source/Assets.xcassets/icon/hot_icon_01.imageset/hot@2x.png b/ShortPlay/Source/Assets.xcassets/icon/hot_icon_01.imageset/hot@2x.png new file mode 100644 index 0000000..49c454f Binary files /dev/null and b/ShortPlay/Source/Assets.xcassets/icon/hot_icon_01.imageset/hot@2x.png differ diff --git a/ShortPlay/Source/Assets.xcassets/icon/hot_icon_01.imageset/hot@3x.png b/ShortPlay/Source/Assets.xcassets/icon/hot_icon_01.imageset/hot@3x.png new file mode 100644 index 0000000..7eb28b0 Binary files /dev/null and b/ShortPlay/Source/Assets.xcassets/icon/hot_icon_01.imageset/hot@3x.png differ diff --git a/ShortPlay/Source/Assets.xcassets/icon/page_indicator_icon_01.imageset/Contents.json b/ShortPlay/Source/Assets.xcassets/icon/page_indicator_icon_01.imageset/Contents.json new file mode 100644 index 0000000..76d0040 --- /dev/null +++ b/ShortPlay/Source/Assets.xcassets/icon/page_indicator_icon_01.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "路径 497@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "路径 497@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ShortPlay/Source/Assets.xcassets/icon/page_indicator_icon_01.imageset/路径 497@2x.png b/ShortPlay/Source/Assets.xcassets/icon/page_indicator_icon_01.imageset/路径 497@2x.png new file mode 100644 index 0000000..cd3a7c8 Binary files /dev/null and b/ShortPlay/Source/Assets.xcassets/icon/page_indicator_icon_01.imageset/路径 497@2x.png differ diff --git a/ShortPlay/Source/Assets.xcassets/icon/page_indicator_icon_01.imageset/路径 497@3x.png b/ShortPlay/Source/Assets.xcassets/icon/page_indicator_icon_01.imageset/路径 497@3x.png new file mode 100644 index 0000000..9c71617 Binary files /dev/null and b/ShortPlay/Source/Assets.xcassets/icon/page_indicator_icon_01.imageset/路径 497@3x.png differ diff --git a/ShortPlay/Source/Assets.xcassets/image/Contents.json b/ShortPlay/Source/Assets.xcassets/image/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/ShortPlay/Source/Assets.xcassets/image/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ShortPlay/Source/Assets.xcassets/image/main_bg_image_01.imageset/Contents.json b/ShortPlay/Source/Assets.xcassets/image/main_bg_image_01.imageset/Contents.json new file mode 100644 index 0000000..36577cc --- /dev/null +++ b/ShortPlay/Source/Assets.xcassets/image/main_bg_image_01.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "bg@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "bg@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ShortPlay/Source/Assets.xcassets/image/main_bg_image_01.imageset/bg@2x.png b/ShortPlay/Source/Assets.xcassets/image/main_bg_image_01.imageset/bg@2x.png new file mode 100644 index 0000000..31058f2 Binary files /dev/null and b/ShortPlay/Source/Assets.xcassets/image/main_bg_image_01.imageset/bg@2x.png differ diff --git a/ShortPlay/Source/Assets.xcassets/image/main_bg_image_01.imageset/bg@3x.png b/ShortPlay/Source/Assets.xcassets/image/main_bg_image_01.imageset/bg@3x.png new file mode 100644 index 0000000..31c4553 Binary files /dev/null and b/ShortPlay/Source/Assets.xcassets/image/main_bg_image_01.imageset/bg@3x.png differ diff --git a/ShortPlay/Source/en.lproj/Localizable.strings b/ShortPlay/Source/en.lproj/Localizable.strings index d70f758..7a783b8 100644 --- a/ShortPlay/Source/en.lproj/Localizable.strings +++ b/ShortPlay/Source/en.lproj/Localizable.strings @@ -10,3 +10,10 @@ "For You" = "For You"; "Error" = "Error"; "Profile" = "Profile"; +"Hot Picks" = "Hot Picks"; +"Top 10" = "Top 10"; +"Fresh Drops" = "Fresh Drops"; +"Free" = "Free"; +"Trending Now" = "Trending Now"; +"Editor's Hotlist" = "Editor's Hotlist"; +"Shorts for You" = "Shorts for You"; diff --git a/ShortPlay/Thirdparty/JYPageController/Classes/JYPageConfig.swift b/ShortPlay/Thirdparty/JYPageController/Classes/JYPageConfig.swift index c5926be..0066f2c 100644 --- a/ShortPlay/Thirdparty/JYPageController/Classes/JYPageConfig.swift +++ b/ShortPlay/Thirdparty/JYPageController/Classes/JYPageConfig.swift @@ -14,6 +14,8 @@ import UIKit } @objc public enum JYSegmentedViewAlignment: Int { + ///平铺 + case scatter case left case right case center diff --git a/ShortPlay/Thirdparty/JYPageController/Classes/JYPageController.swift b/ShortPlay/Thirdparty/JYPageController/Classes/JYPageController.swift index 232709f..e7130c8 100644 --- a/ShortPlay/Thirdparty/JYPageController/Classes/JYPageController.swift +++ b/ShortPlay/Thirdparty/JYPageController/Classes/JYPageController.swift @@ -541,8 +541,8 @@ extension JYPageController: UITableViewDelegate, UITableViewDataSource { cell.backgroundColor = .clear cell.selectionStyle = .none // pageContentScrollView.frame = CGRect(x: 0, y: 0, width: childControllerViewFrame.width, height: childControllerViewFrame.height) - cell.contentView.addSubview(segmentedView) cell.contentView.addSubview(pageContentScrollView) + cell.contentView.addSubview(segmentedView) return cell } } diff --git a/ShortPlay/Thirdparty/JYPageController/Classes/JYSegmentedView.swift b/ShortPlay/Thirdparty/JYPageController/Classes/JYSegmentedView.swift index 11919ac..6e842e6 100644 --- a/ShortPlay/Thirdparty/JYPageController/Classes/JYSegmentedView.swift +++ b/ShortPlay/Thirdparty/JYPageController/Classes/JYSegmentedView.swift @@ -523,12 +523,17 @@ public class JYSegmentedView: UIView { private func updateItemsFrame() { let width = calculateTotalWidth() var startX: CGFloat = config.leftPadding - if config.alignment == .center, width < frame.width { - startX = (frame.width - width)/2 + config.leftPadding - } + var itemsMargin = config.itemsMargin - if config.alignment == .right, width < frame.width { + if config.alignment == .center, width < frame.width { + startX = (frame.width - width)/2 + + } else if config.alignment == .right, width < frame.width { startX = frame.width - width + + } else if config.alignment == .scatter, width < frame.width { + let itemTotalWidth = itemTotalWidth() + itemsMargin = (self.frame.size.width - itemTotalWidth - config.leftPadding - config.rightPadding) / CGFloat(items.count - 1) } var totalWidth: CGFloat = 0 @@ -538,9 +543,9 @@ public class JYSegmentedView: UIView { item.badgeView?.frame = CGRect(x: item.frame.width + config.badgeViewOffset.x, y: item.frame.origin.y - item.badgeViewHeight/2 + config.badgeViewOffset.y, width: item.badgeViewWidth, height: item.badgeViewHeight) totalWidth = startX + item.frame.width }else{ - item.frame = CGRect(x: totalWidth + config.itemsMargin , y: item.frame.origin.y, width: item.frame.width, height: item.frame.height) + item.frame = CGRect(x: totalWidth + itemsMargin , y: item.frame.origin.y, width: item.frame.width, height: item.frame.height) item.badgeView?.frame = CGRect(x: item.frame.width + item.frame.origin.x + config.badgeViewOffset.x, y: item.frame.origin.y - item.badgeViewHeight/2 + config.badgeViewOffset.y, width: item.badgeViewWidth, height: item.badgeViewHeight) - totalWidth = totalWidth + item.frame.width + config.itemsMargin + totalWidth = totalWidth + item.frame.width + itemsMargin } let bgView = self.itemBackgroundViews[index] @@ -556,6 +561,14 @@ public class JYSegmentedView: UIView { contentView.contentSize = CGSize(width: totalWidth + config.rightPadding, height: frame.size.height) } + private func itemTotalWidth() -> CGFloat { + var totalWidth: CGFloat = 0 + for (index,item) in items.enumerated() { + totalWidth = totalWidth + item.frame.width + } + return totalWidth + } + private func calculateTotalWidth() -> CGFloat { var totalWidth: CGFloat = 0 for (index,item) in items.enumerated() {