一、屏幕原點坐標的研究
小伙伴們可能發現,我們給一個空間設置origin為(0,0)的時候,有時候這個點會再屏幕的最左上角(有導航欄的情況下還可能會被導航欄給蓋住),有時候又在導航欄的下邊,都是同樣的原點坐標,那么為什么會出現這種情況呢?下面給出答案:
一個controller的view的原點位置受self.navigationController. navigationBar 的 setTranslucent (BOOL) 屬性控制,在 iOS7 以后 translucent 屬性默認為 YES。
translucent 為YES:原點位置坐標為屏幕左頂端,即屏幕坐標系(0 , 0),含義為毛玻璃、半透明效果。
translucent 為NO:原點位置坐標為導航欄的下邊的左頂端,即屏幕坐標系(0 , 64),此時導航欄不透明。
注意,當我們設置navigationBar的背景圖片setBackgroundImage(注意是背景圖片不是背景顏色)的時候,坐標起點也會變成(0,64),因為當我們設置背景圖片的時候,系統會自動修改translucent為NO。
二、自定制導航欄
修改導航欄可以采用全局修改(一般在appDelegate中或者在父navigationController中設置navigationBar ),也可以單獨在相應的頁面設置。
全局appearance修改:
UINavigationBar * navigationBarApperance = [UINavigationBar appearance];
//后續對bar設置,代碼省略。
父navigationController修改:
獲取self.navigationBar設置,代碼省略。
單獨頁面設置:
self.navigationController.navigationBar設置,代碼省略。
注:下文我們的示例代碼都是全局設置。
1.修改導航欄的“背景”顏色
修改導航欄顏色有如下幾種方式:
1.1 通過backgroundColor進行設置:
UINavigationBar * navigationBarApperance = [UINavigationBar appearance];
navigationBarApperance.backgroundColor = [UIColor redColor];
navigationBarApperance.translucent = YES;
此方式需要translucent=YES為前提,而且設置出來的背景顏色不純,會被導航欄的毛玻璃效果遮擋(至于為什么會被遮擋下文會講),此方式基本不成功,效果太傻缺,而且效果產生的優先級會很低,如果后面再設置navigationBar的barTintColor,會覆蓋掉這個效果。
綜上,次方式直接廢棄。
1.2 通過barTintColor進行設置:
UINavigationBar * navigationBarApperance = [UINavigationBar appearance];
navigationBarApperance.barTintColor = [UIColor redColor];
如上圖可以看到底部會有一條淺黃色(這個淺黃色是系統根據你導航欄的顏色自動適配的一個顏色)的分割線陰影,這條分割陰影是用來分割導航欄和下面視圖的。如你不想要分割線,你也可以通過設置相同顏色的陰影圖片去解除:
navigationBarApperance.shadowImage = [UIImage imageWithColor:[UIColor redColor]];
此方式設置的背景色,可以達到效果,但是效果產生的優先級比較弱沒有下面1.3的設置背景圖片高,同學們可以根據實際情況考量是否選擇此方法。
綜上,此方法可行,優先級相對弱,推薦,綜合考量使用。
1.3 通過設置setBackgroundImage進行設置:
UINavigationBar * navigationBarApperance = [UINavigationBar appearance];
[navigationBarApperance setBackgroundImage:[UIImage imageWithColor:[UIColor redColor]] forBarMetrics:UIBarMetricsDefault];
此方法設置的導航欄底部也會有一條淺黃的分割線陰影,和上面barTintColor效果一樣,底下的分割線陰影也可以自動以設置。但是需要注意的是,此方法設置的優先級是最高的,會覆蓋掉1.1,1.2中所有設置的背景色。
驗證如下:
UINavigationBar * navigationBarApperance = [UINavigationBar appearance];
[navigationBarApperance setBackgroundImage:[UIImage imageWithColor:[UIColor whiteColor]] forBarMetrics:UIBarMetricsDefault];
navigationBarApperance.barTintColor = [UIColor redColor];
以上代碼我先設置白色背景圖,再設置紅色barTintColor,但是紅色的背景色沒有生效,還是被白色背景圖覆蓋,如下圖:
綜上,此方法可行,優先級最高,推薦,綜合考量使用。
這里說個查bug的小提示,當我們在某個頁面設置了導航欄背景色,但是沒有生效,這個時候我們需要檢查下是不是我們用的bartintColor設置的被父類的設置背景圖給覆蓋了,導致沒有生效,這個時候你就需要也用設置背景色來設置了。
下面我們針對前面提出的為什么設置的backgrandColor會被遮擋做出解釋。
導航欄的層級圖如下:
從上圖我們可以看到,導航欄一共分為4大層,分別是,
1:背景色(backgroundColor)層,在最下面
2:背景層(barbackground),用作父視圖
3:背景圖片(imageview)層,此處有2個imageview,一個是背景圖片,一個市分割線圖片
4:主內容(contentview)層,用來顯示navigationItem,比如導航欄的title,titleview,barButtonItem等。
通過層級我們可以看到,我們前面之所以設置的背景色顯示不出來,是因為這個背景色在最底層,會被上面的背景層給遮擋,個人感覺說白了,我們設置導航欄的背景色就是無用的。
2.設置導航欄上的字體顏色
2.1 設置導航欄左右兩邊barbuttonItem的顏色:tintColor
navigationBarApperance.barTintColor = [UIColor greenColor];
注意:這種方式不能改變導航欄中間標題的顏色
barbuttonItem的顏色也可以通過自定制視圖設置:
UIButton *leftBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[leftBtn setTitle:@"左邊" forState:UIControlStateNormal];
[leftBtn setTitleColor:[UIColor greenColor] forState:UIControlStateNormal];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:leftBtn];
以上這種自定制設置如果設置了顏色會覆蓋掉前面設置的tintColor。
2.2 設置導航欄中間標題的顏色,字體:通過設置屬性字符串實現TitleTextAttributes
navigationBarApperance.titleTextAttributes = @{NSForegroundColorAttributeName : [UIColor redColor],NSFontAttributeName:[UIFont systemFontOfSize:18]};
這里說下,設置頁面導航欄標題的方式,有兩種:
方式一:self.title = @"首頁";
方式二:self.navigationItem.title = @"首頁";
這兩種方式都可以設置標題,而且效果是一樣的,如果這兩個方式都設置了標題,那么最后的標題會覆蓋掉前面的設置的。
3.梳理下navigationBar,navigationItem的關系
navigationBar是UINavigationController的一個屬性,主要用來設置導航欄顏色(背景色和鏤空色tintColor)
navigationItem是UIViewController的一個分類UINavigationControllerItem中的屬性,主要用來自定制導航欄上顯示的東西,包括左右兩邊的barbuttonItem,中間的title或者中間的titleview。navigationItem主要是前面介紹的導航欄層級中最上層contentview的子視圖。
三、常用設置導航欄,tabbar代碼
1.統一設置NavigationBar的顏色、tint顏色、、字體
// 設置導航欄的顏色 [[UINavigationBar appearance] setBarTintColor:[UIColor redColor]]; // 設置tint顏色 [[UINavigationBar appearance] setTintColor: [UIColor whiteColor]]; // 設置導航欄上的標題的顏色、字體 [[UINavigationBar appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor redColor],NSFontAttributeName:[UIFont systemFontOfSize:18]}]; // 取消透明度 [[UINavigationBar appearance] setTranslucent:NO]; // 設置背景圖片(前面已經設置了顏色,此處可以不設置,避免覆蓋掉上面的顏色) [[UINavigationBar appearance] setBackgroundImage:xxx forBarMetrics:UIBarMetricsDefault]; // 去掉導航欄與內容之間的分割線 [self.navigationController.navigationBar setShadowImage:nil];
2、設置tabbar相關
[[UITabBar appearance] setTintColor: [UIColor blueColor]]; //Normal [[UITabBarItem appearance] setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12],NSBackgroundColorAttributeName:[UIColor greenColor]} forState:UIControlStateNormal]; //Selected [[UITabBarItem appearance] setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:15],NSBackgroundColorAttributeName:[UIColor redColor]} forState:UIControlStateSelected]; // 設置tabbar上的圖片不要用tintcolor,使用圖片原生的樣子 UIImage *normalImg = [[UIImage imageNamed:@"xxx"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; vc.tabBarItem.image = normalImg; UIImage *selectImg = [[UIImage imageNamed:@"xxx"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; vc.tabBarItem.selectedImage = selectImg; // 將tabbar的顏色設置為黑色 self.tabBar.barTintColor = [UIColor blackColor];