android狀態(tài)欄總結(jié)

  1. 針對(duì)狀態(tài)欄的操作,只針對(duì)4.4kitKat(含)以上的機(jī)型,部分國(guó)產(chǎn)rom會(huì)失效马僻,目前發(fā)現(xiàn)的有華為的EMUI
  1. Activity必須是noActionbar主題
  2. 本文基于StatusBarUtils略作修改莫其,感謝作者laobie
  3. 本文源碼地址
相關(guān)屬性重溫
  • FitsSystemWindows
    在使用FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDSFLAG_TRANSLUCENT_STATUS擠占了狀態(tài)欄的高度的時(shí)候粗截,我們的布局文件也跟著頂?shù)搅藸顟B(tài)欄上惋耙。通過FitsSystemWindows,系統(tǒng)會(huì)把a(bǔ)pp布局文件的paddingTop修改成狀態(tài)欄的高度熊昌,達(dá)到適配的效果
    false頂?shù)綘顟B(tài)欄
true,paddingTop有一個(gè)狀態(tài)欄高度
  • android.R.id.content
    通過它我們可以在不需要知道ID的情況下绽榛,訪問當(dāng)前Activity根節(jié)點(diǎn),一般是ContentFrameLayout類型婿屹,通過((ViewGroup)findViewById(R.id.content)).getChildAt(0);可以獲取到我們布局xml的根節(jié)點(diǎn)

  • getDecorView()
    通過他灭美,我們可以獲取到整個(gè)Window界面的最頂層View。我們用的很多的findViewById()昂利,就是基于這個(gè)DecorView查找里面的子節(jié)點(diǎn)的冲粤。比如Activity主題是Theme.AppCompat.Light.NoActionBar的組織層級(jí)如下美莫,

noActionbarView層次.png

為什么嵌套那么深,因?yàn)楦鱾€(gè)層次可能都會(huì)有幾個(gè)ViewStub方便注入梯捕,只是我們現(xiàn)在的主題用不到就是空了厢呵。

下面開始實(shí)戰(zhàn)了,一般我們用的比較多的是透明狀態(tài)欄傀顾、設(shè)置狀態(tài)欄顏色襟铭、DrawerLayout蓋在狀態(tài)欄上三種。

1. 透明狀態(tài)欄

這種情況一般用于把圖片延伸到狀態(tài)欄上短曾,圖片還分兩種

  1. 作為background的全屏大圖
  2. 作為ImageView控件存在寒砖,一般只占屏幕高度的一部分

這兩種情況下的處理方式還不一樣,具體看下文

/** * 使?fàn)顟B(tài)欄透明 */
private static void transparentStatusBar(Activity activity) {    
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {       
          activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);        
          activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
    } 
     else {       
          activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);   
  }
}

上面的代碼針對(duì)5.0以上或者4.4以上5.0以下的機(jī)型嫉拐,讓其狀態(tài)欄透明哩都、導(dǎo)航欄半透明,效果如下:


透明狀態(tài)欄的結(jié)果是布局文件頂?shù)搅藸顟B(tài)欄上

dump了下節(jié)點(diǎn)信息婉徘,我們發(fā)現(xiàn)布局的paddingTop從(50px狀態(tài)欄高度)被修改成了0px漠嵌。從而讓圖片延伸到了狀態(tài)欄

不透明狀態(tài)欄.png

透明狀態(tài)欄.png

這種情況下,對(duì)app布局文件通過設(shè)置FitsSystemWindows就可以完成適配了

/**
 * 獲取activity的根節(jié)點(diǎn)
 *@param activity
 *@return
 */
public static ViewGroup getAppRootView(Activity activity) { 
   return (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
}

/**  
*將目標(biāo)View的paddingTop從0設(shè)置為狀態(tài)欄的高度
 */
private static void setRootViewFitSystemWindow(Activity activity) { 
   ViewGroup rootView = getAppRootView(activity);   
   rootView.setFitsSystemWindows(true);   
   rootView.setClipToPadding(true);
}

app內(nèi)容布局有了padding.png

注意8呛簟儒鹿!要延伸到狀態(tài)欄的圖片,如果不是根節(jié)點(diǎn)的背景圖几晤,而是一個(gè)ImageView控件约炎,那么就不能設(shè)置setFitsSystemWindows了,原因參考上圖紅框蟹瘾。這種情況下圾浅,為了防止頂?shù)綘顟B(tài)欄,需要手動(dòng)在xml里通過paddingTop憾朴、marginTop調(diào)整標(biāo)題欄元素位置達(dá)到適配贱傀。類似下圖

延伸到狀態(tài)欄的圖片是一個(gè)ImageView

2. 狀態(tài)欄顏色

設(shè)置狀態(tài)欄顏色的步驟和透明類似,差別在于5.0以下機(jī)型無(wú)法直接設(shè)置狀態(tài)欄顏色伊脓,我們可以模擬一個(gè)純色的View放到狀態(tài)欄下面間接達(dá)到著色效果府寒。放置的父層級(jí)我們選擇DecorView

如果發(fā)現(xiàn)狀態(tài)欄顏色設(shè)置無(wú)效,有可能是布局文件的root節(jié)點(diǎn)加了backgroundColor所致

/**
 * 
設(shè)置狀態(tài)欄顏色
 *
 * @param activity       需要設(shè)置的activity
 * @param color          狀態(tài)欄顏色值
 * @param statusBarAlpha 狀態(tài)欄透明度
 */
public static void setColor(Activity activity, int color, int statusBarAlpha) { 
   if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)     return; 

   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {  
      activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);       
      activity.getWindow().setStatusBarColor(UIUtils.calcColorWithAlpha(color, statusBarAlpha));   
 } else {        
     activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);     
     ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();        
     insertMockStatusBackgroundView(decorView, color, statusBarAlpha);  
  }    
     setRootViewFitSystemWindow(activity);
}

上面的代碼判斷DecorView下第0個(gè)View是不是我們自定義的StatusbarView類型报腔,如果是則設(shè)置顏色株搔,否則創(chuàng)建一個(gè)純色控件插入到DecorView內(nèi),同時(shí)布局內(nèi)容上間距騰出給純色控件纯蛾。

3. DrawerLayout蓋在狀態(tài)欄上

DrawerLayout主要有兩個(gè)子元素1:內(nèi)容View 2:側(cè)滑欄
側(cè)滑欄必然要在內(nèi)容View后面以覆蓋前者

側(cè)滑欄效果

所以我們要做的有2步

  1. 插入純色控件到內(nèi)容View(如果不是LinarLayout需要考慮內(nèi)容View元素重新排列)
  2. DrawerLayout設(shè)置fitSystemWindow=false纤房;以覆蓋到狀態(tài)欄上

代碼如下:

/** * 為DrawerLayout 布局設(shè)置狀態(tài)欄變色
 * 
* @param activity       需要設(shè)置的activity 
* @param drawerLayout   DrawerLayout
 * @param color          狀態(tài)欄顏色值
 * @param statusBarAlpha 狀態(tài)欄透明度 
*/public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, int color, int statusBarAlpha) { 
   if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {        return;    }  

   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {        
      activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);        
      activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);      
      activity.getWindow().setStatusBarColor(Color.TRANSPARENT);   
   } else {        
     activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 
   }    
     ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);    
     //如果內(nèi)容view不是LinearLayout,則需要重新排列內(nèi)容view子元素的內(nèi)容    
     insertMockStatusBackgroundView(contentLayout, color, statusBarAlpha);    
     drawerLayout.setFitsSystemWindows(false);
}

總結(jié):

上面三個(gè)方法翻诉,涵蓋了app在大部分沉浸場(chǎng)景下的狀態(tài)炮姨。在了解了底層實(shí)現(xiàn)后捌刮,我們也可以輕松在安卓上實(shí)現(xiàn)IOS的沉浸效果了,最低版本4.4 kitkat現(xiàn)在已經(jīng)非常普及舒岸,隨著MIUI绅作、FlyME相繼都升級(jí)到5.0、6.0以上蛾派,魅藍(lán)俄认、紅米等大批國(guó)產(chǎn)中低端機(jī)型的都可以體驗(yàn)到這種酷炫的效果了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末洪乍,一起剝皮案震驚了整個(gè)濱河市眯杏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌壳澳,老刑警劉巖岂贩,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異巷波,居然都是意外死亡萎津,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門褥紫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人瞪慧,你說(shuō)我怎么就攤上這事髓考。” “怎么了弃酌?”我有些...
    開封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵氨菇,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我妓湘,道長(zhǎng)查蓉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任榜贴,我火速辦了婚禮豌研,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘唬党。我一直安慰自己鹃共,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開白布驶拱。 她就那樣靜靜地躺著霜浴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蓝纲。 梳的紋絲不亂的頭發(fā)上阴孟,一...
    開封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天晌纫,我揣著相機(jī)與錄音,去河邊找鬼永丝。 笑死锹漱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的类溢。 我是一名探鬼主播凌蔬,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼闯冷!你這毒婦竟也來(lái)了砂心?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蛇耀,失蹤者是張志新(化名)和其女友劉穎辩诞,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體纺涤,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡译暂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了撩炊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片外永。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拧咳,靈堂內(nèi)的尸體忽然破棺而出伯顶,到底是詐尸還是另有隱情,我是刑警寧澤骆膝,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布祭衩,位于F島的核電站,受9級(jí)特大地震影響阅签,放射性物質(zhì)發(fā)生泄漏掐暮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一政钟、第九天 我趴在偏房一處隱蔽的房頂上張望路克。 院中可真熱鬧,春花似錦养交、人聲如沸衷戈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)殖妇。三九已至,卻和暖如春破花,著一層夾襖步出監(jiān)牢的瞬間谦趣,已是汗流浹背疲吸。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留前鹅,地道東北人摘悴。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像舰绘,于是被迫代替她去往敵國(guó)和親蹂喻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容