1 首先要配置主题
在value-21下建立自己项目中使用的主题 并添加如下属性
状态栏
<item name="android:windowTranslucentStatus">false</item>
虚拟按键是否透明,这个为truefitsSystemWindows属性才有效果
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
2 关键属性 android:fitsSystemWindows="***"
这个属性当为true的时候代表子控件内容不会显示在状态栏上
当为false时子控件的内容允许显示在状态栏上,支持对布局里面多个子孩子添加
3 注意 这个属性只针对子孩子,并且需要自己处理状态栏的颜色,不然不太好看
4 发现的问题是,fragment创建后又销毁有创建 fitSystemWindows无效
侧拉布局沉濅式实现布局 参考
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--填充状态栏 大概高度30dp 不需要那么准确,能填充状态栏-->
<View
android:layout_width="match_parent"
android:layout_height="30dp"
android:background="@color/colorPrimaryDark"></View>
<!--让子孩子显示在状态栏下面 并且设置虚拟按键背景颜色 ,设置虚拟按键背景颜色 主要是background -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/lay_trans_color"
android:fitsSystemWindows="true"
android:orientation="vertical">
<!--布局思路 上面为导航栏的颜色 下面为虚拟按键的颜色 中间为内容的颜色-->
<!-- 由于上个布局设置了背景颜色为虚拟按键 子孩子不会显示在虚拟按键上 所以要恢复内容的背景颜色-->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="?android:windowBackground">
<!--在这里可以加入主体布局的内容 会正确的显示在屏幕内-->
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@color/red"
android:text="我是内容布局" />
</FrameLayout>
</LinearLayout>
</FrameLayout>
<!--侧拉布局内容 下面配置的false 也就是子孩子允许显示在状态栏上-->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="left"
android:background="@color/white"
android:clickable="true"
android:fitsSystemWindows="false"
android:focusable="true"
android:orientation="vertical">
<!--侧拉布局内容 在这里加入侧拉布局的xml 会显示在虚拟导航栏和状态栏上-->
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@color/yellow"
android:text="我是侧拉布局" />
</LinearLayout>
</android.support.v4.widget.DrawerLayout>
</android.support.design.widget.CoordinatorLayout>
lay_trans_color.xml 如下
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!--上面的30dp为透明颜色 下面的30dp设置为黑色 如果有虚拟按键显示为黑色-->
<item android:top="30dp">
<color android:color="@color/black"></color>
</item>
在value-21下建立自己项目中使用的主题 并添加如下属性
状态栏
<item name="android:windowTranslucentStatus">false</item>
虚拟按键是否透明,这个为truefitsSystemWindows属性才有效果
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
2 关键属性 android:fitsSystemWindows="***"
这个属性当为true的时候代表子控件内容不会显示在状态栏上
当为false时子控件的内容允许显示在状态栏上,支持对布局里面多个子孩子添加
3 注意 这个属性只针对子孩子,并且需要自己处理状态栏的颜色,不然不太好看
4 发现的问题是,fragment创建后又销毁有创建 fitSystemWindows无效
侧拉布局沉濅式实现布局 参考
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--填充状态栏 大概高度30dp 不需要那么准确,能填充状态栏-->
<View
android:layout_width="match_parent"
android:layout_height="30dp"
android:background="@color/colorPrimaryDark"></View>
<!--让子孩子显示在状态栏下面 并且设置虚拟按键背景颜色 ,设置虚拟按键背景颜色 主要是background -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/lay_trans_color"
android:fitsSystemWindows="true"
android:orientation="vertical">
<!--布局思路 上面为导航栏的颜色 下面为虚拟按键的颜色 中间为内容的颜色-->
<!-- 由于上个布局设置了背景颜色为虚拟按键 子孩子不会显示在虚拟按键上 所以要恢复内容的背景颜色-->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="?android:windowBackground">
<!--在这里可以加入主体布局的内容 会正确的显示在屏幕内-->
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@color/red"
android:text="我是内容布局" />
</FrameLayout>
</LinearLayout>
</FrameLayout>
<!--侧拉布局内容 下面配置的false 也就是子孩子允许显示在状态栏上-->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="left"
android:background="@color/white"
android:clickable="true"
android:fitsSystemWindows="false"
android:focusable="true"
android:orientation="vertical">
<!--侧拉布局内容 在这里加入侧拉布局的xml 会显示在虚拟导航栏和状态栏上-->
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@color/yellow"
android:text="我是侧拉布局" />
</LinearLayout>
</android.support.v4.widget.DrawerLayout>
</android.support.design.widget.CoordinatorLayout>
lay_trans_color.xml 如下
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!--上面的30dp为透明颜色 下面的30dp设置为黑色 如果有虚拟按键显示为黑色-->
<item android:top="30dp">
<color android:color="@color/black"></color>
</item>
</layer-list>
项目中具体效果如下
1 在fragment中发现当fragment销毁后有重新加载改fitsSystemWindows=true属性失效,可以通过一下方法解决。
在onActivityCreate里面调用此方法fixFitsSystemWindows即可
/** * fragment里面fitsSystemWindows=true有可能失效 * </p> * 需要手动调用此方法,修复fitsSystemWindows属性失效问题 * <p> * 带有fitSystemWindows=true属性的控件 * * @param fixView */ public static void fixFitsSystemWindows(final View fixView) { //4.4低版本上面没有fitsSystem没有 if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) return; boolean fitsSystemWindows = fixView.getFitsSystemWindows(); if (!fitsSystemWindows) return; //父控件 如果有这属性 fitsSystemWindows="true" 这个控件需要正确显示在屏幕内 fixView.getViewTreeObserver().addOnGlobalLayoutListener( new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { fixView.getViewTreeObserver() .removeGlobalOnLayoutListener(this); //因为有了 int paddingTop = fixView.getPaddingTop(); if (paddingTop < 1) paddingTop = ScreenUtils.getStatusHeight(fixView.getContext()); int navHeight = ScreenUtils.getNavigationBarHeight(fixView.getContext()); fixView.setPadding(0, paddingTop, 0, navHeight); } }); }
/** * 获得状态栏的高度 * * @param context * @return */ public static int getStatusHeight(Context context) { int statusHeight = -1; try { Class<?> clazz = Class.forName("com.android.internal.R$dimen"); Object object = clazz.newInstance(); int height = Integer.parseInt(clazz.getField("status_bar_height") .get(object).toString()); statusHeight = context.getResources().getDimensionPixelSize(height); } catch (Exception e) { e.printStackTrace(); } return statusHeight; }
//获取虚拟按键的高度 public static int getNavigationBarHeight(Context context) { int result = 0; if (hasNavigationBar(context)) { Resources res = context.getResources(); int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android"); if (resourceId > 0) { result = res.getDimensionPixelSize(resourceId); } } return result; } public static boolean hasNavigationBar(Context activity) { Resources rs = activity.getResources(); int id = rs.getIdentifier("config_showNavigationBar", "bool", "android"); boolean hasNavBarFun=false; if (id > 0) { hasNavBarFun = rs.getBoolean(id); } try { Class systemPropertiesClass = Class.forName("android.os.SystemProperties"); Method m = systemPropertiesClass.getMethod("get", String.class); String navBarOverride = (String)m.invoke(systemPropertiesClass, "qemu.hw.mainkeys"); if ("1".equals(navBarOverride)) { hasNavBarFun = false; } else if ("0".equals(navBarOverride)) { hasNavBarFun = true; } } catch (Exception e) { hasNavBarFun = false; } return hasNavBarFun; }