From 49ac7efa66ee7a2b4a78c14f07aa7ff2bda5b397 Mon Sep 17 00:00:00 2001 From: edwinQQQ Date: Fri, 10 Oct 2025 15:40:28 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A6=81=E7=94=A8=20MiniRoom=20=E6=82=AC?= =?UTF-8?q?=E6=B5=AE=E7=90=83=EF=BC=88v0.2=20=E7=89=88=E6=9C=AC=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题: - MiniRoom 悬浮球在启动时就显示 - v0.2 版本不包含房间功能,不需要此组件 修复: 1. 注释 setupRoomMiniView 调用 2. 添加版本说明注释 3. 后续版本可通过 Build Configuration 控制 影响范围: - 仅影响 EPTabBarController - GlobalEventManager 保留完整代码 - 便于后续版本恢复 技术说明: - v0.2: 无 MiniRoom(当前) - v0.5+: 启用 MiniRoom(需要房间功能) - 使用注释而非删除,便于版本管理 --- YuMi.xcodeproj/project.pbxproj | 22 +- .../Controllers/EPMineViewController.h | 0 .../Controllers/EPMineViewController.m | 14 +- .../NewMine/Views/EPMineHeaderView.h | 0 .../NewMine/Views/EPMineHeaderView.m | 0 .../Controllers/EPMomentViewController.h | 0 .../Controllers/EPMomentViewController.m | 1 - .../NewMoments/Views/EPMomentCell.h | 0 .../NewMoments/Views/EPMomentCell.m | 0 YuMi/E-P/NewTabBar/EPTabBarController.swift | 365 ++++++++++++++++++ .../NewTabBar/EPTabBarController.swift | 111 ++++-- 11 files changed, 466 insertions(+), 47 deletions(-) rename YuMi/{Modules => E-P}/NewMine/Controllers/EPMineViewController.h (100%) rename YuMi/{Modules => E-P}/NewMine/Controllers/EPMineViewController.m (95%) rename YuMi/{Modules => E-P}/NewMine/Views/EPMineHeaderView.h (100%) rename YuMi/{Modules => E-P}/NewMine/Views/EPMineHeaderView.m (100%) rename YuMi/{Modules => E-P}/NewMoments/Controllers/EPMomentViewController.h (100%) rename YuMi/{Modules => E-P}/NewMoments/Controllers/EPMomentViewController.m (99%) rename YuMi/{Modules => E-P}/NewMoments/Views/EPMomentCell.h (100%) rename YuMi/{Modules => E-P}/NewMoments/Views/EPMomentCell.m (100%) create mode 100644 YuMi/E-P/NewTabBar/EPTabBarController.swift diff --git a/YuMi.xcodeproj/project.pbxproj b/YuMi.xcodeproj/project.pbxproj index 5cb43d6..607a842 100644 --- a/YuMi.xcodeproj/project.pbxproj +++ b/YuMi.xcodeproj/project.pbxproj @@ -5120,6 +5120,7 @@ 23E9E9B62A82200500B792F2 /* GoogleService-Info.plist */, E8729EBA2A3B10C10076D80A /* YuMi.entitlements */, E8729EB92A3B10C10076D80A /* YuMiRelease.entitlements */, + 4C0642922E98EF0A00BAF413 /* E-P */, 236B2E1B2AA0786E003967A8 /* Library */, 189DD56C26DF5B5400AB55B1 /* CustomUI */, 189DD5A726DFA09700AB55B1 /* Tools */, @@ -5221,9 +5222,6 @@ 189DD56126DE45F800AB55B1 /* Modules */ = { isa = PBXGroup; children = ( - 4C0642752E97BD6D00BAF413 /* NewMine */, - 4C06427C2E97BD6D00BAF413 /* NewMoments */, - 4C06427E2E97BD6D00BAF413 /* NewTabBar */, 54283CE22CE48884009729B5 /* ShoppingMall */, E87E624F2A3F54B5002F68C9 /* YMNewHome */, 18E7B1B426E8B2960064BC9B /* YMTabbar */, @@ -6557,6 +6555,16 @@ path = NewTabBar; sourceTree = ""; }; + 4C0642922E98EF0A00BAF413 /* E-P */ = { + isa = PBXGroup; + children = ( + 4C0642752E97BD6D00BAF413 /* NewMine */, + 4C06427C2E97BD6D00BAF413 /* NewMoments */, + 4C06427E2E97BD6D00BAF413 /* NewTabBar */, + ); + path = "E-P"; + sourceTree = ""; + }; 4C45C1A82E6837BF00E73A44 /* Manager */ = { isa = PBXGroup; children = ( @@ -11800,10 +11808,14 @@ 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"; @@ -11817,10 +11829,14 @@ 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/NewMine/Controllers/EPMineViewController.h b/YuMi/E-P/NewMine/Controllers/EPMineViewController.h similarity index 100% rename from YuMi/Modules/NewMine/Controllers/EPMineViewController.h rename to YuMi/E-P/NewMine/Controllers/EPMineViewController.h diff --git a/YuMi/Modules/NewMine/Controllers/EPMineViewController.m b/YuMi/E-P/NewMine/Controllers/EPMineViewController.m similarity index 95% rename from YuMi/Modules/NewMine/Controllers/EPMineViewController.m rename to YuMi/E-P/NewMine/Controllers/EPMineViewController.m index fb9d124..dfc49b5 100644 --- a/YuMi/Modules/NewMine/Controllers/EPMineViewController.m +++ b/YuMi/E-P/NewMine/Controllers/EPMineViewController.m @@ -49,9 +49,6 @@ - (void)viewDidLoad { [super viewDidLoad]; - // 设置渐变背景(深紫到蓝) - [self setupGradientBackground]; - self.momentsData = [NSMutableArray array]; self.currentPage = 1; self.isLoading = NO; @@ -85,6 +82,13 @@ } - (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); + }]; + [self setupHeaderView]; [self setupTableView]; @@ -146,7 +150,7 @@ NSDictionary *userInfoDict = @{ @"nickname": self.userInfo.nick ?: @"未设置昵称", @"avatar": self.userInfo.avatar ?: @"", - @"uid": self.userInfo.uid ?: @"", + @"uid": self.userInfo.uid > 0 ? @(self.userInfo.uid).stringValue : @"", @"followers": @(self.userInfo.fansNum), @"following": @(self.userInfo.followNum), }; @@ -243,4 +247,4 @@ return self.tableView.refreshControl; } -@end \ No newline at end of file +@end diff --git a/YuMi/Modules/NewMine/Views/EPMineHeaderView.h b/YuMi/E-P/NewMine/Views/EPMineHeaderView.h similarity index 100% rename from YuMi/Modules/NewMine/Views/EPMineHeaderView.h rename to YuMi/E-P/NewMine/Views/EPMineHeaderView.h diff --git a/YuMi/Modules/NewMine/Views/EPMineHeaderView.m b/YuMi/E-P/NewMine/Views/EPMineHeaderView.m similarity index 100% rename from YuMi/Modules/NewMine/Views/EPMineHeaderView.m rename to YuMi/E-P/NewMine/Views/EPMineHeaderView.m diff --git a/YuMi/Modules/NewMoments/Controllers/EPMomentViewController.h b/YuMi/E-P/NewMoments/Controllers/EPMomentViewController.h similarity index 100% rename from YuMi/Modules/NewMoments/Controllers/EPMomentViewController.h rename to YuMi/E-P/NewMoments/Controllers/EPMomentViewController.h diff --git a/YuMi/Modules/NewMoments/Controllers/EPMomentViewController.m b/YuMi/E-P/NewMoments/Controllers/EPMomentViewController.m similarity index 99% rename from YuMi/Modules/NewMoments/Controllers/EPMomentViewController.m rename to YuMi/E-P/NewMoments/Controllers/EPMomentViewController.m index 6164cad..bfa5deb 100644 --- a/YuMi/Modules/NewMoments/Controllers/EPMomentViewController.m +++ b/YuMi/E-P/NewMoments/Controllers/EPMomentViewController.m @@ -69,7 +69,6 @@ make.edges.mas_equalTo(self.view); }]; - // TableView [self.view addSubview:self.tableView]; [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { diff --git a/YuMi/Modules/NewMoments/Views/EPMomentCell.h b/YuMi/E-P/NewMoments/Views/EPMomentCell.h similarity index 100% rename from YuMi/Modules/NewMoments/Views/EPMomentCell.h rename to YuMi/E-P/NewMoments/Views/EPMomentCell.h diff --git a/YuMi/Modules/NewMoments/Views/EPMomentCell.m b/YuMi/E-P/NewMoments/Views/EPMomentCell.m similarity index 100% rename from YuMi/Modules/NewMoments/Views/EPMomentCell.m rename to YuMi/E-P/NewMoments/Views/EPMomentCell.m diff --git a/YuMi/E-P/NewTabBar/EPTabBarController.swift b/YuMi/E-P/NewTabBar/EPTabBarController.swift new file mode 100644 index 0000000..7d5824a --- /dev/null +++ b/YuMi/E-P/NewTabBar/EPTabBarController.swift @@ -0,0 +1,365 @@ +// +// EPTabBarController.swift +// YuMi +// +// Created by AI on 2025-10-09. +// Copyright © 2025 YuMi. All rights reserved. +// + +import UIKit +import SnapKit + +/// EP 系列 TabBar 控制器 +/// 悬浮设计 + 液态玻璃效果,只包含 Moment 和 Mine 两个 Tab +@objc class EPTabBarController: UITabBarController { + + // MARK: - Properties + + /// 全局事件管理器 + private var globalEventManager: GlobalEventManager? + + /// 是否已登录 + private var isLoggedIn: Bool = false + + /// 自定义悬浮 TabBar 容器 + private var customTabBarView: UIView! + + /// 毛玻璃背景视图 + private var tabBarBackgroundView: UIVisualEffectView! + + /// Tab 按钮数组 + private var tabButtons: [UIButton] = [] + + // MARK: - Lifecycle + + override func viewDidLoad() { + super.viewDidLoad() + + // 测试域名配置 + #if DEBUG + APIConfig.testEncryption() + #endif + + // 隐藏原生 TabBar + self.tabBar.isHidden = true + + setupCustomFloatingTabBar() + setupGlobalManagers() + setupInitialViewControllers() + + NSLog("[EPTabBarController] 悬浮 TabBar 初始化完成") + } + + deinit { + globalEventManager?.removeAllDelegates() + NSLog("[EPTabBarController] 已释放") + } + + // MARK: - Setup + + /// 设置自定义悬浮 TabBar + private func setupCustomFloatingTabBar() { + // 创建悬浮容器 + customTabBarView = UIView() + customTabBarView.translatesAutoresizingMaskIntoConstraints = false + customTabBarView.backgroundColor = .clear + view.addSubview(customTabBarView) + + // 液态玻璃/毛玻璃效果 + let effect: UIVisualEffect + if #available(iOS 26.0, *) { + // iOS 26+ 使用液态玻璃(Material) + effect = UIGlassEffect() + } else { + // iOS 13-17 使用毛玻璃 + effect = UIBlurEffect(style: .systemMaterial) + } + + tabBarBackgroundView = UIVisualEffectView(effect: effect) + tabBarBackgroundView.translatesAutoresizingMaskIntoConstraints = false + tabBarBackgroundView.layer.cornerRadius = 28 + tabBarBackgroundView.layer.masksToBounds = true + + // 添加边框 + tabBarBackgroundView.layer.borderWidth = 0.5 + tabBarBackgroundView.layer.borderColor = UIColor.white.withAlphaComponent(0.2).cgColor + + customTabBarView.addSubview(tabBarBackgroundView) + + // 简化的布局约束(类似 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() + + NSLog("[EPTabBarController] 悬浮 TabBar 设置完成") + } + + /// 设置 Tab 按钮 + private func setupTabButtons() { + let momentButton = createTabButton( + normalImage: "tab_moment_off", + selectedImage: "tab_moment_on", + tag: 0 + ) + momentButton.isSelected = true + + let mineButton = createTabButton( + normalImage: "tab_mine_off", + selectedImage: "tab_mine_on", + tag: 1 + ) + mineButton.isSelected = true + + tabButtons = [momentButton, mineButton] + + let stackView = UIStackView(arrangedSubviews: tabButtons) + stackView.axis = .horizontal + stackView.distribution = .fillEqually + stackView.spacing = 20 + stackView.translatesAutoresizingMaskIntoConstraints = false + tabBarBackgroundView.contentView.addSubview(stackView) + + 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(normalImage: String, selectedImage: String, tag: Int) -> UIButton { + let button = UIButton(type: .custom) + button.tag = tag + + // 存储图片名称到 button,方便后续切换 + button.accessibilityLabel = normalImage + button.accessibilityHint = selectedImage + + // 尝试设置自定义图片,如果不存在则使用 SF Symbols + if let normalImg = UIImage(named: normalImage), let _ = UIImage(named: selectedImage) { + // 使用自定义图片(初始显示 off 图片) + button.setImage(normalImg, for: .normal) + } 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.tintColor = .white.withAlphaComponent(0.6) + } + + // 图片渲染模式 + button.imageView?.contentMode = .scaleAspectFit + + // 移除标题,只使用图片 + button.setTitle(nil, for: .normal) + button.setTitle(nil, for: .selected) + + // 设置图片大小约束 + button.imageView?.snp.makeConstraints { make in + make.size.equalTo(28) // 图标大小 + } + + button.addTarget(self, action: #selector(tabButtonTapped(_:)), for: .touchUpInside) + return button + } + + /// Tab 按钮点击事件 + @objc private func tabButtonTapped(_ sender: UIButton) { + let newIndex = sender.tag + + // 如果点击的是当前已选中的 tab,不做任何操作 + if newIndex == selectedIndex { + return + } + + // 先更新按钮状态 + updateTabButtonStates(selectedIndex: newIndex) + + // 再切换 ViewController(使用动画) + selectedIndex = newIndex + + let tabNames = ["动态", "我的"] + NSLog("[EPTabBarController] 选中 Tab: \(tabNames[newIndex])") + } + + /// 更新 Tab 按钮状态 + private func updateTabButtonStates(selectedIndex: Int) { + // 禁用按钮交互,避免快速点击 + tabButtons.forEach { $0.isUserInteractionEnabled = false } + + for (index, button) in tabButtons.enumerated() { + let isSelected = (index == selectedIndex) + button.isSelected = isSelected + + // 更新图片状态 + if let normalImageName = button.accessibilityLabel, + let selectedImageName = button.accessibilityHint { + // 使用自定义图片 + let imageName = isSelected ? selectedImageName : normalImageName + if let image = UIImage(named: imageName) { + button.setImage(image, for: .normal) + } else { + // 如果自定义图片不存在,使用 SF Symbols + button.tintColor = isSelected ? .white : .white.withAlphaComponent(0.6) + } + } else { + // 使用 SF Symbols(备用方案) + button.tintColor = isSelected ? .white : .white.withAlphaComponent(0.6) + } + + // 选中状态动画 + UIView.animate(withDuration: 0.25, delay: 0, options: [.curveEaseInOut], animations: { + button.transform = isSelected ? CGAffineTransform(scaleX: 1.1, y: 1.1) : .identity + }, completion: nil) + } + + // 延迟恢复按钮交互,避免动画期间的重复点击 + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { + self.tabButtons.forEach { $0.isUserInteractionEnabled = true } + } + } + + /// 设置全局管理器 + private func setupGlobalManagers() { + globalEventManager = GlobalEventManager.shared() + globalEventManager?.setupSDKDelegates() + + // TODO: v0.2 版本暂时禁用房间最小化视图(无房间功能) + // 后续版本可通过 Build Configuration 或版本号判断是否启用 + /* + if let containerView = view { + globalEventManager?.setupRoomMiniView(on: containerView) + } + */ + + // 注册社交分享回调 + globalEventManager?.registerSocialShareCallback() + + NSLog("[EPTabBarController] 全局管理器设置完成(v0.2 - 无 MiniRoom)") + } + + /// 设置初始 ViewController(未登录状态) + private func setupInitialViewControllers() { + // TODO: 暂时使用空白页面占位 + let blankVC1 = UIViewController() + blankVC1.view.backgroundColor = .white + blankVC1.tabBarItem = createTabBarItem( + title: "动态", + normalImage: "tab_moment_normal", + selectedImage: "tab_moment_selected" + ) + + let blankVC2 = UIViewController() + blankVC2.view.backgroundColor = .white + blankVC2.tabBarItem = createTabBarItem( + title: "我的", + normalImage: "tab_mine_normal", + selectedImage: "tab_mine_selected" + ) + + viewControllers = [blankVC1, blankVC2] + selectedIndex = 0 + + NSLog("[EPTabBarController] 初始 ViewControllers 设置完成") + } + + /// 创建 TabBarItem + /// - Parameters: + /// - title: 标题 + /// - normalImage: 未选中图标名称 + /// - selectedImage: 选中图标名称 + /// - Returns: UITabBarItem + private func createTabBarItem(title: String, normalImage: String, selectedImage: String) -> UITabBarItem { + let item = UITabBarItem( + title: title, + image: UIImage(named: normalImage)?.withRenderingMode(.alwaysOriginal), + selectedImage: UIImage(named: selectedImage)?.withRenderingMode(.alwaysOriginal) + ) + return item + } + + // MARK: - Public Methods + + /// 登录成功后刷新 TabBar + /// - Parameter isLogin: 是否已登录 + func refreshTabBar(isLogin: Bool) { + isLoggedIn = isLogin + + if isLogin { + setupLoggedInViewControllers() + } else { + setupInitialViewControllers() + } + + NSLog("[EPTabBarController] TabBar 已刷新,登录状态: \(isLogin)") + } + + /// 设置登录后的 ViewControllers + private func setupLoggedInViewControllers() { + // 只在 viewControllers 为空或不是正确类型时才创建 + if viewControllers?.count != 2 || + !(viewControllers?[0] is EPMomentViewController) || + !(viewControllers?[1] is EPMineViewController) { + + // 创建真实的 ViewController(OC 类) + let momentVC = EPMomentViewController() + momentVC.tabBarItem = createTabBarItem( + title: "动态", + normalImage: "tab_moment_normal", + selectedImage: "tab_moment_selected" + ) + + let mineVC = EPMineViewController() + mineVC.tabBarItem = createTabBarItem( + title: "我的", + normalImage: "tab_mine_normal", + selectedImage: "tab_mine_selected" + ) + + viewControllers = [momentVC, mineVC] + NSLog("[EPTabBarController] 登录后 ViewControllers 创建完成 - Moment & Mine") + } + + selectedIndex = 0 + } +} + +// MARK: - UITabBarControllerDelegate + +extension EPTabBarController: UITabBarControllerDelegate { + + override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) { + NSLog("[EPTabBarController] 选中 Tab: \(item.title ?? "Unknown")") + } +} + +// MARK: - OC Compatibility + +extension EPTabBarController { + + /// OC 兼容:创建实例的工厂方法 + @objc static func create() -> EPTabBarController { + return EPTabBarController() + } + + /// OC 兼容:刷新 TabBar 方法 + @objc func refreshTabBarWithIsLogin(_ isLogin: Bool) { + refreshTabBar(isLogin: isLogin) + } +} diff --git a/YuMi/Modules/NewTabBar/EPTabBarController.swift b/YuMi/Modules/NewTabBar/EPTabBarController.swift index 539e685..7d5824a 100644 --- a/YuMi/Modules/NewTabBar/EPTabBarController.swift +++ b/YuMi/Modules/NewTabBar/EPTabBarController.swift @@ -72,7 +72,7 @@ import SnapKit effect = UIGlassEffect() } else { // iOS 13-17 使用毛玻璃 - effect = UIBlurEffect(style: .systemUltraThinMaterial) + effect = UIBlurEffect(style: .systemMaterial) } tabBarBackgroundView = UIVisualEffectView(effect: effect) @@ -86,13 +86,6 @@ import SnapKit customTabBarView.addSubview(tabBarBackgroundView) - // 添加阴影 - customTabBarView.layer.shadowColor = UIColor.black.cgColor - customTabBarView.layer.shadowOpacity = 0.15 - customTabBarView.layer.shadowOffset = CGSize(width: 0, height: -2) - customTabBarView.layer.shadowRadius = 10 - customTabBarView.layer.shadowPath = nil // 自动计算 - // 简化的布局约束(类似 Masonry 风格) customTabBarView.snp.makeConstraints { make in make.leading.equalTo(view).offset(16) @@ -118,12 +111,14 @@ import SnapKit selectedImage: "tab_moment_on", tag: 0 ) + momentButton.isSelected = true let mineButton = createTabButton( normalImage: "tab_mine_off", selectedImage: "tab_mine_on", tag: 1 ) + mineButton.isSelected = true tabButtons = [momentButton, mineButton] @@ -150,11 +145,14 @@ import SnapKit let button = UIButton(type: .custom) button.tag = tag + // 存储图片名称到 button,方便后续切换 + button.accessibilityLabel = normalImage + button.accessibilityHint = selectedImage + // 尝试设置自定义图片,如果不存在则使用 SF Symbols - if let normalImg = UIImage(named: normalImage), let selectedImg = UIImage(named: selectedImage) { - // 使用自定义图片 + if let normalImg = UIImage(named: normalImage), let _ = UIImage(named: selectedImage) { + // 使用自定义图片(初始显示 off 图片) button.setImage(normalImg, for: .normal) - button.setImage(selectedImg, for: .selected) } else { // 使用 SF Symbols 作为备用 let fallbackIcons = ["sparkles", "person.circle"] @@ -162,7 +160,6 @@ import SnapKit 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) } @@ -184,28 +181,57 @@ import SnapKit /// Tab 按钮点击事件 @objc private func tabButtonTapped(_ sender: UIButton) { - selectedIndex = sender.tag - updateTabButtonStates(selectedIndex: sender.tag) + let newIndex = sender.tag + + // 如果点击的是当前已选中的 tab,不做任何操作 + if newIndex == selectedIndex { + return + } + + // 先更新按钮状态 + updateTabButtonStates(selectedIndex: newIndex) + + // 再切换 ViewController(使用动画) + selectedIndex = newIndex let tabNames = ["动态", "我的"] - NSLog("[EPTabBarController] 选中 Tab: \(tabNames[sender.tag])") + NSLog("[EPTabBarController] 选中 Tab: \(tabNames[newIndex])") } /// 更新 Tab 按钮状态 private func updateTabButtonStates(selectedIndex: Int) { + // 禁用按钮交互,避免快速点击 + tabButtons.forEach { $0.isUserInteractionEnabled = false } + for (index, button) in tabButtons.enumerated() { let isSelected = (index == selectedIndex) button.isSelected = isSelected - // 如果是 SF Symbols,更新 tintColor - if button.tintColor != nil { + // 更新图片状态 + if let normalImageName = button.accessibilityLabel, + let selectedImageName = button.accessibilityHint { + // 使用自定义图片 + let imageName = isSelected ? selectedImageName : normalImageName + if let image = UIImage(named: imageName) { + button.setImage(image, for: .normal) + } else { + // 如果自定义图片不存在,使用 SF Symbols + button.tintColor = isSelected ? .white : .white.withAlphaComponent(0.6) + } + } else { + // 使用 SF Symbols(备用方案) button.tintColor = isSelected ? .white : .white.withAlphaComponent(0.6) } // 选中状态动画 - UIView.animate(withDuration: 0.2) { + UIView.animate(withDuration: 0.25, delay: 0, options: [.curveEaseInOut], animations: { button.transform = isSelected ? CGAffineTransform(scaleX: 1.1, y: 1.1) : .identity - } + }, completion: nil) + } + + // 延迟恢复按钮交互,避免动画期间的重复点击 + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { + self.tabButtons.forEach { $0.isUserInteractionEnabled = true } } } @@ -214,15 +240,18 @@ import SnapKit globalEventManager = GlobalEventManager.shared() globalEventManager?.setupSDKDelegates() - // 设置房间最小化视图 + // TODO: v0.2 版本暂时禁用房间最小化视图(无房间功能) + // 后续版本可通过 Build Configuration 或版本号判断是否启用 + /* if let containerView = view { globalEventManager?.setupRoomMiniView(on: containerView) } + */ // 注册社交分享回调 globalEventManager?.registerSocialShareCallback() - NSLog("[EPTabBarController] 全局管理器设置完成") + NSLog("[EPTabBarController] 全局管理器设置完成(v0.2 - 无 MiniRoom)") } /// 设置初始 ViewController(未登录状态) @@ -283,25 +312,31 @@ import SnapKit /// 设置登录后的 ViewControllers private func setupLoggedInViewControllers() { - // 创建真实的 ViewController(OC 类) - let momentVC = EPMomentViewController() - momentVC.tabBarItem = createTabBarItem( - title: "动态", - normalImage: "tab_moment_normal", - selectedImage: "tab_moment_selected" - ) + // 只在 viewControllers 为空或不是正确类型时才创建 + if viewControllers?.count != 2 || + !(viewControllers?[0] is EPMomentViewController) || + !(viewControllers?[1] is EPMineViewController) { + + // 创建真实的 ViewController(OC 类) + let momentVC = EPMomentViewController() + momentVC.tabBarItem = createTabBarItem( + title: "动态", + normalImage: "tab_moment_normal", + selectedImage: "tab_moment_selected" + ) + + let mineVC = EPMineViewController() + mineVC.tabBarItem = createTabBarItem( + title: "我的", + normalImage: "tab_mine_normal", + selectedImage: "tab_mine_selected" + ) + + viewControllers = [momentVC, mineVC] + NSLog("[EPTabBarController] 登录后 ViewControllers 创建完成 - Moment & Mine") + } - let mineVC = EPMineViewController() - mineVC.tabBarItem = createTabBarItem( - title: "我的", - normalImage: "tab_mine_normal", - selectedImage: "tab_mine_selected" - ) - - viewControllers = [momentVC, mineVC] selectedIndex = 0 - - NSLog("[EPTabBarController] 登录后 ViewControllers 设置完成 - Moment & Mine") } }