最近遇到了這樣一個(gè)bug箕宙,發(fā)現(xiàn)當(dāng)狀態(tài)欄改變(比如出現(xiàn)開啟熱點(diǎn)享怀,另一個(gè)程序后臺(tái)獲取位置等)后调榄,有些view會(huì)下移愿伴,而有些view不會(huì)下移肺魁,如果是底部的view下移后就會(huì)造成bug。于是我就探索了一下并做出總結(jié)隔节。
狀態(tài)欄的改變會(huì)造成哪些改變鹅经?
當(dāng)狀態(tài)欄出現(xiàn)后,當(dāng)前視圖的根view的frame會(huì)發(fā)生改變怎诫,它的y值會(huì)增加20瞬雹,高度會(huì)減少20。而[UIScreen mainScreen].bounds
和[UIApplication sharedApplication].keyWindow.bounds
這兩個(gè)方法得到的frame是不會(huì)改變的(始終等于屏幕大泄艉纭)。所以一不注意就很容易寫出狀態(tài)欄改變后會(huì)引起視圖下移的bug呢诬。
狀態(tài)欄出現(xiàn)的幾種情況
- view創(chuàng)建的時(shí)候已經(jīng)有狀態(tài)欄
- view創(chuàng)建的時(shí)候沒有狀態(tài)欄涌哲,view顯示完全后才出現(xiàn)狀態(tài)欄
解決思路
最簡(jiǎn)單的辦法就是使用autolayout進(jìn)行約束,并且靠底部的視圖一定要從底部進(jìn)行約束尚镰,這樣無論是第一種情況還是第二種情況都不會(huì)產(chǎn)生bug阀圾。或者使用autoresizing狗唉,即設(shè)置view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
如果在不使用autolayout和autoresizingMask的情況下
- view創(chuàng)建的時(shí)候已經(jīng)有狀態(tài)欄
這種情況就很簡(jiǎn)單初烘,當(dāng)我們寫frame獲取當(dāng)前視圖大小的時(shí)候不要使用[UIScreen mainScreen].bounds
和[UIApplication sharedApplication].keyWindow.bounds
這兩個(gè)方法,改為[UIApplication sharedApplication].keyWindow.rootViewController.view.bounds
這樣來獲取,這樣獲取的結(jié)果就是當(dāng)前有無狀態(tài)欄的時(shí)候的視圖尺寸肾筐。
- view創(chuàng)建的時(shí)候沒有狀態(tài)欄哆料,view顯示完全后才出現(xiàn)狀態(tài)欄
這種情況就是view已經(jīng)創(chuàng)建后狀態(tài)欄會(huì)動(dòng)態(tài)改變這種情況,而我們寫代碼的時(shí)候?yàn)榱吮苊獬霈F(xiàn)bug也是必須要兼容這種情況的吗铐。這種情況除了前面說的用autolayout來創(chuàng)建視圖东亦,另一種方法就只能監(jiān)聽狀態(tài)欄改變的通知了,并且在收到通知后去動(dòng)態(tài)的調(diào)整唬渗。
一些建議
- 如果是要獲取當(dāng)前視圖的大械湔蟆(而不是屏幕尺寸),建議使用
[UIApplication sharedApplication].keyWindow.rootViewController.view.bounds
- 靠底部的簡(jiǎn)單視圖盡量使用autolayout或者autoresizing镊逝,并且從底部進(jìn)行約束(這樣完全可以避免bug)
- 如果是用frame創(chuàng)建的視圖壮啊,并且視圖靠近底部,一定要考慮狀態(tài)欄改變后視圖下移可能造成遮擋的情況撑蒜,所以這時(shí)候就只能去監(jiān)聽通知并進(jìn)行一下動(dòng)態(tài)的改變或者使用autoresizing歹啼。