什么是沉浸式
官方的沉浸式Translucent:就是讓整個APP沉浸(充斥了整個屏幕)在屏幕里面,沒有顯示狀態(tài)欄,甚至沒有顯示底部導(dǎo)航欄。
平時大家所討論的沉浸式:比如QQ的頂部Toolbar和狀態(tài)欄程一體的顏色。
兼容開發(fā):
-
5.0+ API
5.0+自動實現(xiàn)了沉浸式效果,狀態(tài)欄的顏色跟隨你的主題里面的colorPrimaryDark屬性。1)通過設(shè)置主題達(dá)到
<style name="AppTheme" parent="AppBaseTheme">
<item name="android:textColor">@color/mytextcolor</item>
<item name="colorPrimary">@color/colorPrimary_pink</item>
<item name="colorPrimaryDark">@color/colorPrimary_pinkDark</item>
</style>
2)通過設(shè)置樣式屬性解決
<item name="android:statusBarColor">@color/system_bottom_nav_color</item>
3)通過代碼設(shè)置
//5.0+可以直接用API來修改狀態(tài)欄的顏色。
getWindow().setStatusBarColor(getResources().getColor(R.color.material_blue_grey_800)); 4.4 API
(低于4.4API,不可以做到)
用到一些特殊手段!----4.4(KitKat)新出的API,可以設(shè)置狀態(tài)欄為透明的。
1.在屬性樣式里面解決(不推薦使用,因為兼容不好)
<item name="android:windowTranslucentStatus">true</item>
2.再代碼里面解決
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
setContentView(R.layout.activity_main);
出現(xiàn)副作用:
APP的內(nèi)容頂?shù)阶钌厦嫒チ耍礌顟B(tài)欄會遮擋一部分界面。很坑
解決辦法(有幾種):
1)給Toolbar設(shè)置android:fitsSystemWindows="true"
該屬性的作用:設(shè)置布局時,是否考慮當(dāng)前系統(tǒng)窗口的布局,如果為true就會調(diào)整整個系統(tǒng)窗口
布局(包括狀態(tài)欄的view)以適應(yīng)你的布局。
但是:又出現(xiàn)了一個bug,當(dāng)里面有ScrollView并且ScrollView里面有Edittext的時候,就會出現(xiàn)軟鍵盤一彈起就會把toolbar拉下來,很難看
這種辦法有什么價值呢?如果里面沒有ScrollView就可以用。
2)推薦
靈感:發(fā)現(xiàn)給布局最外層容器設(shè)置android:fitsSystemWindows="true" 可以達(dá)到狀態(tài)欄透明,并且露出底色---android:windowBackground顏色。
巧妙地解決:步驟:
1.在最外層容器設(shè)置android:fitsSystemWindows="true"
2.直接將最外層容器(也可以修改-android:windowBackground顏色)設(shè)置成狀態(tài)欄想要的顏色
3.下面剩下的布局再包裹一層正常的背景顏色。
3)修改Toolbar的高度
1.設(shè)置狀態(tài)欄的透明屬性,不要給Toolbar設(shè)置android:fitsSystemWindows="true"
2.需要知道狀態(tài)欄的高度是多少?去源碼里面找找
<dimen name="status_bar_height">24dp</dimen>
<dimen name="navigation_bar_height">48dp</dimen>
反射手機(jī)運行的類:android.R.dimen.status_bar_height.
3.修改Toolbar的PaddingTop(因為純粹增加toolbar的高度會遮擋toobar里面的一些內(nèi)容)
toolbar.setPadding(
toolbar.getPaddingLeft(),
toolbar.getPaddingTop()+getStatusBarHeight(this),
toolbar.getPaddingRight(),
toolbar.getPaddingBottom());
private int getStatusBarHeight(Context context) {
// 反射手機(jī)運行的類:android.R.dimen.status_bar_height.
int statusHeight = -1;
try {
Class<?> clazz = Class.forName("com.android.internal.R$dimen");
Object object = clazz.newInstance();
String heightStr = clazz.getField("status_bar_height").get(object).toString();
int height = Integer.parseInt(heightStr);
//dp--->px
statusHeight = context.getResources().getDimensionPixelSize(height);
} catch (Exception e) {
e.printStackTrace();
}
return statusHeight;
}
NavigationBar沉浸式效果
- 5.x 底部虛擬導(dǎo)航沉浸效果
1)屬性解決
navigationBarColor
2)代碼
getWindow().setNavigationBarColor()
-
4.4
用到一些特殊手段!----4.4(KitKat)新出的API,可以設(shè)置虛擬導(dǎo)航欄為透明的。
步驟:
1)在布局底部添加一個高度為0.1dp的view
2)動態(tài)設(shè)置底部View的高度為虛擬導(dǎo)航欄的高度
View nav = findViewById(R.id.nav);
LayoutParams p = nav.getLayoutParams();
p.height += getNavigationBarHeight(this);
nav.setLayoutParams(p);
3.做兼容性判斷
1)SDK版本不一樣
兩個區(qū)間:1. 大于5.0;2.=<4.4sdk<5.02)有的沒有虛擬導(dǎo)航欄
判斷是否有虛擬導(dǎo)航欄(源碼里面有方法可以得到是否有虛擬導(dǎo)航,反射得到)3)有的有虛擬導(dǎo)航,但是還可以開關(guān)
判斷是否虛擬導(dǎo)航欄打開了
一步解決2)3)兩個問題: NavigationBarHeight=整個屏幕的高度 - 內(nèi)容部分view的高度 判斷是否>0
代碼:
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public class BaseTranslucentActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
//判斷版本,如果[4.4,5.0)就設(shè)置狀態(tài)欄和導(dǎo)航欄為透明
if(android.os.Build.VERSION.SDK_INT>=android.os.Build.VERSION_CODES.KITKAT
&&android.os.Build.VERSION.SDK_INT<android.os.Build.VERSION_CODES.LOLLIPOP){
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//設(shè)置虛擬導(dǎo)航欄為透明
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
}
@SuppressLint("NewApi")
public void setOrChangeTranslucentColor(Toolbar toolbar,View bottomNavigationBar, int translucentPrimaryColor){
//判斷版本,如果[4.4,5.0)就設(shè)置狀態(tài)欄和導(dǎo)航欄為透明
if(android.os.Build.VERSION.SDK_INT>=android.os.Build.VERSION_CODES.KITKAT
&&android.os.Build.VERSION.SDK_INT<android.os.Build.VERSION_CODES.LOLLIPOP){
if(toolbar!=null){
//1.先設(shè)置toolbar的高度
LayoutParams params = toolbar.getLayoutParams();
int statusBarHeight = getStatusBarHeight(this);
params.height += statusBarHeight ;
toolbar.setLayoutParams(params );
//2.設(shè)置paddingTop,以達(dá)到狀態(tài)欄不遮擋toolbar的內(nèi)容。
toolbar.setPadding(
toolbar.getPaddingLeft(),
toolbar.getPaddingTop()+getStatusBarHeight(this),
toolbar.getPaddingRight(),
toolbar.getPaddingBottom());
//設(shè)置頂部的顏色
toolbar.setBackgroundColor(translucentPrimaryColor);
}
if(bottomNavigationBar!=null){
//解決低版本4.4+的虛擬導(dǎo)航欄的
if(hasNavigationBarShow(getWindowManager())){
LayoutParams p = bottomNavigationBar.getLayoutParams();
p.height += getNavigationBarHeight(this);
bottomNavigationBar.setLayoutParams(p);
//設(shè)置底部導(dǎo)航欄的顏色
bottomNavigationBar.setBackgroundColor(translucentPrimaryColor);
}
}
}else if(android.os.Build.VERSION.SDK_INT>=android.os.Build.VERSION_CODES.LOLLIPOP){
getWindow().setNavigationBarColor(translucentPrimaryColor);
getWindow().setStatusBarColor(translucentPrimaryColor);
}else{
//<4.4的,不做處理
}
}
private int getNavigationBarHeight(Context context) {
return getSystemComponentDimen(this, "navigation_bar_height");
}
/**
* 獲取狀態(tài)欄的高度
* @param context
* @return
*/
private int getStatusBarHeight(Context context) {
// 反射手機(jī)運行的類:android.R.dimen.status_bar_height.
return getSystemComponentDimen(this, "status_bar_height");
}
private static int getSystemComponentDimen(Context context, String dimenName){
// 反射手機(jī)運行的類:android.R.dimen.status_bar_height.
int statusHeight = -1;
try {
Class<?> clazz = Class.forName("com.android.internal.R$dimen");
Object object = clazz.newInstance();
String heightStr = clazz.getField(dimenName).get(object).toString();
int height = Integer.parseInt(heightStr);
//dp--->px
statusHeight = context.getResources().getDimensionPixelSize(height);
} catch (Exception e) {
e.printStackTrace();
}
return statusHeight;
}
private static boolean hasNavigationBarShow(WindowManager wm){
Display display = wm.getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics();
//獲取整個屏幕的高度
display.getRealMetrics(outMetrics);
int heightPixels = outMetrics.heightPixels;
int widthPixels = outMetrics.widthPixels;
//獲取內(nèi)容展示部分的高度
outMetrics = new DisplayMetrics();
display.getMetrics(outMetrics);
int heightPixels2 = outMetrics.heightPixels;
int widthPixels2 = outMetrics.widthPixels;
int w = widthPixels-widthPixels2;
int h = heightPixels-heightPixels2;
System.out.println("~~~~~~~~~~~~~~~~h:"+h);
return w>0||h>0;//豎屏和橫屏兩種情況。
}
}