沉浸式的封裝(狀態列和底部導航同時實現)
阿新 • • 發佈:2019-02-10
我在使用沉浸式的時候遇到很多坑,最典型的就是相容性問題,有的效果5.0以上很容易實現,但在4.4使用同樣的方法就不可取了,有的機型底部有虛擬導航按鈕,有的卻沒有,所有我們不僅要區分手機的版本,也要區分底部是否有導航欄。只有在4.4及以上才有沉浸式這麼一說的,在本次封裝中,我們要同時實現頂部狀態列和底部導航欄的沉浸式,需要的童鞋可以當做工具類,直接copy到自己的BaseActivity中進行使用。
之前寫過實現沉浸式方法的文章,詳情見http://blog.csdn.net/sinat_35159441/article/details/76839484 ,首先我們來分析一下,不是所有的Activity都需要實現沉浸式,所以設定沉浸式的方法沒必要做成抽象的,需要使用的Activity重寫一下即可。該方法實現步驟如下:
- 如果當前版本為4.4,我們首先設定狀態列和導航欄透明,5.0不用
//判斷手機的版本,如果是4.4的版本,則設定狀態列和導航欄透明,5.0以上不用設定,已經實現
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT &&
Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG _TRANSLUCENT_STATUS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
在佈局里加入
* 判斷版本,4.4以下可以忽略,4.4使用反射機制動態設定Toolbar的高度,再設定其顏色,同樣使用反射設定導航欄的高度,再設定其顏色,5.0以上直接使用官方提供的API設定其顏色,高度使用預設的。
/**
* 設定頂部及底部的沉浸式,這個方法需要子類來調,必須在setContentView()之後呼叫
*/
public void setTranslucentBar(final Toolbar toolbar, final View navigationView, int barColor) {
//當手機的版本在4.4的時候,設定透明之後,再設定高度,然後再設定顯示的顏色
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT &&
Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
if (toolbar != null) {
toolbar.post(new Runnable() {
@Override
public void run() {
ViewGroup.LayoutParams layoutParams = toolbar.getLayoutParams();
layoutParams.height += getBarHeight("status_bar_height");
toolbar.setLayoutParams(layoutParams);
}
});
toolbar.setBackgroundColor(barColor);
}
if (navigationView != null) {
//這時還要判斷當前手機有沒有底部虛擬導航欄,如果沒有的話,我們不做處理
if (hasNavigationView(getWindowManager())) {
navigationView.post(new Runnable() {
@Override
public void run() {
ViewGroup.LayoutParams layoutParams = navigationView.getLayoutParams();
layoutParams.height += getBarHeight("navigation_bar_height");
navigationView.setLayoutParams(layoutParams);
}
});
navigationView.setBackgroundColor(barColor);
}
}
//5.0及以上
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setStatusBarColor(barColor);
getWindow().setNavigationBarColor(barColor);
toolbar.setBackgroundColor(barColor);
} else {
//4.4以下,沒有沉浸式這一說,我們不做任何處理
}
}
最終我的基類的程式碼如下:
/**
* 實現頂部及底部沉浸式導航欄的基類
*/
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//判斷手機的版本,如果是4.4的版本,則設定狀態列和導航欄透明,5.0以上不用設定,已經實現
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT &&
Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
}
/**
* 設定頂部及底部的沉浸式,這個方法需要子類來調,必須在setContentView()之後呼叫
*/
public void setTranslucentBar(final Toolbar toolbar, final View navigationView, int barColor) {
//當手機的版本在4.4的時候,設定透明之後,再設定高度,然後再設定顯示的顏色
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT &&
Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
if (toolbar != null) {
toolbar.post(new Runnable() {
@Override
public void run() {
ViewGroup.LayoutParams layoutParams = toolbar.getLayoutParams();
layoutParams.height += getBarHeight("status_bar_height");
toolbar.setLayoutParams(layoutParams);
}
});
toolbar.setBackgroundColor(barColor);
}
if (navigationView != null) {
//這時還要判斷當前手機有沒有底部虛擬導航欄,如果沒有的話,我們不做處理
if (hasNavigationView(getWindowManager())) {
navigationView.post(new Runnable() {
@Override
public void run() {
ViewGroup.LayoutParams layoutParams = navigationView.getLayoutParams();
layoutParams.height += getBarHeight("navigation_bar_height");
navigationView.setLayoutParams(layoutParams);
}
});
navigationView.setBackgroundColor(barColor);
}
}
//5.0及以上
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setStatusBarColor(barColor);
getWindow().setNavigationBarColor(barColor);
toolbar.setBackgroundColor(barColor);
} else {
//4.4以下,沒有沉浸式這一說,我們不做任何處理
}
}
/**
* 判斷當前手機是否含有底部導航欄,如果沒有的話返回false,有的話返回true
*
* @return
*/
private boolean hasNavigationView(WindowManager wm) {
Display display = wm.getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics();
display.getRealMetrics(outMetrics);
//獲取螢幕實際的高度,實際的高度包括內容的高度和底部導航的高度
int realHeight = outMetrics.heightPixels;
outMetrics = new DisplayMetrics();
display.getMetrics(outMetrics);
//螢幕中內容的高度
int heightPixels = outMetrics.heightPixels;
//如果實際的高度和大於內容的高度說明該手機含有底部導航,否則沒有
return realHeight - heightPixels > 0;
}
/**
* 獲取狀態列或是底部導航欄的高度
*
* @return
*/
public int getBarHeight(String dimenName) {
int height = 0;
try {
Class clazz = Class.forName("com.android.internal.R$dimen");
Object object = clazz.newInstance();
String s = clazz.getField(dimenName).get(object).toString();
int heightId = Integer.parseInt(s);
//dp 2 px
height = getResources().getDimensionPixelSize(heightId);
} catch (Exception e) {
e.printStackTrace();
}
return height;
}
}
它的子類的程式碼如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
navigationView = findViewById(R.id.navi);
setTranslucentBar(toolbar, navigationView, getResources().getColor(R.color.barcolor));
}
最終效果如下: