我在 解決navigationBar跳轉(zhuǎn)出現(xiàn)的黑色塊 這篇文章里面介紹了設(shè)置 NavigationBar 透明的方法薄辅,但是我們設(shè)置的頁面的rootView不是UIScrollView,如果是UIScrollView應(yīng)該會(huì)碰到以下的問題走芋。
iPhone4s是IOS8系統(tǒng)齿梁,iPhoneX是IOS11系統(tǒng)
1. scrollView的內(nèi)容沒有從屏幕開始
2.當(dāng)滾動(dòng)到出現(xiàn)紅色的NavigationBar鸿秆,push下一個(gè)頁面龙优,再回來會(huì)發(fā)現(xiàn)標(biāo)題欄變白色了尽爆。
- 備注:這里變成白色是因?yàn)槲沂褂?a target="_blank" rel="nofollow">RTRootNavigationController,如果是使用 UINavigationController抬伺,會(huì)變成黑色孤个。
以上我在項(xiàng)目中遇到的問題,碰到這兩個(gè)問題沛简,我也束手無策齐鲤,然后就各種搜索,各種嘗試椒楣,最終勉強(qiáng)處理了给郊,但是還是沒弄懂為什么會(huì)這樣。后來再繼續(xù)深究捧灰,才算找到了規(guī)律淆九。
隱藏頁面布局的起點(diǎn)位置有下面幾個(gè)屬性
- edgesForExtendedLayout
- translucent
- extendedLayoutIncludesOpaqueBars
- automaticallyAdjustsScrollViewInsets
我們先說 edgesForExtendedLayout、translucent毛俏,下面是這兩個(gè)屬性的官方文檔
/*
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 NS_AVAILABLE_IOS(3_0) UI_APPEARANCE_SELECTOR; // Default is NO on iOS 6 and earlier. Always YES if barStyle is set to UIBarStyleBlackTranslucent
@property(nonatomic,assign) UIRectEdge edgesForExtendedLayout NS_AVAILABLE_IOS(7_0); // Defaults to UIRectEdgeAll
- edgesForExtendedLayout 默認(rèn)是UIRectEdgeAll炭庙,表示屏幕從(0, 0)左上角開始布局;如果設(shè)置UIRectEdgeNone煌寇,那么就會(huì)從NavigationBar下開始布局
- translucent 默認(rèn)是YES焕蹄,表示屏幕從(0, 0)左上角開始布局;如果設(shè)置NO阀溶,那么就會(huì)從NavigationBar下開始布局腻脏;
- 這兩個(gè)的排列組合,就有一下幾種情況:
- A. edgesForExtendedLayout = UIRectEdgeAll; translucent = YES;
- B. edgesForExtendedLayout = UIRectEdgeAll; translucent = NO;
- C. edgesForExtendedLayout = UIRectEdgeNone; translucent = YES;
- D. edgesForExtendedLayout = UIRectEdgeNone; translucent = NO;
- 上面四種情況分別對應(yīng)四個(gè)效果圖银锻;我們可以得出
*1. translucent = NO; 或者 edgesForExtendedLayout = UIRectEdgeNone;根視圖會(huì)從NavigationBar下開始布局
*2. 如果設(shè)置 translucent = NO; 那么 edgesForExtendedLayout 不起作用
需求 1.rootView是UIScrollView永品,且 NavigationBar是透明的。
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"UIScrollView+透明NavigationBar";
[self setNavigationBarColor:[UIColor clearColor]];
CGFloat width = [UIScreen mainScreen].bounds.size.width;
CGFloat height = [UIScreen mainScreen].bounds.size.height;
UIScrollView *rootView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
rootView.backgroundColor = [UIColor whiteColor];
rootView.contentSize = CGSizeMake(0, height+10);//界面可以滾動(dòng)
[self.view addSubview:rootView];
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height+10)];
containerView.backgroundColor = [UIColor yellowColor];
[rootView addSubview:containerView];
UIView *view = [[UIView alloc] init];
view.backgroundColor = [UIColor redColor];
view.frame = CGRectMake(0, 0, 100, 100);
[containerView addSubview:view];
}
設(shè)置了透明NavigationBar击纬,我們需要的是界面從屏幕左上角開始鼎姐,而不是NavigationBar下方開始。這是因?yàn)?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
/**
Discussion
The default value of this property is YES, which lets container view controllers know that they should adjust the scroll view insets of this view controller’s view to account for screen areas consumed by a status bar, search bar, navigation bar, toolbar, or tab bar. Set this property to NO if your view controller implementation manages its own scroll view inset adjustments.
**/
/**
會(huì)為self.view的滾動(dòng)視圖做適配更振,會(huì)為你考慮狀態(tài)欄炕桨,搜索欄,導(dǎo)航欄殃饿,工具欄或選項(xiàng)卡欄的高度谋作,自動(dòng)調(diào)整芋肠;默認(rèn)是true乎芳,即自動(dòng)調(diào)整;如果要自己控制,就設(shè)置false; ios7.0-ios11.0
**/
//我們上面的問題奈惑,在ios7.0-ios11.0吭净,做下面設(shè)置就可以解決了
self.automaticallyAdjustsScrollViewInsets = NO;
在ios11.0之后呢,就要設(shè)置 UIScrollView's contentInsetAdjustmentBehavior
/* Configure the behavior of adjustedContentInset.
Default is UIScrollViewContentInsetAdjustmentAutomatic.
*/
@property(nonatomic) UIScrollViewContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior API_AVAILABLE(ios(11.0),tvos(11.0));
//對于上面的效果圖出現(xiàn)的情況肴甸,完整的解決方案是
if (@available(iOS 11.0, *)) {
self.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
} else {
self.automaticallyAdjustsScrollViewInsets = NO;
}
最后還有一個(gè)屬性 extendedLayoutIncludesOpaqueBars 這個(gè)什么作用呢寂殉,大家回頭看看最開始說的兩個(gè)問題中的第二個(gè),NavigationBar的顏色是隨scrollView的滑動(dòng)而改變的原在,當(dāng)我們停留在“褐色NavigationBar”時(shí)友扰,進(jìn)入下一個(gè)頁面,再回來庶柿,會(huì)發(fā)現(xiàn)NavigationBar白色了村怪,而且頁面也從NavigationBar下開始,而不是全屏浮庐。
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
這是文檔中的描述甚负,如果設(shè)置自定義背景圖片,會(huì)從自定義背景圖片獲取alpha审残,如果它有任何像素的alpha <1.0 就設(shè)為YES梭域,否則就取反。
備注:如果你手動(dòng)設(shè)置了translucent搅轿,那這個(gè)自動(dòng)取值就不會(huì)生效
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageWithColor:color] forBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setShadowImage:[UIImage new]];
//這是我們設(shè)置NavigationBar的顏色方法病涨,可以在后面打印translucent的值,做驗(yàn)證
- 當(dāng)我們設(shè)置“透明”時(shí),translucent=YES;當(dāng)我們設(shè)置“褐色”,translucent=NO;
我們上面也講過translucent=NO,就是“組合B”的效果圖璧坟,會(huì)出現(xiàn)NavigationBar- 為什么在當(dāng)前頁面滑動(dòng)沒有問題没宾,要進(jìn)入下一個(gè)頁面再回來才會(huì)出現(xiàn)呢?
這是因?yàn)檫@個(gè)設(shè)置需要在viewDidAppear設(shè)置好沸柔,我們默認(rèn)設(shè)置的是“透明”即translucent=YES循衰,所以顯示正常;當(dāng)滾動(dòng)界面設(shè)置“褐色”時(shí)褐澎,translucent=NO会钝,從下一個(gè)界面回來,會(huì)觸發(fā)viewWillAppear工三,系統(tǒng)會(huì)在根據(jù)translucent=NO調(diào)整界面迁酸。
所以我們設(shè)置上面相關(guān)的屬性,要在loadView俭正,viewDidLoad奸鬓,viewWillAppear等方法中設(shè)置。
那么要怎么解決上面的問題呢掸读?
這就是我們最后一個(gè)屬性 extendedLayoutIncludesOpaqueBars 的作用了串远。
/**
A Boolean value indicating whether or not the extended layout includes opaque bars.
**/
@property(nonatomic,assign) BOOL extendedLayoutIncludesOpaqueBars NS_AVAILABLE_IOS(7_0); // Defaults to NO, but bars are translucent by default on 7_0.
//不透明bar時(shí)宏多,還要不要從屏幕頂部開始。默認(rèn)值NO
所以上面的問題澡罚,我們只需要設(shè)置這個(gè)值為YES伸但,就可以解決了
self.extendedLayoutIncludesOpaqueBars = YES;
- 總結(jié):這四個(gè)屬性覆蓋了NavigationBar的很多情況了,了解了這四個(gè)屬性的用法及作用留搔,基本上可以NavigationBar就不會(huì)再困擾你了更胖。
這里還有一篇文章可以參考,iOS 導(dǎo)航欄的那些事兒隔显,可能這篇文章寫得更好却妨。