【问题标题】:How do I use DrawerLayout to display over the ActionBar/Toolbar and under the status bar?如何使用 DrawerLayout 在 ActionBar/Toolbar 上方和状态栏下方显示?
【发布时间】:2014-12-13 23:21:31
【问题描述】:

我在新材料设计Side Nav spec 中看到,您可以将抽屉显示在操作栏上方和状态栏后面。我该如何实现?

【问题讨论】:

  • 即使在今天,也没有一个明确的答案适用于向后兼容。这类问题确实激怒了任何程序员。已在 Android 系统中推广“N”API 和许多基础方面的改进。

标签: android navigation-drawer toolbar android-appcompat statusbar


【解决方案1】:

框架中的新功能和支持库正好允许这样做。共有三个“拼图”:

  1. 使用Toolbar,以便您可以将操作栏嵌入到视图层次结构中。
  2. 制作DrawerLayoutfitsSystemWindows,使其布局在系统栏后面。
  3. 禁用Theme.Material 的正常状态栏着色,以便 DrawerLayout 可以在那里绘制。

我假设您将使用新的 appcompat。

首先,你的布局应该是这样的:

<!-- The important thing to note here is the added fitSystemWindows -->
<android.support.v4.widget.DrawerLayout
    xmlns: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 -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <!-- We use a Toolbar so that our drawer can be displayed
             in 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, LinearLayout
         is just an example. As we have set fitSystemWindows=true
         this will be displayed under the status bar. -->
    <LinearLayout
        android: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>

然后在您的 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 ActionBar
    Toolbar 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);
}

然后你需要确保 DrawerLayout 在状态栏后面是可见的。你可以通过改变你的 values-v21 主题来做到这一点:

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>

注意: 如果使用&lt;fragment android:name="fragments.NavigationDrawerFragment"&gt; 而不是

<LinearLayout
    android:layout_width="304dp"
    android:layout_height="match_parent"
    android:layout_gravity="left|start"
    android:fitsSystemWindows="true">

    <!-- Your drawer content -->

</LinearLayout>

实际布局,如果你在从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;
}

【讨论】:

  • 是的,DrawerLayout 需要将其布置在系统栏后面。然后您需要在抽屉视图上设置它,以便DrawerLayout 将其放置在窗口插图中。
  • 根本无法让它工作。在一个新的演示应用程序中使用上面的代码,结果看起来与@ScootrNova 描述的相似。看到这个截图:imgur.com/QLk3syt
  • 看起来您实际上需要在抽屉内容布局的根目录中使用否定的layout_marginTop。否则,您的抽屉内容布局的背景将被绘制在状态栏的顶部,而其他所有内容都将被下推。然而,这似乎是一个粗略的解决方案,据我所知,没有 ?attr/statusBarSize 或 Android 提供的类似内容。
  • 为了获得抽屉通过状态栏可见的效果,我最终在 DrawerLayout 上将 android:fitsSystemWindows 设置为 false,在我的主要内容布局上将 android:fitsSystemWindows 设置为 true(包含工具栏),并将 true 添加到我的主题 - 在 Lollipop 上是
  • 这个答案不完整。您还需要将导航抽屉包装在 ScrimLayout 中。见stackoverflow.com/a/26926998/174149
【解决方案2】:

编辑:新的设计支持库支持这一点,不再需要以前的方法。

现在可以使用新的Android Design Support Library 来实现。

您可以查看 Chris Banes 的 Cheesesquare sample app,其中演示了所有新功能。


上一个方法:

由于没有发布完整的解决方案,这是我达到预期结果的方式。

首先在您的项目中包含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);
    }

    @Override
    protected boolean fitSystemWindows(Rect insets) {
        mInsets = new Rect(insets);
        setWillNotDraw(mInsetForeground == null);
        ViewCompat.postInvalidateOnAnimation(this);
        if (mOnInsetsCallback != null) {
            mOnInsetsCallback.onInsetsChanged(insets);
        }
        return true; // consume insets
    }

    @Override
    public 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());

            // Top
            mTempRect.set(0, 0, width, mInsets.top);
            mInsetForeground.setBounds(mTempRect);
            mInsetForeground.draw(canvas);

            // Bottom
            mTempRect.set(0, height - mInsets.bottom, width, height);
            mInsetForeground.setBounds(mTempRect);
            mInsetForeground.draw(canvas);

            // Left
            mTempRect.set(
                0, 
                mInsets.top, 
                mInsets.left, 
                height - mInsets.bottom);
            mInsetForeground.setBounds(mTempRect);
            mInsetForeground.draw(canvas);

            // Right
            mTempRect.set(
                width - mInsets.right, 
                mInsets.top, width, 
                height - mInsets.bottom);
            mInsetForeground.setBounds(mTempRect);
            mInsetForeground.draw(canvas);

            canvas.restoreToCount(sc);
        }
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (mInsetForeground != null) {
            mInsetForeground.setCallback(this);
        }
    }

    @Override
    protected 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);
    }
}

然后创建一个样式,以便可以设置insetForeground

values/attrs.xml

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

更新您的 Activity 的 xml 文件并确保 DrawerLayoutScrimInsetsFrameLayout 上的 android:fitsSystemWindows 设置为 true。

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 -->
    <LinearLayout
        android: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>

在活动的 onCreate 方法中设置抽屉布局的状态栏背景颜色。

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));
}

最后更新您应用的主题,使DrawerLayout 位于状态栏后面。

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>

结果:

【讨论】:

  • 这对我来说效果最好。我花了 2 天时间来完成这件事,这就是这个。这应该标记为答案。非常感谢。
  • 我没有使用 appcompat,这不起作用。 :( 是否有任何指南可以在没有 appcompat 的情况下使其正常工作?
  • 这是最完美的答案。我已经在从 4.X 到 5.X 的各种 Android 设备上实现并测试了它,并且可以确认它运行良好。非常感谢。
  • 正如我所说,它工作得很好,但我有一个小问题。带有导航抽屉的活动具有透明的状态栏,但所有其他活动都失去了状态栏中的“primaryDark”颜色。怎么找回来?
  • 我花了三天时间才接受目前除了使用包裹在抽屉片段周围的额外布局之外别无他法。否则状态栏将是灰色(第一个孩子的背景颜色)或抽屉将显示在状态栏下方。
【解决方案3】:

随着最新版Android Support Library (rev 22.2.0) 的发布,我们有了Design Support Library 以及一个名为NavigationView 的新视图。因此,我们无需使用 ScrimInsetsFrameLayout 和所有其他东西自己做所有事情,而是使用此视图,一切都为我们完成。

示例

步骤 1

Design Support Library 添加到您的build.gradle 文件中

dependencies {
    // Other dependencies like appcompat
    compile 'com.android.support:design:22.2.0'
}

第二步

NavigationView 添加到您的DrawerLayout

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/drawer_layout"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:fitsSystemWindows="true"> <!-- this is important -->

     <!-- Your contents -->

     <android.support.design.widget.NavigationView
         android:id="@+id/navigation"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:layout_gravity="start"
         app:menu="@menu/navigation_items" /> <!-- The items to display -->
 </android.support.v4.widget.DrawerLayout>

第三步

/res/menu 中创建一个新的菜单资源并添加您想要显示的项目和图标:

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_home"
            android:icon="@drawable/ic_action_home"
            android:title="Home" />
        <item
            android:id="@+id/nav_example_item_1"
            android:icon="@drawable/ic_action_dashboard"
            android:title="Example Item #1" />
    </group>

    <item android:title="Sub items">
        <menu>
            <item
                android:id="@+id/nav_example_sub_item_1"
                android:title="Example Sub Item #1" />
        </menu>
    </item>

</menu>

第四步

初始化 NavigationView 并处理点击事件:

public class MainActivity extends AppCompatActivity {

    NavigationView mNavigationView;
    DrawerLayout mDrawerLayout;

    // Other stuff

    private void init() {
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mNavigationView = (NavigationView) findViewById(R.id.navigation_view);
        mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(MenuItem menuItem) {
                mDrawerLayout.closeDrawers();
                menuItem.setChecked(true);
                switch (menuItem.getItemId()) {
                    case R.id.nav_home:
                        // TODO - Do something
                        break;
                    // TODO - Handle other items
                }
                return true;
            }
        });
    }
}

第 5 步

请务必在values-v21 中设置android:windowDrawsSystemBarBackgroundsandroid:statusBarColor,否则您的抽屉将不会显示在状态栏“下方”

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Other attributes like colorPrimary, colorAccent etc. -->
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
</style>

可选步骤

向 NavigationView 添加一个标题。为此,只需创建一个新布局并将 app:headerLayout="@layout/my_header_layout" 添加到 NavigationView。

结果

注意事项

  • 突出显示的颜色使用通过colorPrimary 属性定义的颜色
  • 列表项使用通过textColorPrimary属性定义的颜色
  • 图标使用通过textColorSecondary属性定义的颜色

您还可以查看 Chris Banesexample app,它突出显示 NavigationView 以及属于设计支持库的其他新视图(如 FloatingActionButton , TextInputLayout, Snackbar, TabLayout 等)

【讨论】:

  • 感谢@reVerse!!。 > 如果您想从样式文件更新列表中的每个项目和图标,可以使用:&lt;item name="itemTextColor"&gt;@color/YOUR_COLOR&lt;/item&gt;&lt;item name="itemIconTint"&gt;@color/YOUR_COLOR&lt;/item&gt;
  • 如何改变选中项的背景颜色?
  • 这种方法仍然会产生位于 ActionBar 后面的 NavigationView。
  • @southerton 当然,你必须使用 Toolbar - 没有办法使用 ActionBar 来做到这一点
  • @reegan29 只需拨打mDrawerLayout.openDrawer(GravityCompat.START); 即可。如果您使用的是ActionBarDrawerToggle,则应在您单击汉堡包图标时自动完成。
【解决方案4】:

使其工作,在 values-v21 样式或主题 xml 中需要使用此属性:

&lt;item name="android:windowTranslucentStatus"&gt;true&lt;/item&gt;

这就是魔法!

【讨论】:

  • 这使我的操作栏也出现在状态栏的后面。
  • 但这就是我们想要达到的效果,看看Gmail 5.0 应用程序?它显示状态栏后面的侧栏。
  • 我不是这个意思。尽管导航抽屉在这行代码的状态栏后面,工具栏/操作栏也是如此。
  • 发帖人和答主是设计 AppCompat 的 Google 员工,所以我很确定他在写内容时知道自己在做什么。
  • @Mixx,您可以为您的正常内容视图设置 android:fitsSystemWindows="true"(例如,如果采用接受的答案布局)。它可以工作,甚至适用于 Android 4.4。但这里有一点点不同:在 Android 5.0 中,状态栏的透明度级别比 GMail 中的更高(更高的 alpha 值),使状态栏更暗。
【解决方案5】:

以上所有方法都是正确的并且可能有效。我按照上述指南创建了一个工作演示,并在 2.x 到 5.x 上进行了测试

你可以从Github克隆

重要的事情是在 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);
} 

和回调

@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
}

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>

和 ScrimInsetsFrameLayout

现在有了新的Design Support library,这变得更容易了

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

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

【讨论】:

    【解决方案6】:

    我正在使用设计支持库。并且仅通过使用自定义主题,我在打开导航抽屉时实现了透明状态栏。

    <style name="NavigationStyle" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/primaryColor</item>
        <item name="colorPrimaryDark">@color/primaryColorDark</item>
    
        <!-- To Make Navigation Drawer Fill Status Bar and become Transparent Too -->
        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
    
    </style>
    

    最后在 Manifest File 中添加主题

    <activity
      ........
      ........
     android:theme="@style/NavigationStyle"> 
    </activity>
    

    别忘了使用属性,android:fitsSystemWindows="true" in "DrawerLayout"

    【讨论】:

    • 如何将其用于 api 级别 19 设备?
    【解决方案7】:

    这里提到的所有答案都太老太冗长了。与最新 Navigationview 一起使用的最佳和简短的解决方案是

    @Override
    public void onDrawerSlide(View drawerView, float slideOffset) {
        super.onDrawerSlide(drawerView, slideOffset);
    
        try {
            //int currentapiVersion = android.os.Build.VERSION.SDK_INT;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){
                // Do something for lollipop and above versions
    
            Window window = getWindow();
    
            // clear FLAG_TRANSLUCENT_STATUS flag:
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    
            // add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    
            // finally change the color to any color with transparency
    
             window.setStatusBarColor(getResources().getColor(R.color.colorPrimaryDarktrans));}
    
        } catch (Exception e) {
    
            Crashlytics.logException(e);
    
        }
    }
    

    这将在您打开抽屉时将您的状态栏颜色更改为透明

    现在,当您关闭抽屉时,您需要再次将状态栏颜色更改为深色。所以您可以这样做。

            public void onDrawerClosed(View drawerView) {
            super.onDrawerClosed(drawerView);
            try {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){
        // Do something for lollipop and above versions
    
        Window window = getWindow();
    
        // clear FLAG_TRANSLUCENT_STATUS flag:
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    
        // add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    
        // finally change the color again to dark
        window.setStatusBarColor(getResources().getColor(R.color.colorPrimaryDark));}
        } catch (Exception e) {
        Crashlytics.logException(e);
                        }
                        }
    

    然后在主布局中添加一行,即

                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"
                xmlns:tools="http://schemas.android.com/tools"
                android:id="@+id/drawer_layout"
                android:fitsSystemWindows="true"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
    

    你的导航视图看起来像

        <android.support.design.widget.NavigationView
            android:id="@+id/navigation_view"
            android:layout_height="match_parent"
            android:layout_width="wrap_content"
            android:layout_gravity="start"
            android:fitsSystemWindows="true"
            app:headerLayout="@layout/navigation_header"
            app:menu="@menu/drawer"
            />
    

    我已经对其进行了测试并且它完全可以工作。希望它可以帮助某人。这可能不是最好的方法,但它运行顺利并且易于实施。 如果有帮助,请标记它。快乐的编码:)

    【讨论】:

    • 另外,如果您在 ActionBar 中使用自定义视图,您可以在 onDrawerSlide() 中将自定义视图的可见性设置为 INVISIBLE,在 onDrawerClosed() 中设置为 VISIBLE。
    【解决方案8】:

    这是最简单的,它对我有用:

    在值 21 中:

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

    在价值观中:

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

    并设置到您的工具栏

    android:layout_marginTop="@dimen/topMargin"
    

    【讨论】:

    • 我也这样做了,它在 Lollipop 上就像一个魅力。但我使用24dp 作为上边距。
    • 当您在搭载 Android 7.1 的设备上划分屏幕时,如果您的应用是屏幕的第二部分,则您可以在顶部看到此间隙。
    【解决方案9】:

    而不是使用ScrimInsetsFrameLayout... 添加一个固定高度为24dp 和背景为primaryColor 的视图不是更容易吗?

    我知道这涉及在层次结构中添加一个虚拟视图,但它对我来说似乎更干净。

    我已经试过了,效果很好。

    <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_base_drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
    
            <!-- THIS IS THE VIEW I'M TALKING ABOUT... -->
            <View
                android:layout_width="match_parent"
                android:layout_height="24dp"
                android:background="?attr/colorPrimary" />
    
            <android.support.v7.widget.Toolbar
                android:id="@+id/activity_base_toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                android:elevation="2dp"
                android:theme="@style/ThemeOverlay.AppCompat.Dark" />
    
            <FrameLayout
                android:id="@+id/activity_base_content_frame_layout"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
    
        </LinearLayout>
    
        <fragment
            android:id="@+id/activity_base_drawer_fragment"
            android:name="com.myapp.drawer.ui.DrawerFragment"
            android:layout_width="240dp"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:elevation="4dp"
            tools:layout="@layout/fragment_drawer" />
    
    </android.support.v4.widget.DrawerLayout>
    

    【讨论】:

    • 当您在搭载 Android 7.1 的设备上划分屏幕时,如果您的应用是屏幕的第二部分,则您可以在顶部看到此间隙。
    【解决方案10】:

    试试这个:

    <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/drawer_layout"
    android:fitsSystemWindows="true">
    
    
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <!--Main layout and ads-->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
    
            <FrameLayout
                android:id="@+id/ll_main_hero"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1">
    
            </FrameLayout>
    
            <FrameLayout
                android:id="@+id/ll_ads"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
    
                <View
                    android:layout_width="320dp"
                    android:layout_height="50dp"
                    android:layout_gravity="center"
                    android:background="#ff00ff" />
            </FrameLayout>
    
    
        </LinearLayout>
    
        <!--Toolbar-->
        <android.support.v7.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/toolbar"
            android:elevation="4dp" />
    </FrameLayout>
    
    
    <!--left-->
    <ListView
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@null"
        android:background="@mipmap/layer_image"
        android:id="@+id/left_drawer"></ListView>
    
    <!--right-->
    <FrameLayout
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="right"
        android:background="@mipmap/layer_image">
    
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@mipmap/ken2"
            android:scaleType="centerCrop" />
    </FrameLayout>
    

    风格:

    <style name="ts_theme_overlay" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/red_A700</item>
        <item name="colorPrimaryDark">@color/red1</item>
        <item name="android:windowBackground">@color/blue_A400</item>
    </style>
    

    主 Activity 扩展 ActionBarActivity

    toolBar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolBar);
    

    现在你可以onCreateOptionsMenu 像普通的ActionBar 一样使用ToolBar。

    这是我的布局

    • 顶部:左抽屉 - 右抽屉
      • MID:工具栏 (ActionBar)
      • 底部:ListFragment

    希望你能理解!玩得开心!

    【讨论】:

      猜你喜欢
      • 2015-01-21
      • 2014-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多