標籤:dimen text var 系統配置 背景 pretty views recycle orm
介紹
先上實際,有三個版本號碼請注意區分API版本號碼
| API>=20 |
API=19 |
API<19 |
|
|
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQ2FyZDM2MTQwMTM3Ng==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="<19" title=""> |
以上的效果我們稱之為對狀態列的著色,而非沈浸式狀態列。那是另外的東西。
想要實現以上的效果並不難,閱讀本文瞭解原理後,就會認為想要以上的效果真的非常easy。
本文旨在總結我的理解告訴讀者一步步實現狀態列著色的原理。
原理第一步-設定透明狀態列
對狀態列的控制一切基礎都源於
static public void setTranslucentWindows(Activity activity) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { //透明狀態列 activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); } }
請注意該Flag標識的API版本號碼為19,也就是僅僅能在API>=19以上實現透明狀態列,這就是上文用API區分的原因。
註:下面style樣式同上代碼,可是有相容問題。建議直接使用代碼設定
<item name="android:windowTranslucentStatus">true</item>
第二步-padding出預留空間
設定透明狀態列之後,內容會頂到螢幕頂部會和狀態列中的內容重疊。
就須要設定padding出和狀態列相同的高度。防止重疊
有兩種解決方案:
XML中設定:對某個View設定android:fitsSystemWindows="true"(API+14)系統布局時自己主動找到最外層的View設定paddingTop
代碼控制:確定狀態列高度然後給須要View設定paddingTop的值
在XML中直接設定屬性比較簡單。可是有局限性,僅僅對最外層View有效。假設是Fragment的View視圖中設定fitsSystemWindows然後被加入到螢幕上無效。
代碼控制,可以解決Fragment的問題。可是確定狀態列高度有點麻煩,一般來說狀態列高度都是24dp,保險起見還是須要讀取系統的配置高度,還有設定padding有時也會失效,就須要handler.post(new Runnable())來保證代碼的運行
讀取系統配置的狀態列高度代碼:
/** * 19API以上 讀取到狀態列高度才有意義 * * @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; } }
第三步-著色
這裡先說明前兩步的結果;
- API<19:不運行
- API=19:黑灰漸進透明的狀態列
- API>=20:系統會自己主動產生一個半透明的狀態列
所以就須要我們對第二步中產生的預留空間設定顏色,相同有兩種方法:
- 加入View:對整個視圖的父容器FrameLayout(ID=android.R.id.content)加入一個狀態列高度帶有顏色的View。覆蓋到狀態列。
- 自己主動渲染:對設定了paddingTop的控制項。設定背景色。當該控制項被padding處理時,顏色也同一時候渲染到了狀態列中。
加入覆蓋狀態列View的代碼:
/** * 設定狀態列顏色為App主色 * 配合{@link #setTranslucentWindows(Activity)}方法使用 * 主要方法為加入一個View並設定背景色加入到系統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+:可以調用系統API直接對狀態列著色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));}
總結
實現狀態列著色並不複雜,僅僅須要三步。真正使用時事實上就是幾行代碼或者幾個方法調用。可是在實際使用中須要考慮實際需求,相容問題。搭配使用每一步的使用就能實現我們想要的效果。
如上文的實現就是:Activity狀態列透明,導航搜尋欄View背景色透明paddingTop狀態列高度,覆蓋在圖片之上,而圖片沒有不論什麼控制。
Android開發-狀態列著色原理和API版本號碼相容處理