冬至已到,聖誕將近,最近公司項目實在太多,三四個項目反復的切換真的讓人焦頭爛額,趁今天有點空,把維護的三個項目順利送出,剛好可以縷縷思路,記錄一下最近遇到的問題。說不着急那是假的,客戶一天天的催的確實令人心煩意亂,但是回過頭來想想也確實不易,所以還是說服自己認真對待他們反饋的一個個問題,盡量做到讓他們滿意也讓自己滿意。有句話怎么說來,終於完成了,還好我沒放棄。哈哈,閑言不多講,說一下最近遇到解決的一個問題吧,由熱點引起狀態欄位置變化而導致自定義底部欄位置錯位的問題。
關於熱點的帖子網上確實不少,也給了很多的解決的方案。iPhone作為個人熱點且有連接時,系統狀態欄下面會多一行熱點連接提示欄"Personal Hotspot: * Connection",縱向會下壓20pt;當所有連接都斷開時,熱點欄消失,縱向高度恢復正常。
1.系統狀態欄
APP_STATUSBAR_HEIGHT=[UIApplication sharedApplication].statusBarFrame.size.height,包含熱點欄(如有)高度,標准高度為20pt,當有個人熱點連接時,高度為40pt。
// iOS系統版本
// 標准系統狀態欄高度
#define SYS_STATUSBAR_HEIGHT 20
// 熱點欄高度
#define HOTSPOT_STATUSBAR_HEIGHT 20
// 導航欄(UINavigationController.UINavigationBar)高度
#define NAVIGATIONBAR_HEIGHT 44
// 工具欄(UINavigationController.UIToolbar)高度
#define TOOLBAR_HEIGHT 44
// 標簽欄(UITabBarController.UITabBar)高度
#define TABBAR_HEIGHT 44
// APP_STATUSBAR_HEIGHT=SYS_STATUSBAR_HEIGHT+[HOTSPOT_STATUSBAR_HEIGHT]
#define APP_STATUSBAR_HEIGHT (CGRectGetHeight([UIApplication sharedApplication].statusBarFrame))
// 根據APP_STATUSBAR_HEIGHT判斷是否存在熱點欄
#define IS_HOTSPOT_CONNECTED (APP_STATUSBAR_HEIGHT==(SYS_STATUSBAR_HEIGHT+HOTSPOT_STATUSBAR_HEIGHT)?YES:NO)
// 無熱點欄時,標准系統狀態欄高度+導航欄高度
#define NORMAL_STATUS_AND_NAV_BAR_HEIGHT (SYS_STATUSBAR_HEIGHT+NAVIGATIONBAR_HEIGHT)
// 實時系統狀態欄高度+導航欄高度,如有熱點欄,其高度包含在APP_STATUSBAR_HEIGHT中。
#define STATUS_AND_NAV_BAR_HEIGHT (APP_STATUSBAR_HEIGHT+NAVIGATIONBAR_HEIGHT)
2.UIViewController.view.bounds.height
- SYSTEM_VERSION < 7.0,UIViewController.view.bounds.height包含導航欄高度,不包含系統狀態欄高度,也不包含熱點欄(如果有)。
- SYSTEM_VERSION ≥ 7.0,UIViewController.view.bounds.height包含標准系統狀態欄高度和導航欄高度,但不包含熱點欄(如果有)。
也即當有熱點欄時,UIViewController.view.bounds.height都自動扣除了熱點欄的高度,iOS<7.0不包含標准系統狀態欄,iOS≥7.0包含標准系統狀態欄。
由於iOS7把整個屏幕高度(包括狀態欄,不包括熱點欄)都作為了視圖控制器的有效高度,因此從iOS6升級到iOS7時,會出現視圖整體上移了一個狀態欄的高度(20pt),並和上層的狀態欄交疊在一起。
上面的這兩段是借用的他們總結的一些說明性的東西,分析的還很詳細,原理還是要懂得,以后遇到問題一定要學會總結,不然的話太容易遺忘。網上給了一些解決的思路,我參考了比較好的兩篇博客,他們給的思路還是挺好的,但是還需要加一些處理和判斷,下面我說一下解決問題的完整過程吧。正常來說熱點引起的狀態欄位置的調整有兩種情況,一個是當前頁面已經創建打開,另一個情況是頁面尚未創建,下面來專門區分一下。
1、狀態欄變化通知的處理和添加UIApplicationWillChangeStatusBarFrameNotification,
UIApplicationDidChangeStatusBarFrameNotification是狀態欄變化會走的兩個通知,可以在
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController.navigationBar setHidden:YES];
[[ NSNotificationCenter defaultCenter ] addObserver : self selector : @selector (statusBarFrameWillChange:) name : UIApplicationWillChangeStatusBarFrameNotification object : nil ];
[[ NSNotificationCenter defaultCenter ] addObserver : self selector : @selector (layoutControllerSubViews:) name : UIApplicationDidChangeStatusBarFrameNotification object : nil ];
CGRect statusBarRect = [[UIApplication sharedApplication] statusBarFrame];
if (statusBarRect.size.height == 40)
{
[mytable setFrame:CGRectMake(0, -20, 320, UI_View_Hieght+64-58)];
[bottomView setFrame:CGRectMake(0,UI_View_Hieght+64-58-20,320, 58)];
}
else
{
[mytable setFrame:CGRectMake(0, 0, 320, UI_View_Hieght+64-58)];
[bottomView setFrame:CGRectMake(0,UI_View_Hieght+64-58,320, 58)];
}
}
經過反復的測試發現,原來通知只會在頁面已經創建打開這種情況下走,所以需要注冊監聽狀態欄的通知,並作處理
#pragma mark-狀態欄錄音或通話狀態通知
-(void)layoutControllerSubViews:(NSNotification *)notification
{
//[UIApplication sharedApplication].statusBarFrame.size.height=20;
CGRect statusBarRect = [[UIApplication sharedApplication] statusBarFrame];
if (statusBarRect.size.height == 40)
{
[mytable setFrame:CGRectMake(0, -20, 320, UI_View_Hieght+64-58)];
[bottomView setFrame:CGRectMake(0,UI_View_Hieght+64-58-20,320, 58)];
}
else
{
[mytable setFrame:CGRectMake(0, 0, 320, UI_View_Hieght+64-58)];
[bottomView setFrame:CGRectMake(0,UI_View_Hieght+64-58,320, 58)];
}
}
- (void)statusBarFrameWillChange:(NSNotification*)notification
{
//[self hideTabbar:self.statusBarHidden animated:YES];
//[[UIApplication sharedApplication] setStatusBarHidden:YES];
CGRect statusBarRect = [[UIApplication sharedApplication] statusBarFrame];
if (statusBarRect.size.height == 40)
{
[mytable setFrame:CGRectMake(0, -20, 320, UI_View_Hieght+64-58)];
[bottomView setFrame:CGRectMake(0,UI_View_Hieght+64-58-20,320, 58)];
}
else
{
[mytable setFrame:CGRectMake(0, 0, 320, UI_View_Hieght+64-58)];
[bottomView setFrame:CGRectMake(0,UI_View_Hieght+64-58,320, 58)];
}
}
另一種情況就是頁面尚未打開前,熱點已經連接,這樣的話打開頁面是不會走通知的地方,需要在
- (void)viewWillAppear:(BOOL)animated 加上上面的處理,和通知里面的代碼是一樣的,兩個都是必須的,這樣的話經過反復測試確實效果還是不錯的,今天就說到這里吧先,思路終於清晰了也。