不能将 DrawerLayout 放在 StatusBar 下
Cannot put DrawerLayout under StatusBar
我有一个 activity 和一个 Navigation Drawer
并使用 ScrimInsetsFrameLayout
我能够将布局放在 StatusBar
下并且一切正常。
然后我决定将 Toolbar
和 StatusBar
的颜色替换为所有 activity 布局的 png
背景。
我 运行 模拟器上的应用程序(带有 android 6.0 的 Nexus 5),结果正是我想要的,就像你在下面的 Image #1 中看到的那样,但是当我在我的设备(Galaxy Note 3 with android 5.0)上尝试时,ScrimInsetsFrameLayout 中的布局超出了 StatusBar
Image #2。
我不明白哪里出了问题,你能帮帮我吗?
这是我的 values-v21
和我的 activity.xml
<style parent="Theme.AppCompat.Light.NoActionBar" name="AppTheme_Activities">
<item name="android:colorPrimary">@android:color/transparent</item>
<item name="android:colorPrimaryDark">@color/insetF</item>
<item name="android:navigationBarColor">@color/insetF</item>
<item name="android:colorAccent">@color/primary</item>
<item name="android:colorEdgeEffect">@color/primary</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:statusBarColor">@color/insetF</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
</style>
<?xml version="1.0"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/drawer"
android:fitsSystemWindows="true"
android:background="@drawable/background"> <!--png image-->
<FrameLayout
android:orientation="vertical"
android:layout_height="match_parent"
android:layout_width="match_parent">
<include layout="@layout/toolbar_activities" android:id="@+id/toolbar_layout"/>
<FrameLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/content_frame">
</FrameLayout>
</FrameLayout>
<com.example.myapplication.ScrimInsetsFrameLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/linearLayout"
android:layout_width="304dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:insetForeground="#4000"
android:clickable="true"
android:background="#ffffff"> .....
</com.example.myapplication.ScrimInsetsFrameLayout>
</android.support.v4.widget.DrawerLayout>
图片#1
图片#2
我遇到了同样的问题,码头。烦人的是似乎没有任何像样的指南来说明如何解决这个问题,即使它是 material 设计指南等的一部分
无论如何,我是这样做的...
样式
我的 styles.xml
包含一个基本主题,然后是我的主要应用程序主题。我为使用导航抽屉的活动创建了另一个主题,如下所示:
<style name="Base.AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowNoTitle">true</item>
<item name="windowActionBar">false</item>
</style>
<style name="AppTheme" parent="Base.AppTheme">
<item name="colorPrimary">@color/theme_primary</item>
<item name="colorPrimaryDark">@color/theme_primary_dark</item>
<item name="colorAccent">@color/theme_accent</item>
</style>
<style name="AppTheme.NavDrawer">
<item name="android:windowBackground">@color/window_background</item>
</style>
颜色 window_background
引用了我的 colors.xml
文件,该文件将其列为 #FFF5F5F5
。请注意,以上对于 API 21+ 的工作方式略有不同,因此在 values-v21
目录中,创建另一个 styles.xml
。这应该包括以下内容:
<style name="AppTheme.NavDrawer">
<item name="android:windowBackground">@color/window_background</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
布局
现在开始布局。在布局文件中,您将拥有导航抽屉,您可以包含以下内容。
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true" >
<!-- The main content view -->
<RelativeLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/main_adView">
<!-- The app bar -->
<android.support.design.widget.AppBarLayout
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<android.support.v7.widget.Toolbar
android:id="@+id/main_toolbar"
style="@style/AppTheme.Toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways"/>
</android.support.design.widget.AppBarLayout>
<!-- Your layout content below -->
<FrameLayout
android:id="@+id/your_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
<!-- Other stuff here if you like -->
</RelativeLayout>
<!-- The navigation drawer -->
<include layout="@layout/navdrawer"
android:id="@+id/main_navigationView" />
显然,如果您不需要其中的任何其他视图,您可以删除 RelativeLayout
,因为它是多余的。我在 <include>
标签中引用的导航抽屉如下:
<android.support.design.widget.NavigationView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="@dimen/navdrawer_width"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/navdrawer_header"
app:menu="@menu/navdrawer_items" />
使用上面的代码,你应该让你的导航抽屉正确地绘制在状态栏后面。
添加到您的 onCreate()
的 Activity
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
将ScrimInsetsFrameLayout
的android:fitsSystemWindows
属性改为false
从 DrawerLayout
中删除 android:fitsSystemWindows="true"
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/drawer"
android:background="@drawable/background"> <!--png image-->
<FrameLayout
android:orientation="vertical"
android:layout_height="match_parent"
android:layout_width="match_parent">
<include layout="@layout/toolbar_activities" android:id="@+id/toolbar_layout"/>
<FrameLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/content_frame">
</FrameLayout>
</FrameLayout>
<com.example.myapplication.ScrimInsetsFrameLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/linearLayout"
android:layout_width="304dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="false"
app:insetForeground="#4000"
android:clickable="true"
android:background="#ffffff"> .....
</com.example.myapplication.ScrimInsetsFrameLayout>
</android.support.v4.widget.DrawerLayout>
将这些样式添加到您的 AppTheme_Activities
主题中(保持您的状态所需的颜色):
<item name="windowActionBarOverlay">false</item>
<item name="android:windowActionBarOverlay">false</item>
<item name="android:fitsSystemWindows">false</item>
<item name="android:statusBarColor">#4000</item>
这个状态,工具栏也在状态栏下面,所以你需要做这个 hack:
让Toolbar
的身高="wrap_content"
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
设置 Padding
为 Toolbar
:
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setPadding(0, getStatusBarHeight(), 0, 0);
......
......
public int getStatusBarHeight() {
int result = 0;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
}
return result;
}
应该是这样!
我已经将状态栏下方带有导航抽屉的 test-application 的源代码上传到我的保管箱 - feel free to check it out.
我刚才回答了非常相似的问题 - 也许你也会发现它有用:
希望对你有所帮助
我有一个 activity 和一个 Navigation Drawer
并使用 ScrimInsetsFrameLayout
我能够将布局放在 StatusBar
下并且一切正常。
然后我决定将 Toolbar
和 StatusBar
的颜色替换为所有 activity 布局的 png
背景。
我 运行 模拟器上的应用程序(带有 android 6.0 的 Nexus 5),结果正是我想要的,就像你在下面的 Image #1 中看到的那样,但是当我在我的设备(Galaxy Note 3 with android 5.0)上尝试时,ScrimInsetsFrameLayout 中的布局超出了 StatusBar
Image #2。
我不明白哪里出了问题,你能帮帮我吗?
这是我的 values-v21
和我的 activity.xml
<style parent="Theme.AppCompat.Light.NoActionBar" name="AppTheme_Activities">
<item name="android:colorPrimary">@android:color/transparent</item>
<item name="android:colorPrimaryDark">@color/insetF</item>
<item name="android:navigationBarColor">@color/insetF</item>
<item name="android:colorAccent">@color/primary</item>
<item name="android:colorEdgeEffect">@color/primary</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:statusBarColor">@color/insetF</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
</style>
<?xml version="1.0"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/drawer"
android:fitsSystemWindows="true"
android:background="@drawable/background"> <!--png image-->
<FrameLayout
android:orientation="vertical"
android:layout_height="match_parent"
android:layout_width="match_parent">
<include layout="@layout/toolbar_activities" android:id="@+id/toolbar_layout"/>
<FrameLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/content_frame">
</FrameLayout>
</FrameLayout>
<com.example.myapplication.ScrimInsetsFrameLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/linearLayout"
android:layout_width="304dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:insetForeground="#4000"
android:clickable="true"
android:background="#ffffff"> .....
</com.example.myapplication.ScrimInsetsFrameLayout>
</android.support.v4.widget.DrawerLayout>
图片#1
图片#2
我遇到了同样的问题,码头。烦人的是似乎没有任何像样的指南来说明如何解决这个问题,即使它是 material 设计指南等的一部分
无论如何,我是这样做的...
样式
我的 styles.xml
包含一个基本主题,然后是我的主要应用程序主题。我为使用导航抽屉的活动创建了另一个主题,如下所示:
<style name="Base.AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowNoTitle">true</item>
<item name="windowActionBar">false</item>
</style>
<style name="AppTheme" parent="Base.AppTheme">
<item name="colorPrimary">@color/theme_primary</item>
<item name="colorPrimaryDark">@color/theme_primary_dark</item>
<item name="colorAccent">@color/theme_accent</item>
</style>
<style name="AppTheme.NavDrawer">
<item name="android:windowBackground">@color/window_background</item>
</style>
颜色 window_background
引用了我的 colors.xml
文件,该文件将其列为 #FFF5F5F5
。请注意,以上对于 API 21+ 的工作方式略有不同,因此在 values-v21
目录中,创建另一个 styles.xml
。这应该包括以下内容:
<style name="AppTheme.NavDrawer">
<item name="android:windowBackground">@color/window_background</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
布局
现在开始布局。在布局文件中,您将拥有导航抽屉,您可以包含以下内容。
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true" >
<!-- The main content view -->
<RelativeLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/main_adView">
<!-- The app bar -->
<android.support.design.widget.AppBarLayout
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<android.support.v7.widget.Toolbar
android:id="@+id/main_toolbar"
style="@style/AppTheme.Toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways"/>
</android.support.design.widget.AppBarLayout>
<!-- Your layout content below -->
<FrameLayout
android:id="@+id/your_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
<!-- Other stuff here if you like -->
</RelativeLayout>
<!-- The navigation drawer -->
<include layout="@layout/navdrawer"
android:id="@+id/main_navigationView" />
显然,如果您不需要其中的任何其他视图,您可以删除 RelativeLayout
,因为它是多余的。我在 <include>
标签中引用的导航抽屉如下:
<android.support.design.widget.NavigationView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="@dimen/navdrawer_width"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/navdrawer_header"
app:menu="@menu/navdrawer_items" />
使用上面的代码,你应该让你的导航抽屉正确地绘制在状态栏后面。
添加到您的
onCreate()
的Activity
getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
将
ScrimInsetsFrameLayout
的android:fitsSystemWindows
属性改为false
从
中删除DrawerLayout
android:fitsSystemWindows="true"
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_height="match_parent" android:layout_width="match_parent" android:id="@+id/drawer" android:background="@drawable/background"> <!--png image--> <FrameLayout android:orientation="vertical" android:layout_height="match_parent" android:layout_width="match_parent"> <include layout="@layout/toolbar_activities" android:id="@+id/toolbar_layout"/> <FrameLayout android:layout_height="match_parent" android:layout_width="match_parent" android:id="@+id/content_frame"> </FrameLayout> </FrameLayout> <com.example.myapplication.ScrimInsetsFrameLayout xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/linearLayout" android:layout_width="304dp" android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="false" app:insetForeground="#4000" android:clickable="true" android:background="#ffffff"> ..... </com.example.myapplication.ScrimInsetsFrameLayout> </android.support.v4.widget.DrawerLayout>
将这些样式添加到您的
AppTheme_Activities
主题中(保持您的状态所需的颜色):<item name="windowActionBarOverlay">false</item> <item name="android:windowActionBarOverlay">false</item> <item name="android:fitsSystemWindows">false</item> <item name="android:statusBarColor">#4000</item>
这个状态,工具栏也在状态栏下面,所以你需要做这个 hack:
让
Toolbar
的身高="wrap_content"
<android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" />
设置
Padding
为Toolbar
:Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); toolbar.setPadding(0, getStatusBarHeight(), 0, 0); ...... ...... public int getStatusBarHeight() { int result = 0; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { result = getResources().getDimensionPixelSize(resourceId); } } return result; }
应该是这样!
我已经将状态栏下方带有导航抽屉的 test-application 的源代码上传到我的保管箱 - feel free to check it out.
我刚才回答了非常相似的问题 - 也许你也会发现它有用:
希望对你有所帮助