沉浸式狀態(tài)欄實(shí)現(xiàn)及遇到的坑

Android4.4以前的版本,狀態(tài)欄都是一塊黑色的,個(gè)人認(rèn)為還是比較丑的。自4.4開始,Android已經(jīng)支持透明狀態(tài)欄了(俗稱沉浸式狀態(tài)欄)。個(gè)人認(rèn)為支持沉浸式狀態(tài)欄的app逼格還是比較高的,為了緊跟潮流,我們項(xiàng)目中也準(zhǔn)備加入沉浸式狀態(tài)欄。在實(shí)現(xiàn)沉浸式狀態(tài)欄的過程中踩了不少的坑,特此記錄下來。

如何實(shí)現(xiàn)狀態(tài)欄

Android 4.4以上實(shí)現(xiàn)方式

Android 4.4版本提供了FLAG_TRANSLUCENT_STATUS,在Activity中加入此flag,可以設(shè)置狀態(tài)欄透明。代碼如下:

僅僅設(shè)置FLAG_TRANSLUCENT_STATUS,你會(huì)發(fā)現(xiàn)界面上的ToolBar會(huì)跑到狀態(tài)欄上面去,如下圖:?

通常我們會(huì)使用fitsSystemWindows屬性來解決此問題。

fitSystemWindows官方描述:

Boolean internal attribute to adjust view layout based on system windows such as the status bar. If true, adjusts the padding of this view to leave space for the system windows. Will only take effect if this view is in a non-embedded activity.?

簡(jiǎn)單描述:

這個(gè)屬性的作用是讓view可以根據(jù)系統(tǒng)窗口(如status bar)來調(diào)整自己的布局,如果值為true,就會(huì)調(diào)整view的paingding屬性來給system windows留出空間(即給view添加一個(gè)值為狀態(tài)欄高度的top padding)。

我們?cè)囍oToolBar設(shè)置一下fitsSystemWindows屬性為true。布局代碼如下:

4.4的效果圖如下:

注:有些4.4的系統(tǒng)上面狀態(tài)欄并不是全透明的,而是漸變的。

Android 5.0以上實(shí)現(xiàn)方式

你會(huì)發(fā)現(xiàn),已經(jīng)實(shí)現(xiàn)了沉浸式狀態(tài)欄效果了。如果運(yùn)行在5.0以上的機(jī)器上面,會(huì)發(fā)現(xiàn)大部分手機(jī)會(huì)出現(xiàn)狀態(tài)欄是半透明的,效果圖如下:

我們能不能讓將5.0以上的手機(jī)也設(shè)置為和4.4一樣的全透明的狀態(tài)欄呢?答案是肯定的!Android自5.0起,又為我們提供了設(shè)置狀態(tài)欄顏色的API,我們可以自己設(shè)置狀態(tài)欄的顏色。

在代碼中再加入如下代碼:

再在運(yùn)行看看效果,狀態(tài)欄已經(jīng)變成全透明了。6.0運(yùn)行效果圖和上面4.4一樣,就不再附圖了。

Android 6.0以上設(shè)置狀態(tài)欄字體顏色

默認(rèn)狀態(tài)欄字體顏色是白色的,如果ToolBar的顏色較淺,那么狀態(tài)欄上白色的字看不怎么清楚。

Android6.0以后,我們可以使用代碼將狀態(tài)欄字體的顏色設(shè)置為黑色了,代碼如下:

設(shè)置了深色狀態(tài)欄字體的效果圖如下:

踩過的坑

如果你認(rèn)為已經(jīng)已經(jīng)完美實(shí)現(xiàn)了,那真是too young to simple。下面是一些我踩過的坑。

與軟鍵盤沖突的坑

如果在界面中有EditText的話,你會(huì)發(fā)現(xiàn)當(dāng)軟件盤彈出的時(shí)候(Activity已經(jīng)設(shè)置了adjustResize),ToolBar的內(nèi)容都被頂上去了,但是EditText輸入框卻被有頂上來(正常情況應(yīng)該是ToolBar沒事,輸入框被軟鍵盤頂上去),如下圖:

這是為什么呢?經(jīng)研究發(fā)現(xiàn)原來是fitsSystemWindows屬性搞的鬼。哪個(gè)View設(shè)置了fitsSystemWindows=true,這個(gè)View就會(huì)被軟件盤頂上去。所以說,fitsSystemWindows不能亂用,會(huì)有意想不到的坑。

那能不能不用fitsSystemWindows呢?既然上面說了,fitsSystemWindows=true的作用是給View添加值為狀態(tài)欄高度的padding,那我們何不自己手動(dòng)給ToolBar添加padding呢?

我們?nèi)サ鬞oolBar上的fitsSystemWindows屬性,并設(shè)置一下ToolBar的padding,代碼如下:

去掉ToolBar的fitsSystemWindows屬性,并加上加上上面的代碼,軟鍵盤彈出時(shí)ToolBar正常了,但是輸入框還是沒有彈出來。

解決方式1?

剛才上面給ToolBar設(shè)置了fitsSystemWindows=true,結(jié)果ToolBar的內(nèi)容被頂上去了,那我們能不能給輸入框設(shè)置一個(gè)fitsSystemWindows=true屬性呢?試一下就知道了!

試了之后你會(huì)發(fā)現(xiàn),果然可以,但是輸入框的高度變了,其實(shí)是輸入框的padding增加了狀態(tài)欄的高度。如果設(shè)計(jì)和產(chǎn)品能接受這種效果,那這也不失為一種解決方法。很顯然,一般都不會(huì)接受這種效果的,就算設(shè)計(jì)和產(chǎn)品能接受,我們開發(fā)也不能接受!

那有沒有更好的方法呢?到網(wǎng)上搜索發(fā)現(xiàn)下面一種解決方案。

解決方式2?

添加上面的類,然后在Activity的onCreate方法中的setContentView后面加上如下代碼:

然后運(yùn)行,輸入框能夠正常被頂上去,而且輸入框的布局有沒有受到影響。

該解決方案的原理是,給界面的根布局設(shè)置一個(gè)監(jiān)聽器,當(dāng)界面大小有變化的時(shí)候,如鍵盤彈出的時(shí)候,重新設(shè)置一下根布局的高度,再調(diào)用requestLayout對(duì)界面進(jìn)行重繪。

注:不知道這種解決方案會(huì)不會(huì)引起其他的問題,目前暫時(shí)沒有發(fā)現(xiàn),如果哪位知道有什么問題,請(qǐng)指點(diǎn)一下,謝謝!

華為EMUI3.1上的坑

將上面的沉浸式代碼放在EMUI3.1系統(tǒng)的手機(jī)(如華為榮耀7)上面跑,你會(huì)發(fā)現(xiàn),根本沒有沉浸式效果,狀態(tài)欄是透明的,顯示的是桌面上的顏色,如下圖:

經(jīng)驗(yàn)證,原來是EMUI3.1系統(tǒng)的原因,很多App(如網(wǎng)易云音樂等)也是在EMUI3.0上有沉浸式的效果,到了EMUI3.1卻沒有效果了。在EMUI3.1沒有沉浸式效果如果和4.4以前一樣是黑的也就算了,這樣透明的顯示桌面顏色實(shí)在難看。

后來發(fā)現(xiàn)去掉下面這句代碼,可以讓其有沉浸式的效果。

效果如下:

不過它的狀態(tài)欄不是全透明的,而是像某些4.4的系統(tǒng)一樣是漸變的,不過總比原來的效果好。

這里我們加一個(gè)判斷,判斷如果不是EMUI3.1的系統(tǒng),才調(diào)用clearFlags清除掉FLAG_TRANSLUCENT_STATUS。

具體代碼如下:

ActionMode上的坑

ActionMode是一種Context Menu,它懸浮在ToolBar活著ActionBar上面?,F(xiàn)在已經(jīng)基本上很少app在用ActionMode了,所以可能很多人可能沒有用過,沒用過的可以看看這篇文章http://blog.csdn.net/xyz_lmn/article/details/12754785。

公司項(xiàng)目中使用到了ActionMode(歷史遺留代碼),在實(shí)現(xiàn)沉浸式的效果中,發(fā)現(xiàn)ActionMode并不支持沉浸式。ActionMode彈出來的時(shí)候,狀態(tài)欄會(huì)變成黑色的,效果如下:

ActionMode彈出前:

ActionMode彈出后:

遇到這個(gè)問題的時(shí)候,第一想法就是能不能和ToolBar一樣給ActionMode設(shè)置一個(gè)值為狀態(tài)欄高度的padding,然后將它頂?shù)綘顟B(tài)欄里面去。

在Stackoverflow上面搜了一種方法可以將ActionMode頂?shù)綘顟B(tài)欄上面去,給Activity加一個(gè)Flag即可,代碼如下:

看到能將ActionMode頂?shù)綘顟B(tài)欄中去時(shí)心里已經(jīng)在開始偷著樂了,接下來只要給ActionMode設(shè)置一個(gè)padding即可。然而發(fā)現(xiàn)ActionMode根本沒有提供在代碼中設(shè)置高度和padding的API,只能在style中設(shè)置高度和padding。這樣就有一個(gè)問題,因?yàn)锳ndroid手機(jī)碎片化嚴(yán)重,導(dǎo)致不同廠商的不同手機(jī)狀態(tài)欄的高度不一致,所以使用這個(gè)方法會(huì)出現(xiàn)有的手機(jī)ActionMode彈出時(shí)比ToolBar高或者低,不過也還能接受。

如果僅僅這樣也就算了,沒想到又引起了另外一個(gè)問題。在使用上面的flag之后(flag不能亂加啊,血和淚的教訓(xùn)),雖然ActionMode頂?shù)綘顟B(tài)欄了,但是在某些(如華為)帶虛擬按鍵的手機(jī)(虛擬按鍵對(duì)開發(fā)者來說也是一個(gè)大坑),虛擬按鍵會(huì)遮擋底部的布局。

只能放棄這種方案,尼瑪,怎么這么多坑,讓我哭會(huì)(淚崩)!

沒辦法,問題還是得去解決??!繼續(xù)尋找其它解決方案。。。

這時(shí)候想到了在Android5.0以上我們可以設(shè)置狀態(tài)欄的顏色,那可不可以在ActionMode彈出來的時(shí)候,給狀態(tài)欄設(shè)置一個(gè)與ToolBar顏色一致的顏色呢?嘗試一下吧,在BaseActivity中重寫startSupportActionMode方法,在里面給狀態(tài)欄設(shè)置顏色,具體代碼如下:

沒想到,居然可以。不過只能兼容5.0以上的手機(jī),4.4還是黑色。目前也只能這樣了,后期項(xiàng)目中估計(jì)會(huì)將ActionMode干掉吧,到時(shí)候就OK了。如果大家又更好兼容ActionMode的方法請(qǐng)指點(diǎn)一下,謝謝?。?!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容