在 App 开发的过程中,经常会要求对顶部导航栏进行自定义。本文将介绍在基于 mPaaS 框架创建的页面中,自定义导航栏的方法。包括定制应用主题和定制某一个页面导航栏样式。
基础概念
导航栏元素分布
导航栏元素主要分布在三个区域。一般对导航栏的定制化需求,最终都会变为对这几个区域的修改:
back:返回按钮控制区域,由 mPaaS 页面基类创建,默认样式为返回箭头 + 返回文案。
title/subTitle:标题栏控制区域,默认不显示。若需显示,请调用系统方法设置当前页面的 title。
optionMenu:页面菜单选项区域,默认不显示。如需显示,请调用系统方法设置当前页面的 rightNavigationItem。
导航栏结构
如下图所示,基于 mPaaS 框架创建的应用,默认的 UI 结构为:
window/navigationController
>tabViewController
> 每个 tab 嵌入一个viewController
。即应用主 window 的根应用是一个UINavigationController
的对象,UINavigationController
的根应用是一个UITabViewController
。由以上 UI 结构可以看出,整个应用全局只有一个
navigationController
,因此所有页面共用同一个导航栏(默认使用APNavigationBar
创建)。为了统一所有页面的导航栏样式,要求 mPaaS 应用中,所有页面所在的 VC 都要继承
DTViewControler
,包括 native 和 H5 页面。基于 mPaaS 框架创建的应用的默认主题,主白底黑字蓝按钮:
定制应用主题
每个应用都会有自己的主题风格,根据以下描述修改 mPaaS 应用的默认主题:
修改导航栏背景色、返回控制区域、标题控制区域等,可重写 AUThemeManager 类的
au_defaultTheme_extraInfo
方法,修改以下 key 对应的返回值。接口方法
@interface AUThemeManager(AUExtendinfo) /*支付宝客户端存在默认主题,独立 App 可修改该默认值 * 在该方法中只需返回与默认主题不同的键值对即可,请使用 AUTheme.h 中定义好的 key */ +(NSDictionary *)au_defaultTheme_extraInfo; @end /* * 例如 * +(NSDictionary*)au_defaultTheme_add_Info * { * NSMutableDictionary *dict = [INSMutableDictionary alloc] init]; * dictITITLEBAR_BACKGROUND_COLOR] = AU_COLOR_APP_GREEN; // AUTitleBar 背景色 * dit[TITLEBAR TITLE TEXTCOLOR1 = [UIColor redColor]; // AUTitleBar 标题色 * ... * return dict; * } */
代码示例
@implementation AUThemeManager (Portal) + (NSDictionary *)au_defaultTheme_extraInfo { NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; dict[TITLEBAR_BACKGROUND_COLOR] = @"COLOR(#108EE9,1)"; // 导航栏背景色 dict[TITLEBAR_LINE_COLOR] = @"COLOR(#108EE9,1)"; // 导航栏底部分割线或边线的颜色 dict[TITLEBAR_TITLE_TEXTCOLOR] = @"COLOR(#ffffff,1)"; // 导航栏标题色 dict[TITLEBAR_TITLE_TEXTSIZE_BOLD] = @"FONT(18)"; // 导航栏标题大小 dict[TITLEBAR_TEXTCOLOR] = @"COLOR(#ffffff,1)"; // 导航栏返回按钮颜色 return dict; } @end }
说明颜色值必须使用类如 COLOR(#108EE9,1) 的方式,否则会报错。
修改主题配置中返回按钮图片,需重写 AUBarButtonItem 类中的
au_default_backButtonImg
方法。接口方法
#import "AUUILoadDefine.h"//程序自动生成 #ifdef ANTUI_UI_TitleBar_AUBarButtonltem//程序自动生成 // // AUBarButtonltem+AUExtendInfo.h // AntUI // // Copyright © 2017 Alipay. All rights reserved. // #import "AUBarButtonltem.h" @interface AUBarButtonltem(AUExtendInfo) //支付宝返回按钮默认是蓝色 icon,独立 App 可修改返回按钮默认图标 +(UIImage *)au_default_backButtonlmg; @end
代码示例
@implementation AUBarButtonItem (CGBBarButtonItem) + (UIImage *)au_default_backButtonImg { // 自定义返回按钮的图片 return APCommonUILoadImage(@"back_button_normal_white"); } @end
修改所有页面的返回按钮样式和文案。
定制某一个页面导航栏样式
除了定制主题外,有时也需定制当前页面的导航栏的样式,如修改背景颜色、返回按钮样式等,根据修改时机不同,mPaaS 提供了不同的方法。
页面加载前,在默认导航栏样式基础上修改导航栏颜色,可以在当前页面所在的 VC 中,实现
DTNavigationBarAppearanceProtocol
中的定义方法,来修改对应区域的颜色。接口方法
@protocol DTNavigationBarAppearanceProtocol<NSObject> @optional /** 这个 DTViewController 是否要自动隐藏navigationBar,默认为 NO。业务某个 ViewController 需要隐藏 NavigationBar 可以重载此方法并返回 YES. **/ -(BOOL)autohideNavigationBar; /** 当前 VC 隐藏导航栏后,如果需要设置一个全透明的导航栏,且当前页面需设置与框架逻辑一致的返回文案,请重载此方法,并返回一个 APCustomNavigationView 的实例 -(UIView *)customNavigationBar; /** 如果某个 viewcontroller 希望自己的 titlebar 是不透明,并且指定一个颜色,可以重写这个方法,并返回希望的颜色。 * 仅限于被 Push 的 VC,tabbar 里的 VC 还是不允许修改 navigationBar 的半透明属性 */ -(UIColor *)opaqueNavigationBarColor; /** * 如果某个viewcontroller希望修改状态栏的样式,请重写此方法,并返回希望的style */ - (UIStatusBarStyle)customStatusBarStytle; /** * 如果某个viewcontroller希望修改导航栏标题的颜色,请重写此方法,并返回希望的颜色 */ - (UIColor *)customNavigationBarTitleColor;
代码示例
#pragma mark DTNavigationBarAppearanceProtocol:进入页面时修改导航栏样式 - (UIColor *)opaqueNavigationBarColor { // 设置当前页面导航栏背景为红色 return [UIColor redColor]; // // 设置当前页面导航栏透明 // return [UIColor colorWithRGB:0xff0000 alpha:0]; } - (BOOL)autohideNavigationBar { // 设置当前页面导航栏是否隐藏 return NO; } - (UIStatusBarStyle)customStatusBarStytle { // 设置当前页面状态栏样式 return UIStatusBarStyleDefault; } - (UIColor *)customNavigationBarBackButtonTitleColor { // 设置当前页面返回按钮文案颜色 return [UIColor greenColor]; } - (UIImage *)customNavigationBarBackButtonImage { // 设置当前页面返回按钮图片 return APCommonUILoadImage(@"back_button_normal_white"); } - (UIColor *)customNavigationBarTitleColor { // 设置当前页面标题颜色 return [UIColor greenColor]; }
页面打开后,在用户操作的过程中动态修改导航栏样式,如背景颜色滑动渐变、修改右侧菜单按钮等,根据修改的区域不同,主要分为以下几类:
背景区域:包括隐藏/显示导航栏、透明导航栏、修改导航栏背景颜色、修改状态栏颜色。
- (void)gotoHideNavigator { // 隐藏导航栏 [self.navigationController.navigationBar setHidden:YES]; } - (void)gotoShowNavigator { // 显示导航栏 [self.navigationController.navigationBar setHidden:NO]; } - (void)gotoTransparency { // 透明导航栏 [self.navigationController.navigationBar setNavigationBarTranslucentStyle]; } - (void)gotoUpdateBackgroundColor { // 修改导航栏背景颜色 [self.navigationController.navigationBar setNavigationBarStyleWithColor:[UIColor whiteColor] translucent:NO]; [self.navigationController.navigationBar setNavigationBarBottomLineColor:[UIColor whiteColor]]; } - (void)gotoUpdateStatusBarStyle { // 修改状态栏颜色 [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; }
返回控制区域:修改默认返回按钮文案颜色、修改默认返回按钮返回箭头样式、重新设置返回按钮样式。
- (void)gotoUpdateBackTitleColor { // 修改默认返回按钮文案颜色 NSArray *leftBarButtonItems = self.navigationItem.leftBarButtonItems; if ([leftBarButtonItems count] == 1) { if (leftBarButtonItems[0] && [leftBarButtonItems[0] isKindOfClass:[AUBarButtonItem class]]) { AUBarButtonItem *backItem = leftBarButtonItems[0]; backItem.titleColor = [UIColor blackColor]; } } } - (void)gotoUpdateBackImage { // 修改默认返回按钮返回箭头样式 NSArray *leftBarButtonItems = self.navigationItem.leftBarButtonItems; if ([leftBarButtonItems count] == 1) { if (leftBarButtonItems[0] && [leftBarButtonItems[0] isKindOfClass:[AUBarButtonItem class]]) { AUBarButtonItem *backItem = leftBarButtonItems[0]; backItem.backButtonImage = APCommonUILoadImage(@"back_button_normal"); } } } - (void)gotoUpdateBackItem { // 重新设置返回按钮样式 self.navigationItem.leftBarButtonItem = [AUBarButtonItem barButtonItemWithImageType:AUBarButtonImageTypeDelete target:self action:@selector(onClickBack)]; } - (void)onClickBack { [self.navigationController popViewControllerAnimated:YES]; }
标题控制区域:修改默认标题颜色、设置上下主副标题、修改标题为图片显示。
- (void)gotoUpdateTitleColor { // 修改标题颜色 [self.navigationController.navigationBar setNavigationBarTitleTextAttributesWithTextColor:[UIColor blackColor]]; } - (void)gotoTwoTitle { // 修改标题样式:上下主副标题 self.navigationItem.titleView = [[AUDoubleTitleView alloc] initWithTitle:@"主标题" detailTitle:@"副标题"]; } - (void)gotoTitleImage { // 修改标题样式:图片 UIImageView *imageView = [[UIImageView alloc] initWithImage:APCommonUILoadImage(@"ilustration_ap_expection_alert")]; imageView.frame = CGRectMake(0, 0, self.self.view.width-100, 64); self.navigationItem.titleView = imageView; }
菜单控制区域:设置单个或多个右侧菜单按钮。
- (void)gotoSetOptionMenu { // 设置右侧单按钮 self.navigationItem.rightBarButtonItem = [AUBarButtonItem barButtonItemWithImageType:AUBarButtonImageTypeGroupChat target:self action:@selector(onClickRightItem)]; } - (void)gotoSetTwoOptionMenu { // 设置右侧双按钮 AUBarButtonItem *item1 = [AUBarButtonItem barButtonItemWithImageType:AUBarButtonImageTypeGroupChat target:self action:@selector(onClickRightItem)]; AUBarButtonItem *item2 = [AUBarButtonItem barButtonItemWithImageType:AUBarButtonImageTypeHelp target:self action:@selector(onClickRightItem)]; self.navigationItem.rightBarButtonItems = @[item1, item2]; }
沉浸式导航栏:进入时导航栏透明,滑动到指定位置后不透明。主要分为以下两类:
进入页面时,设置导航栏透明:在当前页面所在的 VC 中重写以下接口。
- (UIColor *)opaqueNavigationBarColor { // 设置当前页面导航栏透明 return [UIColor colorWithRGB:0xff0000 alpha:0]; }
页面滑动到指定位置后,修改导航栏背景区域、返回区域、标题区域及菜单控制区域等样式。
- (void)gotoUpdateBackgroundColor { // 修改导航栏背景颜色 [self.navigationController.navigationBar setNavigationBarStyleWithColor:[UIColor whiteColor] translucent:NO]; [self.navigationController.navigationBar setNavigationBarBottomLineColor:[UIColor whiteColor]]; } - (void)gotoUpdateBackTitleColor { // 修改默认返回按钮文案颜色 NSArray *leftBarButtonItems = self.navigationItem.leftBarButtonItems; if ([leftBarButtonItems count] == 1) { if (leftBarButtonItems[0] && [leftBarButtonItems[0] isKindOfClass:[AUBarButtonItem class]]) { AUBarButtonItem *backItem = leftBarButtonItems[0]; backItem.titleColor = [UIColor blackColor]; } } } - (void)gotoUpdateTitleColor { // 修改标题颜色 [self.navigationController.navigationBar setNavigationBarTitleTextAttributesWithTextColor:[UIColor blackColor]]; }