轉(zhuǎn)載自http://blog.csdn.net/card361401376/article/details/61420830
介紹
先上實際效果圖,有三個版本請注意區(qū)分API版本
API>=20 | API=19 | API<19 |
---|---|---|
API20
|
API19
|
<19
|
以上的效果我們稱之為對狀態(tài)欄的著色,而非沉浸式狀態(tài)欄阶淘,那是另外的東西沪么。 想要實現(xiàn)以上的效果并不難茉继,閱讀本文了解原理后寄狼,就會覺得想要以上的效果真的很簡單。 本文旨在總結(jié)我的理解告訴讀者一步步實現(xiàn)狀態(tài)欄著色的原理喻圃。
原理
第一步-設(shè)置透明狀態(tài)欄
對狀態(tài)欄的控制一切基礎(chǔ)都源于
static public void setTranslucentWindows(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//透明狀態(tài)欄
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
請注意該Flag標識的API版本為19,也就是只能在API>=19以上實現(xiàn)透明狀態(tài)欄粪滤,這就是上文效果圖用API區(qū)分的原因斧拍。
注:以下style樣式同上代碼,但是有兼容問題杖小,建議直接使用代碼設(shè)置
<item name="Android:windowTranslucentStatus">true</item>
第二步-padding出預留空間
設(shè)置透明狀態(tài)欄之后饮焦,內(nèi)容會頂?shù)狡聊豁敳繒蜖顟B(tài)欄中的內(nèi)容重疊。
就需要設(shè)置padding出和狀態(tài)欄相同的高度窍侧,防止重疊 有兩種解決方法:
- XML中設(shè)置:對某個View設(shè)置android:fitsSystemWindows="true"(API+14)系統(tǒng)布局時自動找到最外層的View設(shè)置paddingTop
- 代碼控制:確定狀態(tài)欄高度然后給需要View設(shè)置paddingTop的值
在XML中直接設(shè)置屬性比較簡單县踢,但是有局限性,只對最外層View有效伟件,如果是Fragment的View視圖中設(shè)置fitsSystemWindows然后被添加到屏幕上無效硼啤。 代碼控制,能夠解決Fragment的問題斧账,但是確定狀態(tài)欄高度有點麻煩谴返,一般來說狀態(tài)欄高度都是24dp煞肾,保險起見還是需要讀取系統(tǒng)的配置高度,還有設(shè)置padding有時也會失效嗓袱,就需要handler.post(new Runnable())來保證代碼的執(zhí)行
讀取系統(tǒng)配置的狀態(tài)欄高度代碼:
/**
* 19API以上 讀取到狀態(tài)欄高度才有意義
*
* @param context
* @return
*/
static public int getStatusBarHeight(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
return resourceId > 0 ? context.getResources().getDimensionPixelSize(resourceId) : 0;
} else {
return 0;
}
}
第三步-著色
這里先說明前兩步的結(jié)果;
- API<19:不執(zhí)行
- API=19:黑灰漸進透明的狀態(tài)欄
- API>=20:系統(tǒng)會自動生成一個半透明的狀態(tài)欄
所以就需要我們對第二步中產(chǎn)生的預留空間設(shè)置顏色籍救,同樣有兩種方法:
- 添加View:對整個視圖的父容器FrameLayout(ID=android.R.id.content)添加一個狀態(tài)欄高度帶有顏色的View,覆蓋到狀態(tài)欄渠抹。
- 自動渲染:對設(shè)置了paddingTop的控件蝙昙,設(shè)置背景色,當該控件被padding處理時梧却,顏色也同時渲染到了狀態(tài)欄中奇颠。
添加覆蓋狀態(tài)欄View的代碼:
/**
* 設(shè)置狀態(tài)欄顏色為App主色
* 配合{@link #setTranslucentWindows(Activity)}方法使用
* 主要方法為添加一個View并設(shè)置背景色添加到系統(tǒng)contentView中
*
* @param activity
*/
static public void addStatusBarBackground(Activity activity) {
int height;
height = getStatusBarHeight(activity);
if (height <= 0) {
return;
}
FrameLayout layout = (FrameLayout) activity.findViewById(android.R.id.content);
FrameLayout statusLayout = new FrameLayout(activity);
statusLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height));
TypedValue typedValue = new TypedValue();
TypedArray a = activity.obtainStyledAttributes(typedValue.data, new int[]{R.attr.colorPrimary});
int color = a.getColor(0, 0);
a.recycle();
statusLayout.setBackgroundColor(color);
layout.addView(statusLayout);
}
特殊的API21+
當API21+:能夠調(diào)用系統(tǒng)API直接對狀態(tài)欄著色
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP){
this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
this.getWindow().setStatusBarColor(ContextCompat.getColor(this,R.color.red_normal));
}
總結(jié)
實現(xiàn)狀態(tài)欄著色并不復雜,只需要三步放航,真正使用時其實就是幾行代碼或者幾個方法調(diào)用烈拒。但是在實際使用中需要考慮實際需求,兼容問題广鳍。搭配使用每一步的使用就能實現(xiàn)我們想要的效果荆几。
如上文的效果圖實現(xiàn)就是:
Activity狀態(tài)欄透明,導航搜索欄View背景色透明paddingTop狀態(tài)欄高度赊时,覆蓋在圖片之上伴郁,而圖片沒有任何控制。
備注:我自己在開發(fā)中也遇到了設(shè)置透明狀態(tài)欄引起的其他問題蛋叼,項目設(shè)置了透明狀態(tài)欄焊傅,導致了網(wǎng)頁中鍵盤彈起遮住輸入框,不能自動頂起狈涮,最后采用的解決方案是先判斷鍵盤高度是否高于輸入框的高度狐胎,如果高于就手動將View高度重新設(shè)置;如果有類似的問題歌馍,可以和我交流