沉浸式狀態(tài)欄的實(shí)現(xiàn)原理很簡(jiǎn)單,就是將狀態(tài)欄隱藏掉坷随,然后在原來(lái)狀態(tài)欄的位置添加一個(gè)和狀態(tài)欄大小一模一樣的View洽损,這個(gè)View的顏色定義成和Toolbar一樣的顏色就行了
在styles.xml文件中設(shè)置主題樣式為NoActionBar
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
這樣系統(tǒng)自帶的ActionBar就沒(méi)有了本辐,需要自己在布局文件中添加Toolbar
透明化狀態(tài)欄
/**
* 沉浸式狀態(tài)欄工具類
*/
public class StatusBarUtils {
/**
* 透明化狀態(tài)欄
*/
public static void transparentStatusBar(Activity act, boolean fitWindow) {
Window window = act.getWindow();
//透明狀態(tài)欄
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//獲取根布局
ViewGroup root = (ViewGroup) act.findViewById(android.R.id.content);
View firstChild = root.getChildAt(0);
if (firstChild != null) {
//設(shè)置root的第一個(gè)子View赏酥,使其為系統(tǒng)View預(yù)留空間.
firstChild.setFitsSystemWindows(fitWindow);
}
}
}
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
這行代碼的作用就是使?fàn)顟B(tài)欄透明化
//獲取根布局
ViewGroup root = (ViewGroup) act.findViewById(android.R.id.content);
View firstChild = root.getChildAt(0);
if (firstChild != null) {
//設(shè)置root的第一個(gè)子View,使其為系統(tǒng)View預(yù)留空間.
firstChild.setFitsSystemWindows(fitWindow);
}
這一串代碼的作用是就是在布局文件的最外層控件上添加了一個(gè)android:fitsSystemWindows="true"
屬性管搪,當(dāng)然也可以在布局文件中添加虾攻,就像下面這樣
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/blue"
app:title="標(biāo)題"/>
</LinearLayout>
android:fitsSystemWindows="true"
的效果是為系統(tǒng)View預(yù)留空間,也就是將狀態(tài)欄的位置空出來(lái)更鲁,它的默認(rèn)值是false霎箍。下圖是對(duì)比這個(gè)屬性在狀態(tài)欄透明
時(shí)設(shè)置為true和false的區(qū)別
創(chuàng)建狀態(tài)欄
public static View createStatusBar(Context context, int color) {
//方法原理:
//添加一個(gè)和狀態(tài)欄高、寬相同的指定顏色的View來(lái)覆蓋被透明化的狀態(tài)欄
View statusBar = new View(context);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(context));
statusBar.setLayoutParams(params);
statusBar.setBackgroundColor(color);
return statusBar;
}
這部分沒(méi)什么好講的澡为,就是單純的創(chuàng)建一個(gè)狀態(tài)欄漂坏,狀態(tài)欄的顏色通過(guò)參數(shù)設(shè)置
public static int getStatusBarHeight(Context context) {
int statusBarHeight = -1;
try {
Class clazz = Class.forName("com.android.internal.R$dimen");
//通過(guò)反射獲取狀態(tài)欄高度這個(gè)成員變量
Field status_bar_height = clazz.getField("status_bar_height");
Object obj = clazz.newInstance();
int height = Integer.parseInt(status_bar_height.get(obj).toString());
statusBarHeight = context.getResources().getDimensionPixelSize(height);
} catch (Exception e) {
e.printStackTrace();
}
return statusBarHeight;
}
這個(gè)方法用于獲取狀態(tài)欄的高度,不用在意方法的實(shí)現(xiàn)細(xì)節(jié)媒至,只需要知道這個(gè)方法能夠獲取到狀態(tài)欄的高度就行了
將創(chuàng)建的狀態(tài)欄添加到布局上
public static void addStatusBar(Activity act, int color) {
int resource = act.getResources().getColor(color);
//創(chuàng)建狀態(tài)欄
View statusBar = createStatusBar(act, resource);
//獲取根布局
ViewGroup root = (ViewGroup) act.findViewById(android.R.id.content);
//將狀態(tài)欄添加到根布局的第一個(gè)子布局位置
root.addView(statusBar, 0);
}
這個(gè)方法的第二個(gè)參數(shù)是傳入顏色的id顶别,例如R.color.colorPrimary
這樣的參數(shù)。
這個(gè)方法的作用是將狀態(tài)欄添加到布局上去拒啰,什么意思驯绎?畫個(gè)圖解釋
root.addView(statusBar, 0);
這行代碼就是將狀態(tài)欄添加到根布局下面,參數(shù)0
代表位置需要注意的是根布局不是指布局文件中最外層的控件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/blue"
app:title="標(biāo)題"/>
</LinearLayout>
我的布局文件是這樣的谋旦,根布局并不是指LinearLayout
最后一步
/**
* 繪制狀態(tài)欄
* @param act
* @param color
*/
public static void drawableStatusBar(Activity act, int color) {
transparentStatusBar(act, true);
addStatusBar(act, color);
}
添加上這個(gè)方法工具類就完成了剩失,下面是完整的代碼
/**
* 沉浸式狀態(tài)欄工具類
*/
public class StatusBarUtils {
/**
* 繪制狀態(tài)欄
* @param act
* @param color
*/
public static void drawableStatusBar(Activity act, int color) {
transparentStatusBar(act, true);
addStatusBar(act, color);
}
/**
* 透明化狀態(tài)欄
*
* @param act
*/
public static void transparentStatusBar(Activity act, boolean fitWindow) {
Window window = act.getWindow();
//透明狀態(tài)欄
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//透明導(dǎo)航欄
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
//獲取根布局
ViewGroup root = (ViewGroup) act.findViewById(android.R.id.content);
View firstChild = root.getChildAt(0);
if (firstChild != null) {
//設(shè)置 root 的第一個(gè)子 View . 使其為系統(tǒng) View 預(yù)留空間.
firstChild.setFitsSystemWindows(fitWindow);
}
}
/**
* 添加狀態(tài)欄
*
* @param act
* @param color
*/
public static void addStatusBar(Activity act, int color) {
int resource = act.getResources().getColor(color);
//創(chuàng)建狀態(tài)欄
View statusBar = createStatusBar(act, resource);
//獲取根布局
ViewGroup root = (ViewGroup) act.findViewById(android.R.id.content);
//將狀態(tài)欄添加到根布局下的第一個(gè)子布局位置
root.addView(statusBar, 0);
}
/**
* 創(chuàng)建一個(gè)狀態(tài)欄
*
* @param context
* @param color
* @return
*/
public static View createStatusBar(Context context, int color) {
//方法原理:
//添加一個(gè)和狀態(tài)欄高屈尼、寬相同的指定顏色的View來(lái)覆蓋被透明化的狀態(tài)欄
View statusBar = new View(context);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(context));
statusBar.setLayoutParams(params);
statusBar.setBackgroundColor(color);
return statusBar;
}
/**
* 獲取狀態(tài)欄高度
*
* @param context
* @return
*/
public static int getStatusBarHeight(Context context) {
int statusBarHeight = -1;
try {
Class clazz = Class.forName("com.android.internal.R$dimen");
//通過(guò)反射獲取狀態(tài)欄高度這個(gè)成員變量
Field status_bar_height = clazz.getField("status_bar_height");
Object obj = clazz.newInstance();
int height = Integer.parseInt(status_bar_height.get(obj).toString());
statusBarHeight = context.getResources().getDimensionPixelSize(height);
} catch (Exception e) {
e.printStackTrace();
}
return statusBarHeight;
}
}
在onCreate()
方法中調(diào)用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StatusBarUtils.drawableStatusBar(this, R.color.colorPrimary);
}
效果如下