本文翻译自:How do I use DrawerLayout to display over the ActionBar/Toolbar and under the status bar?

I've seen in the new material design Side Nav spec that you can display the drawer over the action bar and behind the status bar. 我在新的材质设计Side Nav规范中看到,可以在操作栏上方和状态栏后面显示抽屉。 How can I implement this? 我该如何实施?


#1楼

参考:https://stackoom.com/question/1mwTn/如何使用DrawerLayout在操作栏-工具栏上方和状态栏下方显示


#2楼

New functionality in the framework and support libs allow exactly this. 框架和支持库中的新功能完全可以做到这一点。 There are three 'pieces of the puzzle': 一共有三个“谜题”:

  1. Using Toolbar so that you can embed your action bar into your view hierarchy. 使用工具栏,以便您可以将操作栏嵌入到视图层次结构中。
  2. Making DrawerLayout fitsSystemWindows so that it is layed out behind the system bars. 使DrawerLayout适合 fitsSystemWindows以便将其fitsSystemWindows在系统栏后面。
  3. Disabling Theme.Material 's normal status bar coloring so that DrawerLayout can draw there instead. 禁用Theme.Material的正常状态栏着色,以便DrawerLayout可以在此处绘制。

I'll assume that you will use the new appcompat. 我假设您将使用新的appcompat。

First, your layout should look like this: 首先,您的布局应如下所示:

<!-- The important thing to note here is the added fitSystemWindows -->
<android.support.v4.widget.DrawerLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/my_drawer_layout"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"><!-- Your normal content view --><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><!-- We use a Toolbar so that our drawer can be displayedin front of the action bar --><android.support.v7.widget.Toolbar  android:id="@+id/my_awesome_toolbar"android:layout_height="wrap_content"android:layout_width="match_parent"android:minHeight="?attr/actionBarSize"android:background="?attr/colorPrimary" /><!-- The rest of your content view --></LinearLayout><!-- Your drawer view. This can be any view, LinearLayoutis just an example. As we have set fitSystemWindows=truethis will be displayed under the status bar. --><LinearLayoutandroid:layout_width="304dp"android:layout_height="match_parent"android:layout_gravity="left|start"android:fitsSystemWindows="true"><!-- Your drawer content --></LinearLayout></android.support.v4.widget.DrawerLayout>

Then in your Activity/Fragment: 然后在您的活动/片段中:

public void onCreate(Bundled savedInstanceState) {super.onCreate(savedInstanceState);// Your normal setup. Blah blah ...// As we're using a Toolbar, we should retrieve it and set it// to be our ActionBarToolbar toolbar = (...) findViewById(R.id.my_awesome_toolbar);setSupportActionBar(toolbar);// Now retrieve the DrawerLayout so that we can set the status bar color.// This only takes effect on Lollipop, or when using translucentStatusBar// on KitKat.DrawerLayout drawerLayout = (...) findViewById(R.id.my_drawer_layout);drawerLayout.setStatusBarBackgroundColor(yourChosenColor);
}

Then you need to make sure that the DrawerLayout is visible behind the status bar. 然后,您需要确保DrawerLayout在状态栏后面可见。 You do that by changing your values-v21 theme: 您可以通过更改values-v21主题来做到这一点:

values-v21/themes.xml values-v21 / themes.xml

<style name="Theme.MyApp" parent="Theme.AppCompat.Light.NoActionBar"><item name="android:windowDrawsSystemBarBackgrounds">true</item><item name="android:statusBarColor">@android:color/transparent</item><item name="android:windowTranslucentStatus">true</item>
</style>

Note: If a <fragment android:name="fragments.NavigationDrawerFragment"> is used instead of 注意:如果使用<fragment android:name="fragments.NavigationDrawerFragment">而不是

<LinearLayoutandroid:layout_width="304dp"android:layout_height="match_parent"android:layout_gravity="left|start"android:fitsSystemWindows="true"><!-- Your drawer content --></LinearLayout>

the actual layout, the desired effect will be achieved if you call fitsSystemWindows(boolean) on a view that you return from onCreateView method. 实际的布局,如果在从onCreateView方法返回的视图上调用fitsSystemWindows(boolean) ,则将实现所需的效果。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View mDrawerListView = inflater.inflate(R.layout.fragment_navigation_drawer, container, false);mDrawerListView.setFitsSystemWindows(true);return mDrawerListView;
}

#3楼

Make it work, in values-v21 styles or theme xml needs to use this attribute: 使它工作,在values-v21样式或主题xml中需要使用此属性:

<item name="android:windowTranslucentStatus">true</item>

That make the magic! 那使魔术!


#4楼

This is the most simple, and it worked for me: 这是最简单的,对我有用:

In the values-21: 在值21中:

<resources><style name="AppTheme" parent="AppTheme.Base">...<item name="android:windowTranslucentStatus">true</item></style><dimen name="topMargin">25dp</dimen>
</resources>

In the values: 在值中:

<resources><dimen name="topMargin">0dp</dimen>
</resources>

And set to your toolbar 并设置到您的工具栏

android:layout_marginTop="@dimen/topMargin"

#5楼

EDIT: The new Design Support Library supports this and the previous method is no longer required. 编辑:新的设计支持库支持此,并且不再需要以前的方法。

This can now be achieved using the new Android Design Support Library . 现在,可以使用新的Android设计支持库来实现。

You can see the Cheesesquare sample app by Chris Banes which demos all the new features. 您可以看到Chris Banes提供的Cheesesquare示例应用程序 ,其中演示了所有新功能。


Previous method: 以前的方法:

Since there is no complete solution posted, here is the way I achieved the desired result. 由于没有发布完整的解决方案,因此这是我获得期望结果的方法。

First include a ScrimInsetsFrameLayout in your project. 首先在您的项目中包含一个ScrimInsetsFrameLayout 。

/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*//**
* A layout that draws something in the insets passed to
* {@link #fitSystemWindows(Rect)}, i.e. the area above UI chrome
* (status and navigation bars, overlay action bars).
*/
public class ScrimInsetsFrameLayout extends FrameLayout {private Drawable mInsetForeground;private Rect mInsets;private Rect mTempRect = new Rect();private OnInsetsCallback mOnInsetsCallback;public ScrimInsetsFrameLayout(Context context) {super(context);init(context, null, 0);}public ScrimInsetsFrameLayout(Context context, AttributeSet attrs) {super(context, attrs);init(context, attrs, 0);}public ScrimInsetsFrameLayout(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init(context, attrs, defStyle);}private void init(Context context, AttributeSet attrs, int defStyle) {final TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.ScrimInsetsView, defStyle, 0);if (a == null) {return;}mInsetForeground = a.getDrawable(R.styleable.ScrimInsetsView_insetForeground);a.recycle();setWillNotDraw(true);}@Overrideprotected boolean fitSystemWindows(Rect insets) {mInsets = new Rect(insets);setWillNotDraw(mInsetForeground == null);ViewCompat.postInvalidateOnAnimation(this);if (mOnInsetsCallback != null) {mOnInsetsCallback.onInsetsChanged(insets);}return true; // consume insets}@Overridepublic void draw(Canvas canvas) {super.draw(canvas);int width = getWidth();int height = getHeight();if (mInsets != null && mInsetForeground != null) {int sc = canvas.save();canvas.translate(getScrollX(), getScrollY());// TopmTempRect.set(0, 0, width, mInsets.top);mInsetForeground.setBounds(mTempRect);mInsetForeground.draw(canvas);// BottommTempRect.set(0, height - mInsets.bottom, width, height);mInsetForeground.setBounds(mTempRect);mInsetForeground.draw(canvas);// LeftmTempRect.set(0, mInsets.top, mInsets.left, height - mInsets.bottom);mInsetForeground.setBounds(mTempRect);mInsetForeground.draw(canvas);// RightmTempRect.set(width - mInsets.right, mInsets.top, width, height - mInsets.bottom);mInsetForeground.setBounds(mTempRect);mInsetForeground.draw(canvas);canvas.restoreToCount(sc);}}@Overrideprotected void onAttachedToWindow() {super.onAttachedToWindow();if (mInsetForeground != null) {mInsetForeground.setCallback(this);}}@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();if (mInsetForeground != null) {mInsetForeground.setCallback(null);}}/*** Allows the calling container to specify a callback for custom * processing when insets change (i.e. when {@link #fitSystemWindows(Rect)}* is called. This is useful for setting padding on UI elements * based on UI chrome insets (e.g. a Google Map or a ListView). * When using with ListView or GridView, remember to set* clipToPadding to false.*/public void setOnInsetsCallback(OnInsetsCallback onInsetsCallback) {mOnInsetsCallback = onInsetsCallback;}public static interface OnInsetsCallback {public void onInsetsChanged(Rect insets);}
}

Then create a styleable so that the insetForeground can be set. 然后创建一个可样式化的样式,以便可以设置insetForeground

values/attrs.xml values / attrs.xml

<declare-styleable name="ScrimInsetsView"><attr name="insetForeground" format="reference|color" />
</declare-styleable>

Update your activity's xml file and make sure android:fitsSystemWindows is set to true on both the DrawerLayout as well as the ScrimInsetsFrameLayout . 更新您的活动的XML文件,并确保android:fitsSystemWindows设置为true同时在DrawerLayout还有ScrimInsetsFrameLayout

layout/activity_main.xml layout / activity_main.xml

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/drawerLayout"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"tools:context=".MainActivity"><!-- The main content view --><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><!-- Your main content --></LinearLayout><!-- The navigation drawer --><com.example.app.util.ScrimInsetsFrameLayout xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/scrimInsetsFrameLayout"android:layout_width="320dp"android:layout_height="match_parent"android:layout_gravity="start"android:background="@color/white"android:elevation="10dp"android:fitsSystemWindows="true"app:insetForeground="#4000"><!-- Your drawer content --></com.example.app.util.ScrimInsetsFrameLayout></android.support.v4.widget.DrawerLayout>

Inside the onCreate method of your activity set the status bar background color on the drawer layout. 在活动的onCreate方法内,在抽屉布局中设置状态栏背景色。

MainActivity.java MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// ...mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);mDrawerLayout.setStatusBarBackgroundColor(getResources().getColor(R.color.primary_dark));
}

Finally update your app's theme so that the DrawerLayout is behind the status bar. 最后,更新您应用的主题,以使DrawerLayout位于状态栏的后面。

values-v21/styles.xml values-v21 / styles.xml

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"><item name="android:windowDrawsSystemBarBackgrounds">true</item><item name="android:statusBarColor">@android:color/transparent</item>
</style>

Result: 结果:

uG2mXrq.png


#6楼

The above all approaches are correct and may be working . 以上所有方法都是正确的,可能正在起作用。 I have created a working demo following the above guide and tested on 2.x to 5.x 我已经按照上述指南创建了一个工作演示,并在2.x至5.x上进行了测试

You can clone from Github 您可以从Github克隆

The important thing to play around is in Main Activity 重要的事情是在主要活动中

toolbar = (Toolbar) findViewById(R.id.toolbar);
res = this.getResources();this.setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { ScrimInsetsFrameLayout scrimInsetsFrameLayout = (ScrimInsetsFrameLayout)findViewById(R.id.linearLayout);scrimInsetsFrameLayout.setOnInsetsCallback(this);
}

and the call back 和回电

@Override
public void onInsetsChanged(Rect insets) {Toolbar toolbar = this.toolbar;ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams)toolbar.getLayoutParams();lp.topMargin = insets.top;int top = insets.top;insets.top += toolbar.getHeight();toolbar.setLayoutParams(lp);insets.top = top; // revert
}

Absolutely the Theme for V21 does the magic V21的主题绝对具有魔力

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"><!-- API 21 theme customizations can go here. --><item name="colorPrimary">@color/colorPrimary</item><item name="colorPrimaryDark">@color/colorPrimaryDark</item><item name="colorAccent">@color/accent_material_light</item><item name="windowActionModeOverlay">true</item><item name="android:windowDrawsSystemBarBackgrounds">true</item><item name="android:statusBarColor">@android:color/transparent</item><item name="android:windowTranslucentStatus">true</item>
</style>

and the ScrimInsetsFrameLayout 和ScrimInsetsFrameLayout

Now this come more easy with new Design Support library 现在,有了新的设计支持库,这将变得更加容易

compile 'com.android.support:design:22.2.0'

clone from @Chris Banes https://github.com/chrisbanes/cheesesquare 从@Chris Banes克隆https://github.com/chrisbanes/cheesesquare

如何使用DrawerLayout在操作栏/工具栏上方和状态栏下方显示?相关推荐

  1. android如何在底部显示四个按钮,[Android系列—] 四. 添加操作栏(Action Bar)

    [Android系列-] 4. 添加操作栏(Action Bar) 前言 操作栏是最重要的设计元素之一,使用它来实现你的应用程序活动.通过提供多种用户界面功能, 使应用程序快速和其他的Andorid应 ...

  2. 扩展用户体验之操作栏ActionBar

    一.什么是ActionBar 熟悉Android的人应该很清楚ActionBar指的是哪一部分,不熟悉的人并不清楚其的重要性,特别是Web app与Hybrid app开发者基本没有这一概念,当然在你 ...

  3. android中设置菜单栏,android – 菜单项没有显示在操作栏

    我做了一个全新的项目.我已经添加了项目到菜单布局文件.这些项目不会显示在操作栏的右侧.我记得一个有三个点的图标显示出来,打开菜单. 这里是我的活动 public class MainActivity ...

  4. 手机页面操作栏的创建及WebFont的使用

    一.手机界面底部操作栏的创建. 1 <style> 2 .opers{ 3 position:absolute; 4 bottom:0px; 5 left:0px; 6 right:0px ...

  5. Android自定义操作栏示例教程

    In this tutorial we will create an app that consists of Android Custom Action Bar with a custom layo ...

  6. Android源码编译:任意界面屏幕边缘上滑弹出快捷操作栏【一键加速、开关控制】

    <The Fucking Source Code> 注:以下均为android源码Framework层修改. 设计实现在任意界面从屏幕边缘上滑弹出快捷操作栏,包括亮度调节.正在后台运行的程 ...

  7. android更改app背景颜色,使用AppCompat更改操作栏的背景颜色

    我在网上发现了有关此问题的一些问题.不幸的是,到目前为止,我尝试的所有操作均未成功. 标题说,我需要更改操作栏的背景颜色. 该项目的最小sdk为9,最大sdk为19. 我在res / values文件 ...

  8. iphoneX的safari浏览器操作栏隐藏时兼容底部Home键

    iphoneX系列手机底部都有一个home键(横杠),safari浏览器会在页面滚动时隐藏底部的操作栏,许多应用都有在底部放置导航栏的需求.网上的帖子一般都是通过给底部导航栏元素添加内补34像素来处理 ...

  9. layui数据表格操作栏,根据条件改变显示操作的按钮

    本文内容参考网上多篇博客 环境和需求 在使用layui框架的数据表格的时候,需要的操作栏中添加修改,删除,保存等按钮.需求是点击保存按钮就不再显示修改删除两个按钮,二是显示已保存字样. 由于数据表格中 ...

最新文章

  1. matlab graphminspantree
  2. HTML areamap标签及在实际开发中的应用
  3. [Python]网络爬虫(三):异常的处理和HTTP状态码的分类
  4. MySQL IFNull 详解
  5. android执行main函数,AndroidStudio执行main方法报错
  6. C++ 你想要的C++面经都在这(附答案 | 持续更新)
  7. 安卓音量阶数修改_16款手机UI随便用,音量调节原来可以这样玩
  8. win11 c4d如何安装 Windows11安装c4d的步骤方法
  9. SOA介绍--什么是SOA?[转载]
  10. 拆素数【找规律,数学】
  11. 忘记电脑开机密码怎么办、win10、win7忘记开机密码怎么解决
  12. 利用HISTFILESIZE和HISTSIZE在ubunutu中调整命令行History的Size
  13. Koo叔说Shader—Shader简介
  14. fflush(stdout)
  15. php中如何获得当前周数,PHP中根据输入的周数获取到该周的日期范围
  16. 洛谷-P1314-聪明的质检员
  17. 阿里开发的这个网站,让我写文章效率提高50%
  18. Firefox火狐浏览器安装selenium IDE插件实现自动化脚本录制教程
  19. python高校学生消费行为分析系统
  20. 失败狮计划——在localStorage中保存vuex状态

热门文章

  1. Android开发之自定义Dialog二次打开报错问题解决
  2. Android开发之自定义Notification(源代码分享)
  3. Android属性 android:focusableInTouchMode
  4. toolbar menu 字体颜色和大小
  5. python软件管理系统_conda:基于python的软件管理系统
  6. Java继承_Hachi君浅聊Java三大特性之 封装 继承 多态
  7. IOS开发笔记16-Object-C中的属性
  8. Dart Metadata 使用
  9. RxSwift UI控件扩展
  10. (0034) iOS 开发之UIView动画(过渡效果)