// // 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) } }