From 8b177e5fadf2d0231c41e6057e1711f3c59c741e Mon Sep 17 00:00:00 2001 From: edwinQQQ Date: Fri, 10 Oct 2025 15:58:23 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=B6=88=E9=99=A4=20TabBar=20=E5=88=87?= =?UTF-8?q?=E6=8D=A2=E6=97=B6=E7=9A=84=E9=A1=B5=E9=9D=A2=E9=97=AA=E7=83=81?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 核心修复: 1. 移除导航栏动画冲突 - 移除 viewWillAppear 中的 navigationBar 隐藏逻辑 - ViewController 未包装在 NavigationController 中,调用导航栏方法会触发冗余动画 2. 禁用 UITabBarController 默认切换动画 - 设置 UITabBarControllerDelegate - animationControllerForTransitionFrom 返回 nil 禁用系统动画 - 使用 UIView.performWithoutAnimation 确保无动画切换 3. 修复背景色未定义导致的白色闪烁 - 显式设置浅灰色背景作为兜底 (RGB: 0.95, 0.95, 0.97) - 添加背景图片的 contentMode 和 clipsToBounds 属性 - 确保背景图片加载延迟时不显示白色 修复后效果: - Tab 切换流畅无闪烁,仅保留按钮缩放动画 - 背景色始终一致,无白色背景闪现 - 性能提升,消除多个动画冲突 --- .../Controllers/EPMineViewController.m | 11 ++- .../Controllers/EPMomentViewController.m | 15 ++-- .../NewTabBar/EPTabBarController.swift | 71 +++++++++++-------- 3 files changed, 60 insertions(+), 37 deletions(-) diff --git a/YuMi/E-P/NewMine/Controllers/EPMineViewController.m b/YuMi/E-P/NewMine/Controllers/EPMineViewController.m index dfc49b5..3a535dc 100644 --- a/YuMi/E-P/NewMine/Controllers/EPMineViewController.m +++ b/YuMi/E-P/NewMine/Controllers/EPMineViewController.m @@ -63,8 +63,8 @@ - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - // 刷新用户信息 - [self refreshUserInfo]; + // 注意:当前 ViewController 没有包装在 NavigationController 中 + // 如果未来需要导航栏,应该在 TabBarController 中包装 UINavigationController } // MARK: - Setup @@ -82,8 +82,12 @@ } - (void)setupUI { + // 先设置纯色背景作为兜底,避免白色闪烁 + self.view.backgroundColor = [UIColor colorWithRed:0.95 green:0.95 blue:0.97 alpha:1.0]; UIImageView *bgImageView = [[UIImageView alloc] initWithImage:kImage(@"vc_bg")]; + bgImageView.contentMode = UIViewContentModeScaleAspectFill; + bgImageView.clipsToBounds = YES; [self.view addSubview:bgImageView]; [bgImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.mas_equalTo(self.view); @@ -201,6 +205,9 @@ - (void)refreshData { self.currentPage = 1; [self.momentsData removeAllObjects]; + + // 手动下拉刷新时才更新用户信息 + [self loadUserInfo]; [self loadUserMoments]; } diff --git a/YuMi/E-P/NewMoments/Controllers/EPMomentViewController.m b/YuMi/E-P/NewMoments/Controllers/EPMomentViewController.m index bfa5deb..6fe702e 100644 --- a/YuMi/E-P/NewMoments/Controllers/EPMomentViewController.m +++ b/YuMi/E-P/NewMoments/Controllers/EPMomentViewController.m @@ -56,14 +56,19 @@ - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - // 隐藏导航栏(如果需要沉浸式体验) - // [self.navigationController setNavigationBarHidden:YES animated:animated]; + // 注意:当前 ViewController 没有包装在 NavigationController 中 + // 如果未来需要导航栏,应该在 TabBarController 中包装 UINavigationController } // MARK: - Setup UI - (void)setupUI { + // 先设置纯色背景作为兜底,避免白色闪烁 + self.view.backgroundColor = [UIColor colorWithRed:0.95 green:0.95 blue:0.97 alpha:1.0]; + UIImageView *bgImageView = [[UIImageView alloc] initWithImage:kImage(@"vc_bg")]; + bgImageView.contentMode = UIViewContentModeScaleAspectFill; + bgImageView.clipsToBounds = YES; [self.view addSubview:bgImageView]; [bgImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.mas_equalTo(self.view); @@ -75,7 +80,7 @@ make.edges.equalTo(self.view); }]; - // 发布按钮(悬浮在右下角) + // TODO: 调整为右上角 [self.view addSubview:self.publishButton]; [self.publishButton mas_makeConstraints:^(MASConstraintMaker *make) { make.right.equalTo(self.view).offset(-20); @@ -99,7 +104,9 @@ NSString *pageSize = @"10"; NSString *types = @"0,2"; // 类型:0=图片,2=文字 + @kWeakify(self); [Api momentsRecommendList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { + @kStrongify(self); self.isLoading = NO; [self.refreshControl endRefreshing]; @@ -202,7 +209,7 @@ _tableView.delegate = self; _tableView.dataSource = self; _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; - _tableView.backgroundColor = self.view.backgroundColor; + _tableView.backgroundColor = [UIColor clearColor]; // 透明背景,显示下层背景图 _tableView.estimatedRowHeight = 200; _tableView.rowHeight = UITableViewAutomaticDimension; _tableView.showsVerticalScrollIndicator = NO; diff --git a/YuMi/Modules/NewTabBar/EPTabBarController.swift b/YuMi/Modules/NewTabBar/EPTabBarController.swift index 7d5824a..b4b784f 100644 --- a/YuMi/Modules/NewTabBar/EPTabBarController.swift +++ b/YuMi/Modules/NewTabBar/EPTabBarController.swift @@ -43,6 +43,9 @@ import SnapKit // 隐藏原生 TabBar self.tabBar.isHidden = true + // 设置 delegate 以完全控制切换行为 + self.delegate = self + setupCustomFloatingTabBar() setupGlobalManagers() setupInitialViewControllers() @@ -111,14 +114,12 @@ 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] @@ -144,35 +145,35 @@ import SnapKit 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 + button.adjustsImageWhenHighlighted = false // 禁用高亮效果,避免闪烁 // 尝试设置自定义图片,如果不存在则使用 SF Symbols - if let normalImg = UIImage(named: normalImage), let _ = UIImage(named: selectedImage) { - // 使用自定义图片(初始显示 off 图片) + if let normalImg = UIImage(named: normalImage), let selectedImg = UIImage(named: selectedImage) { + // 正确设置:分别为 normal 和 selected 状态设置图片 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) + let normalIcon = UIImage(systemName: iconName, withConfiguration: imageConfig) - button.setImage(UIImage(systemName: iconName, withConfiguration: imageConfig), for: .normal) + button.setImage(normalIcon, for: .normal) + button.setImage(normalIcon, for: .selected) 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) // 图标大小 + make.size.equalTo(28) } button.addTarget(self, action: #selector(tabButtonTapped(_:)), for: .touchUpInside) @@ -191,8 +192,10 @@ import SnapKit // 先更新按钮状态 updateTabButtonStates(selectedIndex: newIndex) - // 再切换 ViewController(使用动画) - selectedIndex = newIndex + // 禁用 UITabBarController 的默认切换动画,避免闪烁 + UIView.performWithoutAnimation { + selectedIndex = newIndex + } let tabNames = ["动态", "我的"] NSLog("[EPTabBarController] 选中 Tab: \(tabNames[newIndex])") @@ -205,32 +208,23 @@ import SnapKit for (index, button) in tabButtons.enumerated() { let isSelected = (index == selectedIndex) + + // 直接设置 isSelected 属性即可,图片会自动切换 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(备用方案) + // SF Symbols 的情况需要手动更新 tintColor + if button.currentImage?.isSymbolImage == true { button.tintColor = isSelected ? .white : .white.withAlphaComponent(0.6) } - // 选中状态动画 - UIView.animate(withDuration: 0.25, delay: 0, options: [.curveEaseInOut], animations: { + // 选中状态缩放动画 + UIView.animate(withDuration: 0.2, delay: 0, options: [.curveEaseOut], animations: { button.transform = isSelected ? CGAffineTransform(scaleX: 1.1, y: 1.1) : .identity - }, completion: nil) + }) } - // 延迟恢复按钮交互,避免动画期间的重复点击 - DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { + // 延迟恢复按钮交互 + DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { self.tabButtons.forEach { $0.isUserInteractionEnabled = true } } } @@ -347,6 +341,21 @@ extension EPTabBarController: UITabBarControllerDelegate { override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) { NSLog("[EPTabBarController] 选中 Tab: \(item.title ?? "Unknown")") } + + /// 禁用系统默认的切换动画 + func tabBarController(_ tabBarController: UITabBarController, + animationControllerForTransitionFrom fromVC: UIViewController, + to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { + // 返回 nil 表示不使用动画 + return nil + } + + /// 完全控制是否允许切换 + func tabBarController(_ tabBarController: UITabBarController, + shouldSelect viewController: UIViewController) -> Bool { + // 允许切换,但通过返回 nil 的 animationController 来禁用动画 + return true + } } // MARK: - OC Compatibility