fix: 消除 TabBar 切换时的页面闪烁问题
核心修复: 1. 移除导航栏动画冲突 - 移除 viewWillAppear 中的 navigationBar 隐藏逻辑 - ViewController 未包装在 NavigationController 中,调用导航栏方法会触发冗余动画 2. 禁用 UITabBarController 默认切换动画 - 设置 UITabBarControllerDelegate - animationControllerForTransitionFrom 返回 nil 禁用系统动画 - 使用 UIView.performWithoutAnimation 确保无动画切换 3. 修复背景色未定义导致的白色闪烁 - 显式设置浅灰色背景作为兜底 (RGB: 0.95, 0.95, 0.97) - 添加背景图片的 contentMode 和 clipsToBounds 属性 - 确保背景图片加载延迟时不显示白色 修复后效果: - Tab 切换流畅无闪烁,仅保留按钮缩放动画 - 背景色始终一致,无白色背景闪现 - 性能提升,消除多个动画冲突
This commit is contained in:
@@ -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];
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user