iOS 中關于導航欄和分欄遇到的問題

translucent

先來看下官方文檔

/*
 New behavior on iOS 7.
 Default is YES.
 You may force an opaque background by setting the property to NO.
 If the navigation bar has a custom background image, the default is inferred 
 from the alpha values of the image—YES if it has any pixel with alpha < 1.0
 If you send setTranslucent:YES to a bar with an opaque custom background image
 it will apply a system opacity less than 1.0 to the image.
 If you send setTranslucent:NO to a bar with a translucent custom background image
 it will provide an opaque background for the image using the bar's barTintColor if defined, or black
 for UIBarStyleBlack or white for UIBarStyleDefault if barTintColor is nil.
 */
@property(nonatomic,assign,getter=isTranslucent) BOOL translucent API_AVAILABLE(ios(3.0)) UI_APPEARANCE_SELECTOR; // Default is NO on iOS 6 and earlier. Always YES if barStyle is set to UIBarStyleBlackTranslucent

iOS 7 之后,該屬性默認為 YES。但是如果給導航欄設置了一張自定義的背景圖片,如果該圖片有一個 alpha<1 的像素,那么該值就為 YES,否則為 NO。(設置導航欄的背景圖片會影響 translucent 的默認值)

如果手動設置了該屬性,并且設置了導航欄的背景圖,則系統(tǒng)可能會對背景圖進行處理:

    1. 如果設置該屬性為 YES,但是提供了一張不透明的背景圖,系統(tǒng)會對該背景圖進行半透明處理
    1. 如果設置該屬性為 NO,但是提供了一張半透明的背景圖,則系統(tǒng)會對該背景圖進行不透明處理。具體是根據(jù)導航欄的 style 或者 barTintColor 進行處理

總結(iOS 7 以上系統(tǒng)):

    1. 當導航欄沒有被隱藏時,且 translucent 屬性設置為 YES,那么,UIViewControllerviewframe 起始點是從屏幕的左上角(0,0)開始,大小是整個屏幕寬高。而當 translucent 屬性設置為 NO 時,那么 UIViewControllerviewframe 起始點是從導航欄左下角開始,寬是屏幕的寬,高是整個屏幕減去導航欄的高度。
    1. UIViewControllerview 的子視圖布局推薦在viewWillLayoutSubviews 中進行,因為此時不管 translucent 為何值,它的 size 都是正確的。
示例

同樣一份代碼,在不同的控制器中,一個控制器導航欄是透明的,一個不透明

UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(30, 10, 200, 100)];
view1.backgroundColor = [UIColor redColor];
[self.view addSubview:view1];

UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(30, [UIScreen mainScreen].bounds.size.height - 200, 200, 200)];
view2.backgroundColor = [UIColor greenColor];
[self.view addSubview:view2];

運行截圖如下

push 時控件下移

push 操作是導航欄特有的,關于它的 translucent 上面也介紹了,下面從兩個方法分析

extendedLayoutIncludesOpaqueBars

官方文檔說明

@property(nonatomic,assign) BOOL extendedLayoutIncludesOpaqueBars API_AVAILABLE(ios(7.0)); // Defaults to NO, but bars are translucent by default on 7_0. 

YES 代表當導航欄不透明時,當前頁面 view 的布局從導航欄頂部開始計算。 需要注意:導航欄半透明時,view 是包含導航欄的。如果一個導航欄不透明,另一個導航欄透明,切換就會出現(xiàn)問題。

edgesForExtendedLayout

官方文檔說明


typedef NS_OPTIONS(NSUInteger, UIRectEdge) {
    UIRectEdgeNone   = 0, //self.view.frame是從navigationBar下面開始計算一直到屏幕tabBar上部
    UIRectEdgeTop    = 1 << 0, //self.view.frame是從navigationBar上面計算面開始計算一直到屏幕tabBar上部
    UIRectEdgeLeft   = 1 << 1,
    UIRectEdgeBottom = 1 << 2, //self.view.frame是從navigationBar下面開始計算一直到屏幕底部
    UIRectEdgeRight  = 1 << 3,
    UIRectEdgeAll    = UIRectEdgeTop | UIRectEdgeLeft | UIRectEdgeBottom | UIRectEdgeRight //布局是從navigationbar頂部開始,屏幕底部結束
} API_AVAILABLE(ios(7.0));

@property(nonatomic,assign) UIRectEdge edgesForExtendedLayout API_AVAILABLE(ios(7.0)); // Defaults to UIRectEdgeAll

邊緣延伸屬性。是視圖控制器的布局屬性,默認值是 UIRectEdgeAll,即:當前視圖控制器里各種UI控件【本身】(而非內容)會忽略導航欄和標簽的存在,布局時若設置其原點設置為(0,0),視圖會延伸顯示到導航欄的下面被覆蓋;其值為UIRectEdgeNone意味著子控件本身會自動躲避導航欄和標簽欄,以免被遮擋。

automaticallyAdjustsScrollViewInsets

官方文檔說明

@property(nonatomic,assign) BOOL automaticallyAdjustsScrollViewInsets API_DEPRECATED("Use UIScrollView's contentInsetAdjustmentBehavior instead", ios(7.0,11.0),tvos(7.0,11.0)); // Defaults to YES

UIViewController 的一個屬性:(iOS7.0引入,11.0廢除,之后其作用被 UIScrollView 的新屬性 contentInsetAdjustmentBehavior 所取代,如設置為 UIScrollViewContentInsetAdjustmentAutomatic 等);
作用:默認情況下,它可以保證滾動視圖的內容自動偏移,不會被 UINavigationBarUITabBar 遮擋。

automaticallyAdjustsScrollViewInsets 的設置只對滾動視圖有效,對普通的 view 無效;對普通 view 而言,UINavigationBarUITabBar 半透明:會被遮擋;不透明,不會被遮擋。如果兩個都是默認情況下,則滾動視圖的內容不會被遮擋,普通的 view 會被遮擋,這是最常見的情況。

以上是自己開發(fā)項目時遇到的問題,做個筆記,方便后續(xù)查看,希望也能幫助需要的小伙伴。如有問題,請指出,謝謝

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容