当前位置: 首页 > 知识库问答 >
问题:

如何将视图与抽屉布局的内容一起移动到同一个Z位置

胡星汉
2023-03-14

我的主视图在屏幕右上角的垂直线性布局中有3个按钮。每个按钮都显示一些托管在抽屉布局中的片段。这样地:

当我单击任何按钮时,我希望DrawerLayout从右侧显示,并在旁边翻译此按钮。像这样:

我已经设法用抽屉移动了按钮,但我的问题是抽屉的阴影也会影响按钮。我希望它像抽屉的内容一样明亮(同样高),但我也希望其他按钮留在抽屉后面。

这是我的主要活动。xml文件:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <include layout="@layout/content_main"/>

        <LinearLayout ... >
            <ImageButton ... />
            <ImageButton ... />
            <ImageButton ... />
        </LinearLayout>

        <FrameLayout
            android:id="@+id/fragment_secondary_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="right"
            tools:context="..."/>

    </android.support.v4.widget.DrawerLayout>

</android.support.design.widget.CoordinatorLayout>

抽屉布局中的按钮在抽屉上方移动,但正在翻译的按钮变暗。

另一方面,如果我把按钮放在抽屉布局外面,移动的按钮看起来没问题,但抽屉在其他按钮下面。例如:

有没有办法避免DrawerLayout的阴影影响特定视图?或者取消它?

共有1个答案

赵俊晤
2023-03-14

DrawerLayout将阴影(scrim)应用于其方法中的子视图。它通过检查给定的子对象不是抽屉视图来确定要将其应用于哪些子对象。它最终通过检查孩子的布局参数的重力来实现这一点。

知道了这一点,我们可以创建一个自定义的DrawerLayout子类来覆盖drawChild(),并临时更改我们不希望scrim应用到的子对象上的重力。由于绘制期间没有布局,因此这不会影响视图的实际放置。

public class CustomDrawerLayout extends DrawerLayout {

    private int noScrimId;

    public CustomDrawerLayout(Context context, AttributeSet attrs) {
        super(context, attrs);

        // Get the ID for the no-scrim View.
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomDrawerLayout);
        noScrimId = a.getResourceId(R.styleable.CustomDrawerLayout_noScrimView, View.NO_ID);
        a.recycle();
    }

    @Override
    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
        // Is this the child we want?
        final boolean isNoScrimView = child.getId() == noScrimId;

        // If yes, temporarily tag it as a drawer.
        if (isNoScrimView) {
            ((LayoutParams) child.getLayoutParams()).gravity = Gravity.LEFT;
        }

        // Let the super class do the draw, and save the return.
        final boolean res = super.drawChild(canvas, child, drawingTime);

        // Reset the gravity if we changed it.
        if (isNoScrimView) {
            ((LayoutParams) child.getLayoutParams()).gravity = Gravity.NO_GRAVITY;
        }

        return res;
    }
}

本例使用自定义属性,以便可以在布局中指定“无scrim”视图。如果不想使用该属性,可以从构造函数中删除TypedArray处理,只需硬编码一个ID。如果确实想使用自定义属性,则需要在项目中定义它,可以将以下文件粘贴到values/文件夹中,或添加到可能已经存在的文件中。

attrs.xml

<resources>
    <declare-styleable name="CustomDrawerLayout">
        <attr name="noScrimView" format="reference" />
    </declare-styleable>
</resources>

CustomDrawerLayout是一个直接替换,您可以像使用常规类一样在布局中使用它。例如,如果您的ImageButtons的LinearLayout具有IDbutton_menu

<com.mycompany.myapp.CustomDrawerLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:noScrimView="@+id/button_menu">

请注意,如果您碰巧将抽屉视图设置为noScrimView,您将度过一段不愉快的时光。此外,noScrimView必须是抽屉布局的直接子对象,因为scrim效果仅适用于这些子对象。

为简单起见,我省略了示例中的任何检查,但如果您希望包含一些检查,请在onometure()方法中执行它们将符合DrawerLayout处理自己检查的方式。

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    final View v = findViewById(noScrimId);
    if (v != null) {
        if (!(v.getLayoutParams() instanceof LayoutParams)) {
            throw new IllegalStateException("noScrimView must be a child of DrawerLayout");
        }
        if (((LayoutParams) v.getLayoutParams()).gravity != Gravity.NO_GRAVITY) {
            throw new IllegalStateException("noScrimView cannot be a drawer View");
        }
    }
    else {
        if (noScrimId != View.NO_ID) {
            Log.d(getClass().getSimpleName(), "noScrimView not found");
        }
    }
}
 类似资料:
  • 我做了一个没有actionbar的双抽屉布局,如下所示: 使用不带TitleBar或ActionBar的导航抽屉 请救命!!

  • 我有一个自定义布局,如下所示。它有三个标签。 标签2是可选的。它并不存在于每个细胞中。因此,我想隐藏它,并将标签1向下移动一点,以便在发生这种情况时与标签3居中对齐。 以下是我为每个标签添加的约束。 标签1 标签 2 标签3 请注意,我添加了一个额外的约束,将中心与Y对齐,值为0的标签为1,并将其优先级设置为750。我想,如果我去掉标签2,优先级较低的约束将取代它的位置并下移。 但它似乎不起作用。

  • 我的应用程序有一个显示当前位置的谷歌地图的父布局,还有一个子布局,在谷歌地图上从屏幕底部向上移动,但只移动到屏幕的一半。我用下面的代码实现了这一切。 向上滑动和向下滑动的动画: 滑下去。xml slide_up.xml 主要活动: 子布局 父布局 问题是 如果地图被放大以扩展,如果子布局向上滑动,则我的地图标记会隐藏在子布局后面。我想在这种情况下,我的地图应该自动向上滑动。 就像Whatsspp聊

  • 我想创建一个导航抽屉效果,但不是抽屉从左侧滑出,它必须在主视图的“后面”,因此滑动的项目是视图本身(即向右)-抽屉根本不移动,而是通过滑动主视图来“显示”。手指滑动(并点击汉堡图标)的动作与抽屉相同,只是显示效果不同。 主视图移动的方式与此处可以实现的方式相同 如何在抽屉布局左侧移动主要内容 但在我的例子中,我希望“抽屉”静态地位于主视图下方。 我通过叠加视图并使抽屉透明达到了预期效果——当然这意

  • 我想在其中一个视图隐藏时制作可调整大小的视图。下面的链接已经针对iOS提出了这个问题。我想为Android制作。感谢任何帮助。我想在将可见性设置为隐藏计数和折扣后,为三个TextViev:position、stat_name、price添加空闲空间 我在这里的风格是:

  • 在我的一个活动中有一个父容器,它调用由一个水平scrollview组成的子容器作为对象之一。有点像recyclerview,其中放置了行对象,有一个由水平滚动视图组成的公共行/项布局。 我的目标是同步horizontalscrollview的位置,这样,当我在其中一个对象上从位置1水平滚动到位置2时,包含HorizonalScrollview的所有其他项目都会从位置1更新到位置2。 这是我的主容器