在 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]]; }