diff --git a/Podfile b/Podfile index 06fdbe0..98bdbc3 100644 --- a/Podfile +++ b/Podfile @@ -66,6 +66,9 @@ target 'YuMi' do pod 'YuMi',:path=>'yum' pod 'QCloudCOSXML' pod 'TYCyclePagerView' + + pod 'SnapKit', '~> 5.0' + end post_install do |installer| diff --git a/Podfile.lock b/Podfile.lock index 45e4a58..6f7d580 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -95,6 +95,7 @@ PODS: - SDWebImageFLPlugin (0.6.0): - FLAnimatedImage (>= 1.0.11) - SDWebImage/Core (~> 5.10) + - SnapKit (5.7.1) - SSKeychain (1.4.1) - SSZipArchive (2.4.3) - SVGAPlayer (2.5.7): @@ -164,6 +165,7 @@ DEPENDENCIES: - SDCycleScrollView - SDWebImage (= 5.21.3) - SDWebImageFLPlugin + - SnapKit (~> 5.0) - SSKeychain - SVGAPlayer - SZTextView @@ -220,6 +222,7 @@ SPEC REPOS: - SDCycleScrollView - SDWebImage - SDWebImageFLPlugin + - SnapKit - SSKeychain - SSZipArchive - SVGAPlayer @@ -282,6 +285,7 @@ SPEC CHECKSUMS: SDCycleScrollView: a0d74c3384caa72bdfc81470bdbc8c14b3e1fbcf SDWebImage: 16309af6d214ba3f77a7c6f6fdda888cb313a50a SDWebImageFLPlugin: 72efd2cfbf565bc438421abb426f4bcf7b670754 + SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a SSKeychain: 55cc80f66f5c73da827e3077f02e43528897db41 SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef SVGAPlayer: 318b85a78b61292d6ae9dfcd651f3f0d1cdadd86 @@ -300,6 +304,6 @@ SPEC CHECKSUMS: YYWebImage: 5f7f36aee2ae293f016d418c7d6ba05c4863e928 ZLCollectionViewFlowLayout: c99024652ce9f0c57d33ab53052c9b85e4a936b7 -PODFILE CHECKSUM: b14955816bdf61713f83a3de2cac5823a1e1449a +PODFILE CHECKSUM: 581cecb560110b972c7e8c7d4b01e24a5deaf833 COCOAPODS: 1.16.2 diff --git a/TAB_ICONS_PLACEHOLDER.md b/TAB_ICONS_PLACEHOLDER.md new file mode 100644 index 0000000..d91955e --- /dev/null +++ b/TAB_ICONS_PLACEHOLDER.md @@ -0,0 +1,56 @@ +# TabBar 图标占位说明 + +## 需要的图标文件 + +由于项目中没有以下图标文件,需要添加: + +### Moment Tab 图标 +- `tab_moment_off` - 未选中状态(白色 60% 透明) +- `tab_moment_on` - 选中状态(白色 100%) + +### Mine Tab 图标 +- `tab_mine_off` - 未选中状态(白色 60% 透明) +- `tab_mine_on` - 选中状态(白色 100%) + +## 临时解决方案 + +在图片资源准备好之前,可以使用以下临时方案: + +1. **使用 SF Symbols**(当前已实现) +2. **使用纯色占位图**(程序生成) +3. **使用项目中的其他图标** + +## 图标规格 + +- 尺寸:28x28pt @3x(84x84px) +- 格式:PNG(支持透明) +- 风格:线性图标,2pt 描边 +- 颜色:白色(未选中 60% 透明,选中 100%) + +## 添加到项目 + +将图标文件添加到 `YuMi/Assets.xcassets` 中: + +``` +Assets.xcassets/ +├── tab_moment_off.imageset/ +│ ├── Contents.json +│ ├── tab_moment_off@1x.png +│ ├── tab_moment_off@2x.png +│ └── tab_moment_off@3x.png +├── tab_moment_on.imageset/ +│ ├── Contents.json +│ ├── tab_moment_on@1x.png +│ ├── tab_moment_on@2x.png +│ └── tab_moment_on@3x.png +├── tab_mine_off.imageset/ +│ ├── Contents.json +│ ├── tab_mine_off@1x.png +│ ├── tab_mine_off@2x.png +│ └── tab_mine_off@3x.png +└── tab_mine_on.imageset/ + ├── Contents.json + ├── tab_mine_on@1x.png + ├── tab_mine_on@2x.png + └── tab_mine_on@3x.png +``` diff --git a/YuMi.xcodeproj/project.pbxproj b/YuMi.xcodeproj/project.pbxproj index 988064a..5cb43d6 100644 --- a/YuMi.xcodeproj/project.pbxproj +++ b/YuMi.xcodeproj/project.pbxproj @@ -11800,14 +11800,10 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-YuMi/Pods-YuMi-resources-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - ); name = "[CP] Copy Pods Resources"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-YuMi/Pods-YuMi-resources-${CONFIGURATION}-output-files.xcfilelist", ); - outputPaths = ( - ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-YuMi/Pods-YuMi-resources.sh\"\n"; @@ -11821,14 +11817,10 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-YuMi/Pods-YuMi-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-YuMi/Pods-YuMi-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); - outputPaths = ( - ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-YuMi/Pods-YuMi-frameworks.sh\"\n"; diff --git a/YuMi/Modules/NewMoments/Controllers/EPMomentViewController.m b/YuMi/Modules/NewMoments/Controllers/EPMomentViewController.m index f4896c3..6164cad 100644 --- a/YuMi/Modules/NewMoments/Controllers/EPMomentViewController.m +++ b/YuMi/Modules/NewMoments/Controllers/EPMomentViewController.m @@ -8,11 +8,9 @@ #import "EPMomentViewController.h" #import "EPMomentCell.h" -#import #import "Api+Moments.h" #import "AccountInfoStorage.h" #import "MomentsInfoModel.h" -#import @interface EPMomentViewController () @@ -48,12 +46,11 @@ [super viewDidLoad]; self.title = @"动态"; - self.view.backgroundColor = [UIColor colorWithRed:0.96 green:0.96 blue:0.96 alpha:1.0]; // 浅灰背景 [self setupUI]; [self loadData]; - NSLog(@"[EPMomentViewController] 页面加载完成"); + NSLog(@"[EPMomentViewController] 页面加载完成"); } - (void)viewWillAppear:(BOOL)animated { @@ -66,6 +63,13 @@ // MARK: - Setup UI - (void)setupUI { + UIImageView *bgImageView = [[UIImageView alloc] initWithImage:kImage(@"vc_bg")]; + [self.view addSubview:bgImageView]; + [bgImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self.view); + }]; + + // TableView [self.view addSubview:self.tableView]; [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { diff --git a/YuMi/Modules/NewTabBar/EPTabBarController.swift b/YuMi/Modules/NewTabBar/EPTabBarController.swift index cae378d..539e685 100644 --- a/YuMi/Modules/NewTabBar/EPTabBarController.swift +++ b/YuMi/Modules/NewTabBar/EPTabBarController.swift @@ -7,6 +7,7 @@ // import UIKit +import SnapKit /// EP 系列 TabBar 控制器 /// 悬浮设计 + 液态玻璃效果,只包含 Moment 和 Mine 两个 Tab @@ -65,16 +66,16 @@ import UIKit view.addSubview(customTabBarView) // 液态玻璃/毛玻璃效果 - let blurEffect: UIBlurEffect - if #available(iOS 18.0, *) { - // iOS 18+ 使用液态玻璃(Material) - blurEffect = UIBlurEffect(style: .systemChromeMaterial) + let effect: UIVisualEffect + if #available(iOS 26.0, *) { + // iOS 26+ 使用液态玻璃(Material) + effect = UIGlassEffect() } else { // iOS 13-17 使用毛玻璃 - blurEffect = UIBlurEffect(style: .systemThinMaterial) + effect = UIBlurEffect(style: .systemUltraThinMaterial) } - tabBarBackgroundView = UIVisualEffectView(effect: blurEffect) + tabBarBackgroundView = UIVisualEffectView(effect: effect) tabBarBackgroundView.translatesAutoresizingMaskIntoConstraints = false tabBarBackgroundView.layer.cornerRadius = 28 tabBarBackgroundView.layer.masksToBounds = true @@ -92,20 +93,17 @@ import UIKit customTabBarView.layer.shadowRadius = 10 customTabBarView.layer.shadowPath = nil // 自动计算 - // 布局约束(悬浮,两侧留白 16pt,底部留白 12pt) - NSLayoutConstraint.activate([ - // TabBar 容器 - customTabBarView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16), - customTabBarView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16), - customTabBarView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -12), - customTabBarView.heightAnchor.constraint(equalToConstant: 64), - - // 背景视图 - tabBarBackgroundView.topAnchor.constraint(equalTo: customTabBarView.topAnchor), - tabBarBackgroundView.leadingAnchor.constraint(equalTo: customTabBarView.leadingAnchor), - tabBarBackgroundView.trailingAnchor.constraint(equalTo: customTabBarView.trailingAnchor), - tabBarBackgroundView.bottomAnchor.constraint(equalTo: customTabBarView.bottomAnchor) - ]) + // 简化的布局约束(类似 Masonry 风格) + customTabBarView.snp.makeConstraints { make in + make.leading.equalTo(view).offset(16) + make.trailing.equalTo(view).offset(-16) + make.bottom.equalTo(view.safeAreaLayoutGuide).offset(-12) + make.height.equalTo(64) + } + + tabBarBackgroundView.snp.makeConstraints { make in + make.edges.equalTo(customTabBarView) + } // 添加 Tab 按钮 setupTabButtons() @@ -116,14 +114,14 @@ import UIKit /// 设置 Tab 按钮 private func setupTabButtons() { let momentButton = createTabButton( - icon: "sparkles", // 临时使用 SF Symbols - title: "动态", + normalImage: "tab_moment_off", + selectedImage: "tab_moment_on", tag: 0 ) let mineButton = createTabButton( - icon: "person.circle", - title: "我的", + normalImage: "tab_mine_off", + selectedImage: "tab_mine_on", tag: 1 ) @@ -136,39 +134,49 @@ import UIKit stackView.translatesAutoresizingMaskIntoConstraints = false tabBarBackgroundView.contentView.addSubview(stackView) - NSLayoutConstraint.activate([ - stackView.topAnchor.constraint(equalTo: tabBarBackgroundView.topAnchor, constant: 8), - stackView.leadingAnchor.constraint(equalTo: tabBarBackgroundView.leadingAnchor, constant: 20), - stackView.trailingAnchor.constraint(equalTo: tabBarBackgroundView.trailingAnchor, constant: -20), - stackView.bottomAnchor.constraint(equalTo: tabBarBackgroundView.bottomAnchor, constant: -8) - ]) + stackView.snp.makeConstraints { make in + make.top.equalTo(tabBarBackgroundView).offset(8) + make.leading.equalTo(tabBarBackgroundView).offset(20) + make.trailing.equalTo(tabBarBackgroundView).offset(-20) + make.bottom.equalTo(tabBarBackgroundView).offset(-8) + } // 默认选中第一个 updateTabButtonStates(selectedIndex: 0) } /// 创建 Tab 按钮 - private func createTabButton(icon: String, title: String, tag: Int) -> UIButton { + private func createTabButton(normalImage: String, selectedImage: String, tag: Int) -> UIButton { let button = UIButton(type: .custom) button.tag = tag - // 设置图标 - let imageConfig = UIImage.SymbolConfiguration(pointSize: 20, weight: .medium) - let iconImage = UIImage(systemName: icon, withConfiguration: imageConfig) - button.setImage(iconImage, for: .normal) + // 尝试设置自定义图片,如果不存在则使用 SF Symbols + if let normalImg = UIImage(named: normalImage), let selectedImg = UIImage(named: selectedImage) { + // 使用自定义图片 + button.setImage(normalImg, for: .normal) + button.setImage(selectedImg, for: .selected) + } else { + // 使用 SF Symbols 作为备用 + let fallbackIcons = ["sparkles", "person.circle"] + let iconName = fallbackIcons[tag] + let imageConfig = UIImage.SymbolConfiguration(pointSize: 24, weight: .medium) + + button.setImage(UIImage(systemName: iconName, withConfiguration: imageConfig), for: .normal) + button.setImage(UIImage(systemName: iconName, withConfiguration: imageConfig), for: .selected) + button.tintColor = .white.withAlphaComponent(0.6) + } - // 设置标题 - button.setTitle(title, for: .normal) - button.titleLabel?.font = UIFont.systemFont(ofSize: 12, weight: .medium) + // 图片渲染模式 + button.imageView?.contentMode = .scaleAspectFit - // 设置颜色 - button.setTitleColor(.white.withAlphaComponent(0.6), for: .normal) - button.setTitleColor(.white, for: .selected) - button.tintColor = .white.withAlphaComponent(0.6) + // 移除标题,只使用图片 + button.setTitle(nil, for: .normal) + button.setTitle(nil, for: .selected) - // 设置布局 - button.titleEdgeInsets = UIEdgeInsets(top: 25, left: -20, bottom: -25, right: 0) - button.imageEdgeInsets = UIEdgeInsets(top: -10, left: 0, bottom: 10, right: 0) + // 设置图片大小约束 + button.imageView?.snp.makeConstraints { make in + make.size.equalTo(28) // 图标大小 + } button.addTarget(self, action: #selector(tabButtonTapped(_:)), for: .touchUpInside) return button @@ -188,8 +196,11 @@ import UIKit for (index, button) in tabButtons.enumerated() { let isSelected = (index == selectedIndex) button.isSelected = isSelected - button.tintColor = isSelected ? .white : .white.withAlphaComponent(0.6) - button.setTitleColor(isSelected ? .white : .white.withAlphaComponent(0.6), for: .normal) + + // 如果是 SF Symbols,更新 tintColor + if button.tintColor != nil { + button.tintColor = isSelected ? .white : .white.withAlphaComponent(0.6) + } // 选中状态动画 UIView.animate(withDuration: 0.2) {