Commit 586f057f authored by edy's avatar edy

home

parent 2e432d2c
......@@ -40,10 +40,22 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
let window = UIApplication.shared.windows.first
let topPadding = window?.safeAreaInsets.top ?? 0
statusBarHeight = topPadding > 0 ? topPadding:20
navHeight = navDefaultHeight + statusBarHeight
navCenterY = 22 + statusBarHeight
}else {
statusBarHeight = UIApplication.shared.statusBarFrame.size.height
navHeight = navDefaultHeight + statusBarHeight
navCenterY = 22 + statusBarHeight
}
if #available(iOS 11.0, *) {
safeHeight = UIApplication.shared.delegate?.window??.safeAreaInsets.bottom ?? 0
}else {
safeHeight = 0
}
}
......
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "nav_back.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "nav_back@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "nav_back@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_charging_home_pre.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_charging_home_pre@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_charging_home_pre@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_cmpress_home_pre.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_cmpress_home_pre@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_cmpress_home_pre@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_contacts_home_pre.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_contacts_home_pre@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_contacts_home_pre@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_email_home_pre.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_email_home_pre@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_email_home_pre@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_secret_home_pre.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_secret_home_pre@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_secret_home_pre@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_pro_home.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_pro_home@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_pro_home@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "home_pro_star_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "home_pro_star_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "home_pro_star_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "home_setting_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "home_setting_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "home_setting_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "home_setting_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "home_setting_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "home_setting_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
//
// BaseNavView.swift
// PhoneManager
//
// Created by edy on 2025/3/21.
//
import UIKit
class BaseNavView:UIView {
var callBack: callBack<Any> = {text in }
lazy var model:BaseNavViewModel = {
let model :BaseNavViewModel = BaseNavViewModel()
model.callBack = {[weak self] (text) in
self?.setupUI()
}
return model
}()
lazy var lineView:UIView = {
let sview:UIView = UIView()
sview.width = width
sview.height = 0.5
sview.y = height - 0.5
sview.x = 0
sview.backgroundColor = UIColor.colorWithHex(hexStr: whiteColor, alpha: 0.08)
return sview
}()
lazy var titleLabel:UILabel = {
let titleLabel:UILabel = UILabel()
titleLabel.font = UIFont.systemFont(ofSize: 18.RW(), weight: .medium)
titleLabel.textColor = UIColor.colorWithHex(hexStr: whiteColor)
titleLabel.textAlignment = .center
return titleLabel
}()
lazy var backBtn:EnlargeBtn = {
let sview:EnlargeBtn = EnlargeBtn(frame: CGRect(x: 0, y: 0, width: iconWH, height: iconWH))
sview.setBackgroundImage(UIImage(named: "nav_back"), for: .normal)
sview.height = iconWH
sview.width = iconWH
sview.x = marginLR
sview.centerY = (height - statusBarHeight) / 2 + statusBarHeight
sview.addTarget(self, action: #selector(backBtnClick(btn:)), for: .touchUpInside)
return sview
}()
override init(frame: CGRect) {
super.init(frame: CGRect(x: 0, y: 0, width: ScreenW, height: navHeight))
setupUI()
addView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupUI() {
backgroundColor = UIColor.colorWithHex(hexStr: model.backgroundColor)
titleLabel.text = model.title
titleLabel.sizeToFit()
titleLabel.width = width - 2 * marginLR - (iconWH + 8.RW()) * 2
titleLabel.centerX = width / 2
titleLabel.centerY = (height - statusBarHeight) / 2 + statusBarHeight
titleLabel.isHidden = model.titleHidden
if model.titleLabelX != 0{
titleLabel.x = backBtn.x + backBtn.width + model.titleLabelX
titleLabel.width = width - titleLabel.x - 30.RW() - 28.RW()
}
backBtn.isHidden = !model.isBackBtnShow
}
func addView() {
addSubview(lineView)
addSubview(titleLabel)
addSubview(backBtn)
}
@objc func backBtnClick(btn:UIButton) {
callBack("back")
}
}
class BaseNavViewModel {
var callBack: callBack<Any> = {text in }
var title:String = "Title" {
didSet {
callBack("title")
}
}
var backgroundColor:String = navBack {
didSet {
callBack("backgroundColor")
}
}
var isBackBtnShow:Bool = false {
didSet {
callBack("isBackBtnShow")
}
}
var titleLabelX:CGFloat = 0 {
didSet {
callBack("titleLabelX")
}
}
var titleHidden:Bool = false {
didSet {
callBack("titleHidden")
}
}
}
//
// BaseViewController.swift
// PhoneManager
//
// Created by edy on 2025/3/21.
//
import UIKit
class BaseViewController:UIViewController {
var barStatyl:UIStatusBarStyle = .darkContent {
didSet {
DispatchQueue.main.async {[weak self] in
guard let self else {return}
self.setNeedsStatusBarAppearanceUpdate()
self.setStatusBarStyle(style: barStatyl)
}
}
}
var barHidden:Bool = false {
didSet {
DispatchQueue.main.async {[weak self] in
guard let self else {return}
self.setNeedsStatusBarAppearanceUpdate()
self.setStatusBarHidden(isHidden: barHidden)
}
}
}
var cIsPopGestureRecognizer:Bool = true {
didSet {
DispatchQueue.main.async {[weak self] in
guard let self else {return}
guard let nav = self.navigationController as? BaseNavViewController else {return}
nav.cIsPopGestureRecognizer = self.cIsPopGestureRecognizer
}
}
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return barStatyl
}
override var prefersStatusBarHidden:Bool {
return barHidden
}
lazy var titleView:BaseNavView = {
let titleView:BaseNavView = BaseNavView()
if navigationController?.children.count ?? 0 > 1 {
titleView.model.isBackBtnShow = true
}else {
titleView.model.isBackBtnShow = false
}
titleView.callBack = {[weak self] text in
if text as? String == "back" {
self?.close()
}
}
return titleView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.colorWithHex(hexStr: dBackColor)
addViews()
}
func addViews() {
view.addSubview(titleView)
}
func close(animation:Bool = true) {
if navigationController?.children.count ?? 0 > 1 {
navigationController?.popViewController(animated: animation)
}else {
navigationController?.dismiss(animated: animation)
}
}
func removeViewControllerOfType<T: UIViewController>(type: T.Type) {
guard var viewControllers = self.navigationController?.viewControllers else { return }
// 过滤掉特定类型的视图控制器
viewControllers.removeAll { $0 is T }
// 设置过滤后的视图控制器栈
self.navigationController?.setViewControllers(viewControllers, animated: true)
}
}
//
// BaseWebViewController.swift
// PhoneManager
//
// Created by edy on 2025/3/21.
//
import Foundation
import UIKit
@preconcurrency import WebKit
class BaseWebViewController:BaseViewController {
lazy var funcNameArray:[String] = []
lazy var webView: WKWebView = {
let webConfiguration = WKWebViewConfiguration()
webConfiguration.applicationNameForUserAgent = "iOS"
let webView1:WKWebView = WKWebView(frame:CGRect(x: 0, y: navHeight, width: ScreenW, height: ScreenH - navHeight),configuration: webConfiguration)
webView1.scrollView.showsVerticalScrollIndicator = false
webView1.scrollView.showsHorizontalScrollIndicator = false
webView1.allowsLinkPreview = false
webView1.scrollView.backgroundColor = .white
webView1.allowsBackForwardNavigationGestures = true
webView1.backgroundColor = .white
webView1.uiDelegate = self
webView1.navigationDelegate = self
webView1.scrollView.delegate = self
if #available(iOS 11.0, *) {
webView1.scrollView.contentInsetAdjustmentBehavior = .never
}
for name in funcNameArray {
webView1.configuration.userContentController.add(self, name: name)
}
return webView1
}()
lazy var activityView:UIActivityIndicatorView = {
let activityView = UIActivityIndicatorView()
activityView.width = 24.RW()
activityView.height = 24.RW()
activityView.centerX = view.width / 2
activityView.centerY = (view.height - navHeight) / 2
activityView.color = .black
activityView.hidesWhenStopped = true
let transform:CGAffineTransform = CGAffineTransformMakeScale(24.RW() / 20,24.RW() / 20);
activityView.transform = transform;
activityView.startAnimating()
return activityView
}()
func LoadWithUrl(url:String) {
if url.count == 0 {
return
}
let newUrl = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
guard let URL1 = URL(string:newUrl) else { return }
let request = URLRequest(url: URL1)
webView.load(request)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.cIsPopGestureRecognizer = true
}
override func addViews() {
super.addViews()
view.addSubview(webView)
view.addSubview(activityView)
}
}
extension BaseWebViewController:WKUIDelegate,WKNavigationDelegate {
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
activityView.stopAnimating()
webView.evaluateJavaScript("document.documentElement.style.webkitUserSelect='none';") { any1, error1 in}
webView.evaluateJavaScript("document.documentElement.style.webkitTouchCallout='none';", completionHandler: nil)
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
activityView.stopAnimating()
Print("网页加载失败:\(error.localizedDescription)")
}
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
activityView.stopAnimating()
Print("网页加载失败:\(error.localizedDescription)")
}
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
decisionHandler(WKNavigationActionPolicy.allow)
}
}
extension BaseWebViewController:WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
}
}
extension BaseWebViewController:UIScrollViewDelegate {
}
......@@ -7,15 +7,22 @@
import UIKit
class HomeViewController:UIViewController {
private var isShowPay:Bool = false
private var homeView:HomeView?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
homeView = HomeView(frame: view.bounds)
view.addSubview(homeView!)
}
override func viewDidAppear(_ animated: Bool) {
......
//
// HomeTabbarItem.swift
// PhoneManager
//
// Created by edy on 2025/3/21.
//
import Foundation
func loadTabbarImtesSONFromBundle() -> [HomeTabbarItem]? {
// 获取 JSON 文件路径
guard let path = Bundle.main.path(forResource: "TabbarImtesData", ofType: "json") else {
print("未找到 JSON 文件")
return nil
}
do {
// 读取文件内容
let data = try Data(contentsOf: URL(fileURLWithPath: path))
// 解析 JSON 数据
let decoder = JSONDecoder()
let items = try decoder.decode([HomeTabbarItem].self, from: data)
return items
} catch {
print("解析 JSON 失败:\(error)")
return nil
}
}
struct HomeTabbarItem:Codable {
var normalImage:String
var heightImage:String
var text:String
enum Category: String, Codable {
case normalImage,heightImage,text
}
}
[
{
"normalImage": "ic_charging_home_pre",
"heightImage": "tabbar_Charging_high",
"text":"Charging",
},
{
"normalImage": "ic_secret_home_pre",
"heightImage": "tabbar_secret_hight",
"text":"Secret Space",
},
{
"normalImage": "ic_contacts_home_pre",
"heightImage": "tabbar_contacts_high",
"text":"Contacts",
},
{
"normalImage": "ic_email_home_pre",
"heightImage": "tabbar_email_high",
"text":"Email Cleaner",
},
{
"normalImage": "ic_cmpress_home_pre",
"heightImage": "tabbar_cmpress_high",
"text":"Compress",
}
]
//
// HomeNavView.swift
// PhoneManager
//
// Created by edy on 2025/3/21.
//
import UIKit
class HomeNavView:UIView {
private var titleLabel:UILabel!
private var settingBtn:UIButton!
private var proBtn:UIButton!
private var tipLabel:UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupUI() {
backgroundColor = .white
titleLabel = UILabel()
titleLabel.text = "Cleanup"
titleLabel.font = UIFont.systemFont(ofSize: 20, weight: .bold)
titleLabel.textColor = UIColor.colorWithHex(hexStr: black3Color)
titleLabel.sizeToFit()
self.addSubview(titleLabel)
titleLabel.snp.makeConstraints { make in
make.centerY.equalTo(navCenterY)
make.left.equalTo(marginLR)
}
settingBtn = UIButton()
settingBtn.setImage(UIImage(named: "home_setting_icon"), for: .normal)
settingBtn.addTarget(self, action: #selector(settingBtnClick), for: .touchUpInside)
self.addSubview(settingBtn)
settingBtn.snp.makeConstraints { make in
make.centerY.equalTo(navCenterY)
make.right.equalToSuperview().offset(-marginLR)
make.width.height.equalTo(iconWH)
}
proBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 70, height: iconWH))
proBtn.setBackgroundImage(UIImage(named: "home_pro_star_back"), for: .normal)
proBtn.addTarget(self, action: #selector(settingBtnClick), for: .touchUpInside)
self.addSubview(proBtn)
proBtn.snp.makeConstraints { make in
make.centerY.equalTo(navCenterY)
make.right.equalTo(settingBtn.snp.left).offset(-8)
make.width.equalTo(70)
make.height.equalTo(iconWH)
}
tipLabel = UILabel()
tipLabel.numberOfLines = 0 // 支持多行
tipLabel.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(tipLabel)
// 设置文本内容
let text = "202 files · 1.15 GB of storage to clean up"
let attributedText = NSMutableAttributedString(string: text)
// 设置整体文本样式
let fullTextAttributes: [NSAttributedString.Key: Any] = [
.font: UIFont.systemFont(ofSize: 14),
.foregroundColor: UIColor(red: 102/255, green: 102/255, blue: 102/255, alpha: 1) // #666666
]
attributedText.addAttributes(fullTextAttributes, range: NSRange(location: 0, length: text.count))
// 设置 "202" 为蓝色
if let range1 = text.range(of: "202") {
let nsRange1 = NSRange(range1, in: text)
attributedText.addAttributes([
.foregroundColor: UIColor.colorWithHex(hexStr: mColor)
], range: nsRange1)
}
// 设置 "1.15 GB" 为蓝色
if let range2 = text.range(of: "1.15 GB") {
let nsRange2 = NSRange(range2, in: text)
attributedText.addAttributes([
.foregroundColor: UIColor.colorWithHex(hexStr: mColor)
], range: nsRange2)
}
// 将 attributedText 赋值给 UILabel
tipLabel.attributedText = attributedText
tipLabel.snp.makeConstraints { make in
make.bottom.equalToSuperview().offset(-16)
make.centerX.equalToSuperview()
make.width.equalToSuperview().offset(-2 * marginLR)
}
}
@objc private func settingBtnClick() {
}
}
//
// HomeTabbarView.swift
// PhoneManager
//
// Created by edy on 2025/3/21.
//
import UIKit
class HomeTabbarView:UIView {
private var tabbarItems:[HomeTabbarItem] = []
override init(frame: CGRect) {
super.init(frame: frame)
getData()
setupUI()
addButton()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupUI() {
backgroundColor = .white
self.setShadow(cornerRadius: 20)
}
private func addButton() {
let cW:CGFloat = (self.width - 16) / Double(tabbarItems.count)
let cH:CGFloat = 54
for (index,item) in tabbarItems.enumerated() {
let btn:UIButton = UIButton()
btn.setImage(UIImage(named: item.normalImage), for: .normal)
btn.setTitleColor(UIColor.colorWithHex(hexStr: black6Color), for: .normal)
btn.titleLabel?.font = UIFont.systemFont(ofSize: 10, weight: .bold)
btn.setTitle(item.text, for: .normal)
btn.addTarget(self, action: #selector(tabbarClick(_:)), for: .touchUpInside)
btn.width = cW
btn.height = cH
btn.y = 12
btn.x = 8 + Double(index) * cW
btn.changBtnWithStytl(btnStyle: .imageTop, margin: 5)
self.addSubview(btn)
}
}
private func getData() {
tabbarItems = loadTabbarImtesSONFromBundle() ?? []
}
@objc func tabbarClick(_ btn:UIButton) {
}
}
//
// HomeView.swift
// PhoneManager
//
// Created by edy on 2025/3/21.
//
import UIKit
import SnapKit
class HomeView:UIView {
private var homeTabbarView:HomeTabbarView?
private var homeNavView:HomeNavView?
private var bottomView:UIView?
private var titleModels:[HomePhotosModel] = []
private var contentModels:[String] = ["123","1234","12323","12"]
lazy var collectionView:UICollectionView = {
let cY:CGFloat = 16.RW()
let layout = WaterfallMutiSectionFlowLayout()
layout.delegate = self
let sview:UICollectionView = UICollectionView.init(frame: CGRect(x: marginLR, y: cY, width: width - 2 * marginLR, height: height - cY), collectionViewLayout: layout)
sview.dataSource = self
sview.delegate = self
sview.showsVerticalScrollIndicator = false
sview.register(HomeTitleCollectionCell.self, forCellWithReuseIdentifier: HomeTitleCollectionCell.identifiers)
sview.backgroundColor = .clear
return sview
}()
override init(frame: CGRect) {
super.init(frame: frame)
setData()
setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setData() {
let model:HomePhotosModel = HomePhotosModel(folderName: "Duplicates", filePaths: [], firstItemPath: "dfdf", allFileSize: 123213132)
titleModels.append(model)
titleModels.append(model)
}
private func setupUI() {
backgroundColor = .white
homeTabbarView = HomeTabbarView(frame: CGRect(x: 0, y: 0, width: self.width, height: safeHeight + 66))
self.addSubview(homeTabbarView!)
homeTabbarView?.snp.makeConstraints({ make in
make.bottom.centerX.width.equalToSuperview()
make.height.equalTo(safeHeight + 66)
})
homeNavView = HomeNavView(frame: CGRect(x: 0, y: 0, width: width, height: statusBarHeight + 96))
self.addSubview(homeNavView!)
homeNavView?.snp.makeConstraints({ make in
make.top.centerX.width.equalToSuperview()
make.height.equalTo(statusBarHeight + 96)
})
bottomView = UIView(frame: CGRect(x: 0, y: 0, width: width, height: safeHeight + 10))
bottomView?.backgroundColor = .white
self.addSubview(bottomView!)
bottomView?.snp.makeConstraints({ make in
make.centerX.width.equalToSuperview()
make.bottom.equalToSuperview().offset(10)
make.height.equalTo(safeHeight + 10)
})
collectionView.contentInset = UIEdgeInsets(top: homeTabbarView!.height, left: 0, bottom: homeTabbarView!.height - safeHeight + 16, right: 0)
self.insertSubview(collectionView, at: 0)
collectionView.snp.makeConstraints { make in
make.center.height.equalToSuperview()
make.width.equalToSuperview().offset(-2 * marginLR)
}
}
func etCell(indexPath: IndexPath) -> UICollectionViewCell {
return UICollectionViewCell()
}
}
extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICollectionViewDelegate {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 2
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
switch section {
case 0:
return titleModels.count
case 1:
return contentModels.count
default:
return 0
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: HomeTitleCollectionCell.identifiers, for: indexPath) as! HomeTitleCollectionCell
let section = indexPath.section
switch section {
case 0:
cell.model = titleModels[indexPath.row]
default:
break
}
return cell
}
func heightForRowAtIndexPath(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, indexPath: IndexPath, itemWidth: CGFloat) -> CGFloat {
if indexPath.section == 0 {
return 190
}else {
return indexPath.row % 2 == 1 ? 197 : 217
}
}
func columnNumber(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> Int {
switch section {
case 0:
return 1
case 1:
return 2
default:
return 0
}
}
func lineSpacing(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGFloat {
return 8
}
func interitemSpacing(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGFloat {
switch section {
case 1:
return 11
default:
return 0
}
}
func spacingWithLastSection(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGFloat {
switch section {
case 1:
return 8
default:
return 0
}
}
}
//
// HomePhotosModel .swift
// PhoneManager
//
// Created by edy on 2025/3/21.
//
import Foundation
struct HomePhotosModel {
var folderName:String
var filePaths:[String]
var firstItemPath:String
var allFileSize:Double
}
//
// HomeTitleCollectionCell.swift
// PhoneManager
//
// Created by edy on 2025/3/21.
//
import UIKit
import SnapKit
class HomeTitleCollectionCell:UICollectionViewCell {
static let identifiers = "HomeTitleCollectionCellID"
private var titleLabel: UILabel?
private var collectionView: UICollectionView?
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
addSubview1()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupUI() {
self.backgroundColor = UIColor.colorWithHex(hexStr: "#F2F6FC")
self.layer.cornerRadius = 12
self.layer.masksToBounds = true
titleLabel = UILabel()
titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .bold)
titleLabel?.textColor = UIColor.colorWithHex(hexStr: black3Color)
}
func addSubview1() {
addSubview(titleLabel!)
}
var model:HomePhotosModel! {
didSet {
titleLabel?.text = model.folderName
titleLabel?.sizeToFit()
}
}
override func layoutSubviews() {
super.layoutSubviews()
titleLabel?.snp.makeConstraints({ make in
make.top.left.equalTo(16)
})
}
}
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_0" orientation="portrait" appearance="light"/>
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
......@@ -14,21 +14,21 @@
<objects>
<viewController storyboardIdentifier="LandingVCID" id="Y6W-OH-hqX" customClass="LandingVC" customModule="PhoneManager" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="5EZ-qb-Rvc">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="S4O-i8-f63">
<rect key="frame" x="15" y="60" width="290" height="4"/>
<rect key="frame" x="15" y="99" width="363" height="4"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstAttribute="height" constant="4" id="MB0-ah-w8U"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="OOl-Ae-eQl">
<rect key="frame" x="15" y="422" width="290" height="146"/>
<rect key="frame" x="15" y="672" width="363" height="146"/>
<subviews>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="Gc5-7d-2EO">
<rect key="frame" x="0.0" y="98" width="290" height="20"/>
<rect key="frame" x="0.0" y="98" width="363" height="20"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstAttribute="height" constant="20" id="Iqb-wD-6WO"/>
......@@ -40,7 +40,7 @@
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xhn-jA-V26">
<rect key="frame" x="9" y="32" width="272" height="46"/>
<rect key="frame" x="9" y="32" width="345" height="46"/>
<color key="backgroundColor" red="0.0" green="0.50980392156862742" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="height" constant="46" id="a0x-2m-ts9"/>
......@@ -58,7 +58,7 @@
</connections>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="*Based on Cleanup intemal data" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="off-hy-MUG">
<rect key="frame" x="0.0" y="3" width="290" height="17"/>
<rect key="frame" x="0.0" y="3" width="363" height="17"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" red="0.70196078431372544" green="0.70196078431372544" blue="0.70196078431372544" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
......
......@@ -22,6 +22,10 @@ class LandingVC:UIViewController {
private var models:[LandingCollectionModel] = []
private var isPPClick:Bool = false
private var isTOUClick:Bool = false
override func viewDidLoad() {
super.viewDidLoad()
......@@ -33,6 +37,15 @@ class LandingVC:UIViewController {
setupUI()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
isPPClick = false
isTOUClick = false
}
private func setDefault() {
models = loadLandingSONFromBundle() ?? []
......@@ -51,7 +64,14 @@ class LandingVC:UIViewController {
let nextIndex = (index as? Int ?? 0) + 1
changeCurrentIndex(index: nextIndex)
if (isPPClick || isTOUClick) {
}else {
changeCurrentIndex(index: nextIndex)
}
}
bottomTextView.isEditable = false
......@@ -214,18 +234,58 @@ class LandingVC:UIViewController {
// 显示 window
cWindow?.makeKeyAndVisible()
UserDef.shard.isShowLanding = true
UserDef.shard.saveUserDefToSandBox()
}
}
private func ppClick() {
if (!isPPClick) {
isPPClick = true
DispatchQueue.main.async {[weak self] in
guard let self else {return}
let vc:PrivacyPolicyWebViewController = PrivacyPolicyWebViewController()
vc.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(vc, animated: true)
}
}
}
private func touClick() {
if (!isTOUClick) {
isTOUClick = true
DispatchQueue.main.async {[weak self] in
guard let self else {return}
let vc:TermOfUseWebViewController = TermOfUseWebViewController()
vc.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(vc, animated: true)
}
}
}
}
extension LandingVC:UITextViewDelegate {
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
if URL.scheme == "terms" {
print("Terms of Use 点击事件")
touClick()
// 处理 Terms of Use 点击事件
return false // 阻止默认行为(打开链接)
} else if URL.scheme == "privacy" {
print("Privacy Policy 点击事件")
ppClick()
// 处理 Privacy Policy 点击事件
return false // 阻止默认行为(打开链接)
}
......
......@@ -18,6 +18,10 @@ class PermissionVC:UIViewController {
@IBOutlet weak var bottomTextView: UITextView!
@IBOutlet weak var nextButton: UIButton!
private var isPPClick:Bool = false
private var isTOUClick:Bool = false
lazy var animationView:LottieAnimationView = {
let animationView = LottieAnimationView(name: "onboardingStorageLight")
......@@ -37,6 +41,15 @@ class PermissionVC:UIViewController {
setupUI()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
isPPClick = false
isTOUClick = false
}
func setupUI() {
titleLabel.font = UIFont.systemFont(ofSize: 24, weight: .bold)
......@@ -133,13 +146,72 @@ class PermissionVC:UIViewController {
@IBAction func gerstartedClick(_ sender: Any) {
print("click");
PhotoAndVideoMananger.getPrivacy {[weak self] status in
guard let self else {return}
if let photoStatus = status as? PrivacyType {
switch photoStatus {
case .authorized,.denied,.restricted:
self.gotoNext()
case .notDetermined: break
}
}
}
}
private func gotoNext() {
DispatchQueue.main.async {[weak self] in
guard let self else {return}
let Ssoryboard = UIStoryboard(name: "LandingVC", bundle: nil)
if let current = Ssoryboard.instantiateViewController(identifier: "LandingVCID") as? LandingVC {
self.navigationController?.pushViewController(current, animated: true)
}
}
}
private func ppClick() {
if (!isPPClick) {
isPPClick = true
DispatchQueue.main.async {[weak self] in
guard let self else {return}
let vc:PrivacyPolicyWebViewController = PrivacyPolicyWebViewController()
vc.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(vc, animated: true)
}
}
let Ssoryboard = UIStoryboard(name: "LandingVC", bundle: nil)
}
private func touClick() {
if let current = Ssoryboard.instantiateViewController(identifier: "LandingVCID") as? LandingVC {
if (!isTOUClick) {
self.navigationController?.pushViewController(current, animated: true)
isTOUClick = true
DispatchQueue.main.async {[weak self] in
guard let self else {return}
let vc:TermOfUseWebViewController = TermOfUseWebViewController()
vc.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(vc, animated: true)
}
}
}
......@@ -149,11 +221,11 @@ class PermissionVC:UIViewController {
extension PermissionVC: UITextViewDelegate {
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
if URL.scheme == "terms" {
print("Terms of Use 点击事件")
touClick()
// 处理 Terms of Use 点击事件
return false // 阻止默认行为(打开链接)
} else if URL.scheme == "privacy" {
print("Privacy Policy 点击事件")
ppClick()
// 处理 Privacy Policy 点击事件
return false // 阻止默认行为(打开链接)
}
......
......@@ -44,9 +44,6 @@ class LauchVC:UIViewController {
vc = current
}
UserDef.shard.isShowLanding = true
UserDef.shard.saveUserDefToSandBox()
}
guard let vc else {return}
......
......@@ -15,11 +15,18 @@ class HomePayViewController:UIViewController {
super.viewDidLoad()
view.backgroundColor = .white
view.backgroundColor = .green
addViews()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
homePayView?.playAnimationWithDelay()
}
private func addViews() {
homePayView = HomePayView(frame: view.bounds)
......@@ -37,6 +44,41 @@ class HomePayViewController:UIViewController {
self.navigationController?.dismiss(animated: true)
}
}
if let commonPush = status as? CommonPush {
switch commonPush {
case .pp:
self.ppClick()
case .tou:
self.touClick()
}
}
}
}
private func ppClick() {
DispatchQueue.main.async {[weak self] in
guard let self else {return}
let vc:PrivacyPolicyWebViewController = PrivacyPolicyWebViewController()
vc.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(vc, animated: true)
}
}
private func touClick() {
DispatchQueue.main.async {[weak self] in
guard let self else {return}
let vc:TermOfUseWebViewController = TermOfUseWebViewController()
vc.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(vc, animated: true)
}
}
}
//
// PrivacyPolicyWebViewController.swift
// PhoneManager
//
// Created by edy on 2025/3/21.
//
import UIKit
class PrivacyPolicyWebViewController:BaseWebViewController {
override func viewDidLoad() {
super.viewDidLoad()
titleView.model.title = "Privacy Policy"
LoadWithUrl(url: "https://sites.google.com/view/test-ios-use/home")
view.backgroundColor = .white
webView.width = ScreenW - 20.RW()
webView.x = 10.RW()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.barStatyl = .lightContent
}
}
//
// TermOfUseWebViewController.swift
// PhoneManager
//
// Created by edy on 2025/3/21.
//
import UIKit
class TermOfUseWebViewController:BaseWebViewController {
override func viewDidLoad() {
super.viewDidLoad()
titleView.model.title = "Term of Use"
LoadWithUrl(url: "https://sites.google.com/view/testiosterms/home")
view.backgroundColor = .white
webView.width = ScreenW - 20.RW()
webView.x = 10.RW()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.barStatyl = .lightContent
}
}
//
// EnlargeBtn.swift
// PhoneManager
//
// Created by edy on 2025/3/21.
//
import UIKit
class EnlargeBtn:UIButton {
}
extension EnlargeBtn {
open override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
var boundCGRect = self.bounds
boundCGRect = CGRectInset(boundCGRect, -16, -16)
return CGRectContainsPoint(boundCGRect, point)
}
}
//
// FileWaterfallMutiSectionFlowLayout.swift
// PhoneManager
//
// Created by edy on 2025/3/21.
//
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,UICollectionViewDelegateFlowLayout {
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()
self.sectionHeadersPinToVisibleBounds = true
self.sectionFootersPinToVisibleBounds = true
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)
}
}
//
// PhotoAndVideoMananger.swift
// PhoneManager
//
// Created by edy on 2025/3/21.
//
import Foundation
import Photos
import UIKit
enum SoureceType {
case Photo
case video
}
enum PrivacyType:String {
case authorized = "authorized"
case notDetermined = "notDetermined"
case denied = "denied"
case restricted = "restricted"
}
class PhotoAndVideoMananger {
static let mananger:PhotoAndVideoMananger = PhotoAndVideoMananger()
class func getPrivacy(suc:@escaping callBack<Any> = {text in}) {
PHPhotoLibrary.requestAuthorization { status in
switch status {
case .authorized:
// 用户授权访问照片库,可以继续操作
Print("用户授权访问照片库,可以继续操作")
suc(PrivacyType.authorized)
case .denied:
Print("用户拒绝访问或者权限受限")
suc(PrivacyType.denied)
case .restricted:
// 需要提示用户去设置中授权
Print("需要提示用户去设置中授权")
suc(PrivacyType.restricted)
case .notDetermined:
// 用户尚未做出选择,可以选择提示用户请求权限
Print("等待用户授权")
suc(PrivacyType.notDetermined)
default:
break
}
}
}
}
......@@ -5,18 +5,61 @@
// Created by zxhy on 2025/3/19.
//
import Foundation
import UIKit
//间距
let ScreenW:CGFloat = UIScreen.main.bounds.size.width
let ScreenH:CGFloat = UIScreen.main.bounds.size.height
let RW:CGFloat = RScreenW()
let RH:CGFloat = RScreenH()
let tabHeight:CGFloat = 49
var safeHeight:CGFloat = 0
var statusBarHeight:CGFloat = 0
//颜色
var navHeight:CGFloat = 44
let navDefaultHeight:CGFloat = 44
var navCenterY:CGFloat = 0
let iconWH:CGFloat = 28
let marginLR:CGFloat = 15
//颜色
let launchColor:String = "#7F33FF"
let dBackColor:String = "#ffffff"
let whiteColor:String = "#ffffff"
let mColor:String = "#0082FF"
let navBack:String = "#0F0F0F"
let blackColor:String = "#000000"
let black3Color:String = "#333333"
let black6Color:String = "#666666"
func RScreenW() -> CGFloat {
return ScreenW / 375
}
func RScreenH() -> CGFloat {
let radio:CGFloat = ScreenH / 812
return radio
}
......@@ -23,3 +23,12 @@ let cWindow:UIWindow? = {
}
}()
public func Print(_ items: Any...) {
#if DEBUG
print(items)
#else
// print(items)
#endif
}
......@@ -16,3 +16,13 @@ enum OperStatus {
case close
}
enum CommonPush {
case pp
case tou
}
enum tabbarType {
case home
}
......@@ -18,7 +18,6 @@ class UserDef:NSObject {
let defaults:UserDefaults = UserDefaults.standard
self.isShowLanding = defaults.value(forKey: "isShowLanding") as? Bool ?? false
}
func saveUserDefToSandBox() {
......
......@@ -162,5 +162,55 @@ extension UIView {
center = center1
}
}
func gradient(colors: [UIColor], direction: GradientDirection = .leftToRight, cornerRadius: CGFloat = 0) {
// 移除已有的渐变图层
self.layer.sublayers?.filter { $0 is CAGradientLayer }.forEach { $0.removeFromSuperlayer() }
// 创建渐变图层
let gradientLayer = CAGradientLayer()
gradientLayer.colors = colors.map { $0.cgColor }
gradientLayer.locations = [0.0, 1.0] // 渐变位置
gradientLayer.startPoint = direction.startPoint
gradientLayer.endPoint = direction.endPoint
gradientLayer.frame = self.bounds
gradientLayer.cornerRadius = cornerRadius
// 将渐变图层添加到视图的最底层
self.layer.insertSublayer(gradientLayer, at: 0)
}
}
enum GradientDirection {
case leftToRight
case topToBottom
case topLeftToBottomRight
case topRightToBottomLeft
var startPoint: CGPoint {
switch self {
case .leftToRight:
return CGPoint(x: 0.0, y: 0.5)
case .topToBottom:
return CGPoint(x: 0.5, y: 0.0)
case .topLeftToBottomRight:
return CGPoint(x: 0.0, y: 0.0)
case .topRightToBottomLeft:
return CGPoint(x: 1.0, y: 0.0)
}
}
var endPoint: CGPoint {
switch self {
case .leftToRight:
return CGPoint(x: 1.0, y: 0.5)
case .topToBottom:
return CGPoint(x: 0.5, y: 1.0)
case .topLeftToBottomRight:
return CGPoint(x: 1.0, y: 1.0)
case .topRightToBottomLeft:
return CGPoint(x: 0.0, y: 1.0)
}
}
}
//
// UIButton+Extension.swift
// PhoneManager
//
// Created by edy on 2025/3/21.
//
import UIKit
extension UIButton {
enum BtnStyle {
case defalut
case imageTop
case imageBottom
case imageRight
}
func changBtnWithStytl(btnStyle:BtnStyle,margin:CGFloat) {
switch btnStyle {
case .defalut :
changBtnStyleImageDefault(margin: margin)
break
case.imageTop :
changBtnStyleImageTop(margin: margin)
break
case.imageBottom :
changBtnStyleImageBottom(margin: margin)
break
case.imageRight :
changBtnStyleImageRight(margin: margin)
break
}
}
private func changBtnStyleImageDefault(margin:CGFloat) {
titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: -margin)
imageEdgeInsets = UIEdgeInsets(top: 0, left: -margin, bottom: 0, right: 0)
}
private func changBtnStyleImageTop(margin:CGFloat) {
titleEdgeInsets = UIEdgeInsets(top: 0, left: -(imageView?.frame.size.width ?? 0), bottom: -(imageView?.frame.size.height ?? 0) - margin, right: 0)
imageEdgeInsets = UIEdgeInsets(top: -(titleLabel?.intrinsicContentSize.height ?? 0) - margin, left: 0, bottom: 0, right: -(titleLabel?.intrinsicContentSize.width ?? 0))
}
private func changBtnStyleImageBottom(margin:CGFloat) {
titleEdgeInsets = UIEdgeInsets(top: -(imageView?.frame.size.height ?? 0) - margin, left: -((imageView?.frame.size.width ?? 0) - margin), bottom: 0, right: 0)
imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: -(titleLabel?.intrinsicContentSize.height ?? 0) - margin, right: -(titleLabel?.intrinsicContentSize.width ?? 0) - margin)
}
private func changBtnStyleImageRight(margin:CGFloat) {
self.titleEdgeInsets = UIEdgeInsets(top: 0, left: -2 * (imageView?.frame.size.width ?? 0) - margin, bottom: 0, right: 0)
imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: -2 * (titleLabel?.intrinsicContentSize.width ?? 0) - margin)
}
func changBtnStyleImageToRight(margin:CGFloat) {
self.titleEdgeInsets = UIEdgeInsets(top: 0, left: -2 * (imageView?.frame.size.width ?? 0) + margin, bottom: 0, right: 0)
imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: -2 * (titleLabel?.intrinsicContentSize.width ?? 0) - margin)
}
}
......@@ -48,4 +48,11 @@ extension UIColor {
return UIColor.init(red: CGFloat(r)/255.0, green: CGFloat(g)/255.0, blue: CGFloat(b)/255.0, alpha: CGFloat(alpha))
}
static var random: UIColor {
let red = CGFloat.random(in: 0...1)
let green = CGFloat.random(in: 0...1)
let blue = CGFloat.random(in: 0...1)
return UIColor(red: red, green: green, blue: blue, alpha: 1.0)
}
}
//
// UIViewController+Extension.swift
// PhoneManager
//
// Created by edy on 2025/3/21.
//
import UIKit
extension UIViewController {
func setStatusBarStyle(style:UIStatusBarStyle) {
guard let nav = self.navigationController as? BaseNavViewController else {return}
nav.barStatyl = style
}
func setStatusBarHidden(isHidden:Bool) {
guard let nav = self.navigationController as? BaseNavViewController else {return}
nav.barHidden = isHidden
}
}
//
// Value+Extension.swift
// PhoneManager
//
// Created by edy on 2025/3/21.
//
import Foundation
extension Int {
func RW() -> Double {
return Double(self) * RScreenW()
}
func RWI() -> Int {
return Int(self) * Int(RScreenW())
}
func RH() -> Double {
return Double(self) * RScreenH()
}
func RHI() -> Int {
return Int(self) * Int(RScreenH())
}
func R(ratio:CGFloat) -> Double {
return Double(self) * ratio
}
}
extension Float {
func RW() -> Double {
return Double(self) * RScreenW()
}
func RWI() -> Int {
return Int(self) * Int(RScreenW())
}
func RH() -> Double {
return Double(self) * RScreenH()
}
func RHI() -> Int {
return Int(self) * Int(RScreenH())
}
func R(ratio:CGFloat) -> Double {
return Double(self) * ratio
}
}
extension Double {
func RW() -> Double {
return Double(self) * RScreenW()
}
func RWI() -> Int {
return Int(self) * Int(RScreenW())
}
func RH() -> Double {
return Double(self) * RScreenH()
}
func RHI() -> Int {
return Int(self) * Int(RScreenH())
}
func R(ratio:CGFloat) -> Double {
return Double(self) * ratio
}
}
extension CGFloat {
func RW() -> Double {
return Double(self) * RScreenW()
}
func RWI() -> Int {
return Int(self) * Int(RScreenW())
}
func RH() -> Double {
return Double(self) * RScreenH()
}
func RHI() -> Int {
return Int(self) * Int(RScreenH())
}
func R(ratio:CGFloat) -> Double {
return Double(self) * ratio
}
}
......@@ -2,6 +2,17 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need album permission to access image storage information</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>
<key>NSLocalNetworkUsageDescription</key>
<string>We need to access the network to load content</string>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment