能否用UINavigationBar Appearance为不同控制器配置不同导航栏背景色?
appearanceWhenContainedInInstancesOfClasses失效的核心原因是:导航栏属于上层的NavigationController,和ControllerA、ControllerB没有直接的容器关联,没法通过这个方法绑定控制器与导航栏的外观规则。不过可以通过以下两种基于Appearance框架的思路实现需求:
方法一:给NavigationController加标识,结合Appearance条件匹配
- 给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
- 在导航控制器的代理方法里,根据即将显示的控制器更新标识:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated { navigationController.needGreenNavBar = [viewController isKindOfClass:[ControllerB class]]; // 触发导航栏外观刷新 [navigationController.navigationBar setNeedsLayout]; }
- 利用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框架的官方用法:
- 提前定义两种配色的外观实例:
// 可全局定义或在控制器内部声明 UINavigationBarAppearance *redNavBarAppearance = [[UINavigationBarAppearance alloc] init]; redNavBarAppearance.backgroundColor = [UIColor redColor]; UINavigationBarAppearance *greenNavBarAppearance = [[UINavigationBarAppearance alloc] init]; greenNavBarAppearance.backgroundColor = [UIColor greenColor];
- 在ControllerA的
viewWillAppear:中设置红色外观:
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; self.navigationController.navigationBar.standardAppearance = redNavBarAppearance; self.navigationController.navigationBar.scrollEdgeAppearance = redNavBarAppearance; }
- 在ControllerB的
viewWillAppear:中设置绿色外观:
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; self.navigationController.navigationBar.standardAppearance = greenNavBarAppearance; self.navigationController.navigationBar.scrollEdgeAppearance = greenNavBarAppearance; }
内容的提问来源于stack exchange,提问作者ximmyxiao
相关产品推荐
相关产品推荐

