【问题标题】:DrawerLayout on top of Actionbar操作栏顶部的 DrawerLayout
【发布时间】:2014-03-20 00:44:10
【问题描述】:

当使用抽屉布局时,有没有办法将抽屉视图覆盖在操作栏上?我不想在显示抽屉时隐藏操作栏。我希望操作栏保持原样,但被发送到后台。这方面的一个例子是 iOS Play 音乐应用程序...

我当前的实现会在抽屉状态更改时隐藏和显示操作栏,但我不喜欢这种用户体验。

        public void onDrawerClosed(View view) {
            getActionBar().show();
            invalidateOptionsMenu(); 
        }

        public void onDrawerOpened(View drawerView) {
            getActionBar().hide();
            invalidateOptionsMenu();
        }

【问题讨论】:

    标签: java android android-actionbar navigation-drawer drawerlayout


    【解决方案1】:

    我在网上搜索了这个问题的任何好的解决方案,但没有找到。所以我做了一个技巧来做到这一点。

    首先我们需要请求操作栏覆盖功能。所以在你的活动的onCreate() 之前,setContntView() 调用:requestWindowFeature(com.actionbarsherlock.view.Window.FEATURE_ACTION_BAR_OVERLAY);

    它将使包括导航抽屉在内的所有内容都绘制在操作栏后面。我们不需要这个,所以我们需要设置 FrameLayout 的上边距,它在 Activity 中承载我们的 Fragment,并具有操作栏的确切高度。在activity的布局文件中我们需要做如下:

    <!-- Framelayout to display Fragments -->
    
        <FrameLayout
            android:id="@+id/frame_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="?attr/actionBarSize" />
    

    它只会让导航抽屉出现在操作栏后面。 现在我们将在导航抽屉打开一半时隐藏操作栏,并在抽屉接近关闭时显示它。为此,我们需要在活动中进行以下操作:

    @Override
        public void onDrawerSlide(View drawerView, float slideOffset) {
            super.onDrawerSlide(drawerView, slideOffset);
    
            if(slideOffset > 0.5){
                actionBar.setBackgroundDrawable(null);
                actionBar.hide();
            } else {
                actionBar.show();
    
                if(slideOffset < 0.1){
                    actionBar.setBackgroundDrawable(layerDrawable);
                }
            }       
        }
    

    如您所见,在我开始隐藏它之前,我还更改了操作栏的背景可绘制对象以使其透明,并在我将其显示回来时将其更改回我的自定义背景。

    我的自定义背景是一个 layerListDrawable,它是全透明的,但底部有一个分隔线和一些阴影。

    为了实现这一点,我在 XML 中定义了以下层列表:

    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:top="0dp" android:left="0dp" android:bottom="0dp" android:right="0dp">
            <shape android:shape="rectangle">
                <solid android:color="@android:color/transparent"/>
            </shape>
        </item>
    
        <item android:top="0dp" android:left="0dp" android:bottom="0dp" android:right="0dp">
            <shape android:shape="rectangle">
                <solid android:color="#afafaf"/>
            </shape>
        </item>
    
        <item android:top="0dp" android:left="0dp" android:bottom="0dp" android:right="0dp">
            <shape android:shape="rectangle">
                <gradient
                    android:angle="270"
                    android:startColor="#88afafaf" 
                    android:endColor="#33afafaf"
                />
            </shape>
        </item>    
    </layer-list>
    

    为了从这个 XML 中获取我需要的背景,我在活动中执行以下操作:

    final ActionBar actionBar = getSupportActionBar();
            final LayerDrawable layerDrawable = (LayerDrawable) getResources()
                    .getDrawable(R.drawable.shadow_divider);
    
            final TypedArray styledAttributes = getTheme().obtainStyledAttributes(
                    new int[] { R.attr.actionBarSize });
            int topOffset = (int) (styledAttributes.getDimension(0, 0));
            styledAttributes.recycle();
    
            layerDrawable.setLayerInset(1, 0, topOffset - 3, 0, 2);
            layerDrawable.setLayerInset(2, 0, topOffset - 2, 0, 0);
    
            actionBar.setBackgroundDrawable(layerDrawable);
    

    其中 R.drawable.shadow_divider 是我之前定义的 XML 层列表。

    看起来真的很棒!希望它可以帮助某人。

    编辑

    我在这里遇到了一个小错误,有时这可能是我迷恋的原因。这是固定代码: `

        <FrameLayout
            android:id="@+id/frame_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            **android:paddingTop="?attr/actionBarSize"**  />`
    

    应该是 paddingTop 而不是 layout_marginTop

    【讨论】:

      【解决方案2】:

      这就是 Android 默认设置的正确效果。如果你想模拟 iOS 效果,你可能不得不自己做,因为 AFAIK 支持库的抽屉组件不允许这种类型的配置。

      无论如何,每当程序员编写大量代码只是为了在 Android 中模仿一些花哨(而且可能不值得)的 iOS 效果时,一只小猫就会死去......

      【讨论】:

      • 我完全同意你的看法,但客户希望在 iOS 和 Android 上获得相同的体验。看来我要去定制了。谢谢。
      • 我明白...我之前经历过,很多客户希望 Android 版本与 iOS 版本完全相同,但相信我,说服他们相信糟糕的是,它比实际在 Android 上重新编码所有 iOS 效果。
      • 恕我直言,“效果”不会破坏用户体验。 “小猫死了”的说法既愚蠢又充满争议……
      • 首先,我是一名专业的Android开发者。在一个以其创造的质量为荣的机构中全职工作。话虽这么说,我同意有些模式不应该跨平台,但并不是每个非常见的效果都是坏的。如果您在进行自定义操作时没有测试您的应用程序,那是您的错!说我发布未经测试的低质量应用程序是不礼貌的。如果客户想要某样东西并为此付出了代价,而这只是一个微不足道的不重要影响,那就太合理了!
      【解决方案3】:

      我认为您无法使用 Android 提供的 Navigation Drawer 来做到这一点(无需做一些真正骇人听闻的事情),因为这样做确实违反了 Android 设计模式。如果你想要一个库来满足你的需求,我在 Android 推出它自己的小部件之前使用了this 库,它可以满足你的需求。

      【讨论】:

      • 感谢滑动菜单的链接。我以前看过,并排除了它。现在看来,这可能是个不错的选择。
      【解决方案4】:

      我在我的问题中找到了答案,还添加了一个示例项目以供参考。你可以看看它是否适合你。 Android Navigation Drawer on top ActionBar

      【讨论】:

        【解决方案5】:

        您可以使用 ActionBarSherlock 来实现这一点。

        http://actionbarsherlock.com/

        【讨论】:

        • 现在使用 ActionBarSherlock 是个坏主意。
        • 这不是一个坏主意,只是不是最好的主意。
        • 使用提供与谷歌官方支持库几乎相同功能的第三方库来实现动画绝对是个坏主意,对不起
        • @thelawnmowerman 不是。 ABS 和 ABC 基本上是在做同样的事情,只是采取了不同的方法。老实说,我喜欢 ABS 采用的方法比 ABC 好得多。
        • ABS 在向后兼容性方面几乎是标准配置。有很多可用的库比操作系统提供的原始功能更好(不仅适用于 Android...)。 (反对票!)
        【解决方案6】:

        你可以做到,但抽屉看起来很尴尬,你不会喜欢它。我有同样的要求,最后我使用了定制为选项卡的单选按钮。您也可以尝试在抽屉打开时隐藏标签,反之亦然,但这肯定不是您想要的。

        您可以尝试使用 ViewPager、标签式指示器,例如 PagerTabStrip 和/或 TabPageIndicator。

        Source.

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-02-23
          • 1970-01-01
          相关资源
          最近更新 更多