標籤:
冬至已到,聖誕將近,最近公司項目實在太多,三四個項目反覆的切換真的讓人焦頭爛額,趁今天有點空,把維護的三個項目順利送出,剛好可以縷縷思路,記錄一下最近遇到的問題。說不著急那是假的,客戶一天天的催的確實令人心煩意亂,但是回過頭來想想也確實不易,所以還是說服自己認真對待他們反饋的一個個問題,盡量做到讓他們滿意也讓自己滿意。有句話怎麼說來,終於完成了,還好我沒放棄。哈哈,閑言不多講,說一下最近遇到解決的一個問題吧,由熱點引起狀態列位置變化而導致自訂底部欄位置錯位的問題。
關於熱點的文章網上確實不少,也給了很多的解決的方案。iPhone作為個人熱點且有串連時,系統狀態列下面會多一行熱點串連提示欄"Personal Hotspot: * Connection",縱向會下壓20pt;當所有串連都斷開時,熱點欄消失,縱向高度恢複正常。
1.系統狀態列
APP_STATUSBAR_HEIGHT=[UIApplication sharedApplication].statusBarFrame.size.height,包含熱點欄(如有)高度,標準高度為20pt,當有個人熱點串連時,高度為40pt。
// iOS系統版本
#define
SYSTEM_VERSION [[[UIDevice currentDevice] systemVersion] doubleValue]
// 標準系統狀態列高度
#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 加上上面的處理,和通知裡面的代碼是一樣的,兩個都是必須的,這樣的話經過反覆測試確實效果還是不錯的,今天就說到這裡吧先,思路終於清晰了也。
iPhone/iOS開啟個人熱點的相關位置調整小結