25

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

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

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

我已经做到了,但现在的问题是,因为内容正在扩展以利用使用 ActionBar 作为覆盖的额外空间,导航抽屉本身也在扩展并且它与 ActionBar 重叠,创建了一个非常糟糕的外观布局:

在此处输入图像描述

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

在此处输入图像描述

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

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

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

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

不知道是什么原因造成的:(

4

5 回答 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"/>
于 2013-06-10T01:25:09.897 回答
14

万一有人对另一个问题感兴趣。这就是发生的事情。

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

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

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

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

这是我所做的:

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

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

如前所述,重要的是不要对尺寸进行硬编码,因为它们因设备而异。

  • 创建一个顶部透明的自定义可绘制对象,其余部分为纯色:

它看起来像这样:

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

请注意,我尝试?android:attr/actionBarSize在可绘制对象上使用,但这使应用程序强制关闭。相反,我通过 grepcode 搜索并找到了几个不同大小的操作栏的 dimen 文件,因此我将它们添加到我自己项目的 dimen 文件中。

  • 对于值:48dp
  • 对于值土地:40dp
  • 对于值-sw600dp:56dp

在那之后,我觉得我看起来很棒,请注意屏幕截图上的列表视图和操作栏是如何不重叠的,并且列表视图的透明部分的大小恰到好处。

在此处输入图像描述

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

于 2013-05-31T02:06:20.137 回答
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>

谷歌音乐应用也是如此:

在此处输入图像描述

于 2013-05-31T00:01:13.447 回答
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>

希望有帮助

于 2014-01-04T08:49:09.790 回答
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>
于 2014-12-30T12:35:15.147 回答