Android4.4以前的版本,狀態欄都是一塊黑色的,個人認為還是比較丑的。自4.4開始,Android已經支持透明狀態欄了(俗稱沉浸式狀態欄)。個人認為支持沉浸式狀態欄的app逼格還是比較高的,為了緊跟潮流,我們項目中也準備加入沉浸式狀態欄。在實現沉浸式狀態欄的過程中踩了不少的坑,特此記錄下來。
Android 4.4版本提供了FLAG_TRANSLUCENT_STATUS,在Activity中加入此flag,可以設置狀態欄透明。代碼如下:
僅僅設置FLAG_TRANSLUCENT_STATUS,你會發現界面上的ToolBar會跑到狀態欄上面去,如下圖:?
通常我們會使用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.?
簡單描述:
這個屬性的作用是讓view可以根據系統窗口(如status bar)來調整自己的布局,如果值為true,就會調整view的paingding屬性來給system windows留出空間(即給view添加一個值為狀態欄高度的top padding)。
我們試著給ToolBar設置一下fitsSystemWindows屬性為true。布局代碼如下:
4.4的效果圖如下:
注:有些4.4的系統上面狀態欄并不是全透明的,而是漸變的。
你會發現,已經實現了沉浸式狀態欄效果了。如果運行在5.0以上的機器上面,會發現大部分手機會出現狀態欄是半透明的,效果圖如下:
我們能不能讓將5.0以上的手機也設置為和4.4一樣的全透明的狀態欄呢?答案是肯定的!Android自5.0起,又為我們提供了設置狀態欄顏色的API,我們可以自己設置狀態欄的顏色。
在代碼中再加入如下代碼:
再在運行看看效果,狀態欄已經變成全透明了。6.0運行效果圖和上面4.4一樣,就不再附圖了。
默認狀態欄字體顏色是白色的,如果ToolBar的顏色較淺,那么狀態欄上白色的字看不怎么清楚。
Android6.0以后,我們可以使用代碼將狀態欄字體的顏色設置為黑色了,代碼如下:
設置了深色狀態欄字體的效果圖如下:
如果你認為已經已經完美實現了,那真是too young to simple。下面是一些我踩過的坑。
如果在界面中有EditText的話,你會發現當軟件盤彈出的時候(Activity已經設置了adjustResize),ToolBar的內容都被頂上去了,但是EditText輸入框卻被有頂上來(正常情況應該是ToolBar沒事,輸入框被軟鍵盤頂上去),如下圖:
這是為什么呢?經研究發現原來是fitsSystemWindows屬性搞的鬼。哪個View設置了fitsSystemWindows=true,這個View就會被軟件盤頂上去。所以說,fitsSystemWindows不能亂用,會有意想不到的坑。
那能不能不用fitsSystemWindows呢?既然上面說了,fitsSystemWindows=true的作用是給View添加值為狀態欄高度的padding,那我們何不自己手動給ToolBar添加padding呢?
我們去掉ToolBar上的fitsSystemWindows屬性,并設置一下ToolBar的padding,代碼如下:
去掉ToolBar的fitsSystemWindows屬性,并加上加上上面的代碼,軟鍵盤彈出時ToolBar正常了,但是輸入框還是沒有彈出來。
解決方式1?
剛才上面給ToolBar設置了fitsSystemWindows=true,結果ToolBar的內容被頂上去了,那我們能不能給輸入框設置一個fitsSystemWindows=true屬性呢?試一下就知道了!
試了之后你會發現,果然可以,但是輸入框的高度變了,其實是輸入框的padding增加了狀態欄的高度。如果設計和產品能接受這種效果,那這也不失為一種解決方法。很顯然,一般都不會接受這種效果的,就算設計和產品能接受,我們開發也不能接受!
那有沒有更好的方法呢?到網上搜索發現下面一種解決方案。
解決方式2?
添加上面的類,然后在Activity的onCreate方法中的setContentView后面加上如下代碼:
然后運行,輸入框能夠正常被頂上去,而且輸入框的布局有沒有受到影響。
該解決方案的原理是,給界面的根布局設置一個監聽器,當界面大小有變化的時候,如鍵盤彈出的時候,重新設置一下根布局的高度,再調用requestLayout對界面進行重繪。
注:不知道這種解決方案會不會引起其他的問題,目前暫時沒有發現,如果哪位知道有什么問題,請指點一下,謝謝!
將上面的沉浸式代碼放在EMUI3.1系統的手機(如華為榮耀7)上面跑,你會發現,根本沒有沉浸式效果,狀態欄是透明的,顯示的是桌面上的顏色,如下圖:
經驗證,原來是EMUI3.1系統的原因,很多App(如網易云音樂等)也是在EMUI3.0上有沉浸式的效果,到了EMUI3.1卻沒有效果了。在EMUI3.1沒有沉浸式效果如果和4.4以前一樣是黑的也就算了,這樣透明的顯示桌面顏色實在難看。
后來發現去掉下面這句代碼,可以讓其有沉浸式的效果。
效果如下:
不過它的狀態欄不是全透明的,而是像某些4.4的系統一樣是漸變的,不過總比原來的效果好。
這里我們加一個判斷,判斷如果不是EMUI3.1的系統,才調用clearFlags清除掉FLAG_TRANSLUCENT_STATUS。
具體代碼如下:
ActionMode是一種Context Menu,它懸浮在ToolBar活著ActionBar上面。現在已經基本上很少app在用ActionMode了,所以可能很多人可能沒有用過,沒用過的可以看看這篇文章http://blog.csdn.net/xyz_lmn/article/details/12754785。
公司項目中使用到了ActionMode(歷史遺留代碼),在實現沉浸式的效果中,發現ActionMode并不支持沉浸式。ActionMode彈出來的時候,狀態欄會變成黑色的,效果如下:
ActionMode彈出前:
ActionMode彈出后:
遇到這個問題的時候,第一想法就是能不能和ToolBar一樣給ActionMode設置一個值為狀態欄高度的padding,然后將它頂到狀態欄里面去。
在Stackoverflow上面搜了一種方法可以將ActionMode頂到狀態欄上面去,給Activity加一個Flag即可,代碼如下:
看到能將ActionMode頂到狀態欄中去時心里已經在開始偷著樂了,接下來只要給ActionMode設置一個padding即可。然而發現ActionMode根本沒有提供在代碼中設置高度和padding的API,只能在style中設置高度和padding。這樣就有一個問題,因為Android手機碎片化嚴重,導致不同廠商的不同手機狀態欄的高度不一致,所以使用這個方法會出現有的手機ActionMode彈出時比ToolBar高或者低,不過也還能接受。
如果僅僅這樣也就算了,沒想到又引起了另外一個問題。在使用上面的flag之后(flag不能亂加啊,血和淚的教訓),雖然ActionMode頂到狀態欄了,但是在某些(如華為)帶虛擬按鍵的手機(虛擬按鍵對開發者來說也是一個大坑),虛擬按鍵會遮擋底部的布局。
只能放棄這種方案,尼瑪,怎么這么多坑,讓我哭會(淚崩)!
沒辦法,問題還是得去解決啊!繼續尋找其它解決方案。。。
這時候想到了在Android5.0以上我們可以設置狀態欄的顏色,那可不可以在ActionMode彈出來的時候,給狀態欄設置一個與ToolBar顏色一致的顏色呢?嘗試一下吧,在BaseActivity中重寫startSupportActionMode方法,在里面給狀態欄設置顏色,具體代碼如下:
沒想到,居然可以。不過只能兼容5.0以上的手機,4.4還是黑色。目前也只能這樣了,后期項目中估計會將ActionMode干掉吧,到時候就OK了。如果大家又更好兼容ActionMode的方法請指點一下,謝謝!!!