Android导航抽屉和windowActionBarOverlay = true

时间:2013-05-30 23:51:12

标签: android android-actionbar overlay navigation-drawer

我正在尝试在我的应用程序中实现新的Android导航抽屉。我创建了一个BaseActivity.java来处理Drawer设置和监听器,我有两个扩展这个基类的子活动。在第二个活动中,我计划使用以下attrs使用不同的操作栏样式:

<item name="android:windowActionBarOverlay">true</item>
<item name="android:background">@android:color/transparent</item>

使操作栏透明,并使内容更丰富,因为我的布局中有一个图片标题。

我已经实现了这一点,但现在问题是,因为内容正在扩展以利用使用ActionBar作为叠加层的额外空间,导航抽屉本身也在扩展并且它与ActionBar重叠,创建一个非常可怕的布局:

enter image description here

我想要做的是,实际内容(将用片段填充的框架布局)占用额外空间,但导航抽屉仍然位于操作栏下方,类似于Play音乐应用程序:

enter image description here

关于我能做些什么来实现这一目标的任何想法?

编辑所以,根据Ahmad的帮助,我只在ListView上设置了marginTop。这是布局:

<!-- The navigation drawer -->
<ListView android:id="@+id/left_drawer"
          android:layout_marginTop="?android:attr/actionBarSize"
<!-- This was added after seeing the crazy effect, but does nothing -->
          android:layout_marginBottom="0dp"
          android:layout_marginLeft="0dp"
          android:layout_marginRight="0dp"
          android:layout_width="240dp"
          android:layout_height="fill_parent"
          android:layout_gravity="start"
          android:choiceMode="singleChoice"
          android:background="?attr/listviewBackground"
          />

而现在,它对于顶端来说效果很好,但由于某种原因,在视图底部还有一个边距,这对我来说根本没有任何意义。 Here's a screenshot

不确定是什么导致它:(

5 个答案:

答案 0 :(得分:16)

  

而现在,它对于顶端来说效果很好,但由于某种原因,在视图底部还有一个边距,这对我来说根本没有任何意义。这是一个截图。

如果您将ListView引力设置为开始|底部,它可以解决您的问题。底部不添加额外的保证金。看起来DrawerLayout的默认引力是start | center

<ListView
    android:id="@+id/left_drawer"
    android:layout_marginTop="?android:attr/actionBarSize"
    android:layout_width="240dp"
    android:layout_height="match_parent"
    android:layout_gravity="start|bottom"/>

答案 1 :(得分:14)

如果有人对另一个人有兴趣接受这个问题。这是发生了什么。

我尝试将边距设置为列表视图的顶部,如下所示:

android:layout_marginTop="?android:attr/actionBarSize"

但正如在编辑过的问题中提到的那样,尽管没有在布局资源文件上设置,但有一个奇怪的行为,其中底部也有一个边距。

所以,我正在密切关注Play音乐应用程序并注意到它实际上并不是一个边距,而是一些填充,另外它们使用的是自定义背景,用填充透明色填充填充指定的空间。

这就是我的所作所为:

  • 在ListView的顶部设置填充,而不是边距:

    android:paddingTop="?android:attr/actionBarSize"

如前所述,重要的是不要根据设备的不同对硬件进行硬编码。

  • 创建一个自定义drawable,其顶部透明,然后是纯色的其余部分:

它看起来像这样:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
    <shape  android:shape="rectangle">
        <solid android:color="#80000000" />
    </shape>
</item>

<item android:top="@dimen/action_bar_default_height">
    <shape
            android:shape="rectangle">
        <solid android:color="@color/light_gray" />
    </shape>
</item>

请注意,我尝试在drawable上使用?android:attr/actionBarSize,但这会使应用程序强制关闭。相反,我搜索了grepcode,并为操作栏找到了一些不同大小的dimen文件,所以我将这些添加到我自己项目的dimen文件中。

  • 对于值:48dp
  • for values-land:40dp
  • 对于值-sw600dp:56dp

之后,我认为我看起来很棒,请注意截图视图中的listview和操作栏不重叠,listview的透明部分是正确的大小。

enter image description here

希望能帮助任何想知道如何实现这一目标的人。

答案 2 :(得分:8)

您可以在布局顶部设置边距,以便内容在ActionBar下方绘制。

只需在父布局中添加:

android:layout_marginTop="?android:attr/actionBarSize"

属性actionBarSize与您已经猜到的一样,指的是ActionBar的大小。您不能将绝对值设置为保证金,因为ActionBar在所有Android设备上并不总是具有相同的大小(平板电脑更大,手机设备更小)。

编辑:

将边距设为ListView

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <ListView
        android:id="@+id/left_drawer"
        android:layout_marginTop="?android:attr/actionBarSize"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"/>
</android.support.v4.widget.DrawerLayout>

Google音乐应用也是如此:

enter image description here

答案 3 :(得分:4)

我使用 paddingTop

解决了这个问题
<FrameLayout
    android:id="@+id/menu_frame"
    android:layout_width="240dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:paddingTop="?attr/actionBarSize" >

    <ListView 
        android:id="@+id/left_drawer_list"
        android:layout_width="240dp"
        android:layout_height="match_parent" />

</FrameLayout>

希望有所帮助

答案 4 :(得分:0)

我按照上述指南创建了一个工作演示,并在2.x到5.x

上进行了测试

您可以从Github

进行克隆

重要的是在主要活动中

    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>