Android导航抽屉和windowActionBarOverlay = true

25

我希望在我的应用中实现新的Android导航抽屉。我创建了一个BaseActivity.java来处理抽屉设置和侦听器,并且我有两个扩展此基类的子活动。在第二个活动中,我计划使用不同的操作栏样式,使用以下属性:

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

为了使操作栏透明并且使内容更加丰富,因为我的布局中有一个图片标题,我已经实现了这一点。但是现在的问题是,由于内容正在扩展以利用ActionBar作为叠加层的额外空间,导航抽屉本身也在扩展,它与ActionBar重叠,创建了一个非常糟糕的布局:

enter image description here

我希望实际内容(将用片段填充的框架布局)占用额外空间,但是导航抽屉仍然可以在ActionBar下面继续进行,类似于Play Music应用程序:

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"
          />

现在,它对于顶部很有效,但是由于某些原因,底部视图也有一个边距,这对我来说没有任何意义。 这里有一张截图

不确定是什么原因造成的:(


从文档中可以看到,他们建议使用填充而不是边距:android:paddingTop="?android:attr/actionBarSize" (http://developer.android.com/training/basics/actionbar/overlaying.html) - greg7gkb
5个回答

16

现在,它在顶部表现得非常好,但由于某种原因,在视图底部也有一个边距,这对我来说毫无意义。以下是屏幕截图。

如果将您的ListView重力设置为start|bottom,它会解决您的问题。底部不会再添加额外的边距。看起来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"/>

14

如果有人对这个问题还有兴趣,这里是另一种解决方法的说明:

我尝试将列表视图的边距仅设置到顶部,像这样:

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

但是根据编辑后的问题所述,尽管在布局资源文件中没有设置底部边距,但它具有奇怪的行为,底部也有一些边距。

因此,我仔细观察了Play Music应用程序,并注意到这实际上不是边距,而是一些填充,此外,他们还使用了一个自定义背景,用透明颜色填充了填充指定的空间。

这是我做的:

  • 在ListView的顶部设置Padding而不是Margin:

    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 文件中。

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

之后,我认为效果很棒。请注意截图,列表视图和动作栏不会重叠,而列表视图的透明部分正好合适。

enter image description here

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


我尝试了你的解决方案,但无法使其工作。背景是否设置为列表视图? - ebernie
你在哪里实现了“创建一个自定义的 drawable,它的顶部是透明的,其余部分是纯色的”? - Steve Luck

8
您可以在布局的顶部设置一个边距,以便内容在ActionBar下方绘制。
只需在父布局中添加以下内容:
android:layout_marginTop="?android:attr/actionBarSize"

属性 actionBarSize 指的是,正如您已经猜到的那样,ActionBar 的大小。您无法将绝对值设置为边距,因为在所有 Android 设备上,ActionBar 的大小并不总是相同的(在平板电脑上更大,在手持设备上更小)。
编辑:
将边距设置为 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>

谷歌音乐应用程序也是如此:

enter image description here


那样做不也会设置框架布局的边距吗?从而使片段的内容显示在操作栏下面? - daniel_c05
是的,这将把所有内容放在ActionBar下面。 - Ahmad
没错,这会带来问题,因为我希望内容利用操作栏的透明度,这就是我一开始使用覆盖层的原因。我只想让抽屉在操作栏下面。 - daniel_c05
嘿,Ahmad,你能看一下编辑后的问题吗?谢谢! - daniel_c05
@daniel_c05 抱歉我不在线。但看起来你已经解决了这个问题。 - Ahmad

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>

希望这有所帮助。

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>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接