You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否用UINavigationBar Appearance为不同控制器配置不同导航栏背景色?

解决方案:用UINavigationBar Appearance实现不同控制器的导航栏配色

appearanceWhenContainedInInstancesOfClasses失效的核心原因是:导航栏属于上层的NavigationController,和ControllerA、ControllerB没有直接的容器关联,没法通过这个方法绑定控制器与导航栏的外观规则。不过可以通过以下两种基于Appearance框架的思路实现需求:

方法一:给NavigationController加标识,结合Appearance条件匹配

  1. 给UINavigationController添加分类,新增一个自定义布尔属性用来标记当前导航栏需要的配色状态:
// UINavigationController+NavBarStyle.h
#import <UIKit/UIKit.h>

@interface UINavigationController (NavBarStyle)
@property (nonatomic, assign) BOOL needGreenNavBar;
@end

// UINavigationController+NavBarStyle.m
#import "UINavigationController+NavBarStyle.h"
#import <objc/runtime.h>

@implementation UINavigationController (NavBarStyle)
static char kNeedGreenNavBarKey;

- (BOOL)needGreenNavBar {
    return [objc_getAssociatedObject(self, &kNeedGreenNavBarKey) boolValue];
}

- (void)setNeedGreenNavBar:(BOOL)needGreenNavBar {
    objc_setAssociatedObject(self, &kNeedGreenNavBarKey, @(needGreenNavBar), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
  1. 在导航控制器的代理方法里,根据即将显示的控制器更新标识:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    navigationController.needGreenNavBar = [viewController isKindOfClass:[ControllerB class]];
    // 触发导航栏外观刷新
    [navigationController.navigationBar setNeedsLayout];
}
  1. 利用iOS 13+支持的when:方法,根据导航控制器的标识设置对应外观:
// 在AppDelegate/SceneDelegate的初始化代码中配置
[[UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[[UINavigationController class]]] 
 whenCondition:^BOOL(UINavigationBar *bar) {
    UINavigationController *nav = (UINavigationController *)bar.viewController;
    return nav.needGreenNavBar;
} setBackgroundColor:[UIColor greenColor]];

[[UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[[UINavigationController class]]] 
 whenCondition:^BOOL(UINavigationBar *bar) {
    UINavigationController *nav = (UINavigationController *)bar.viewController;
    return !nav.needGreenNavBar;
} setBackgroundColor:[UIColor redColor]];

方法二:用UINavigationBarAppearance实例动态切换(iOS 13+)

如果不需要兼容iOS 13以下版本,可直接在控制器生命周期中切换导航栏的外观实例,这也是基于Appearance框架的官方用法:

  1. 提前定义两种配色的外观实例:
// 可全局定义或在控制器内部声明
UINavigationBarAppearance *redNavBarAppearance = [[UINavigationBarAppearance alloc] init];
redNavBarAppearance.backgroundColor = [UIColor redColor];

UINavigationBarAppearance *greenNavBarAppearance = [[UINavigationBarAppearance alloc] init];
greenNavBarAppearance.backgroundColor = [UIColor greenColor];
  1. 在ControllerA的viewWillAppear:中设置红色外观:
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.navigationController.navigationBar.standardAppearance = redNavBarAppearance;
    self.navigationController.navigationBar.scrollEdgeAppearance = redNavBarAppearance;
}
  1. 在ControllerB的viewWillAppear:中设置绿色外观:
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.navigationController.navigationBar.standardAppearance = greenNavBarAppearance;
    self.navigationController.navigationBar.scrollEdgeAppearance = greenNavBarAppearance;
}

内容的提问来源于stack exchange,提问作者ximmyxiao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 15:57:52