web-dev-qa-db-ja.com

全幅ナビゲーションドロワー

全幅のナビゲーションドロワーを作成したい。 _layout_width_で_match_parent_を_@+id/left_drawer_に設定すると、画面スペースの約80%の幅になります。これは標準的な動作のようです。 DrawerLayoutonMeasure()をオーバーライドする必要がありますか?

私の現在のコード:

_<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:background="@color/black"
        Android:id="@+id/mainFragmentContainer">
    </FrameLayout>

    <include
        Android:id="@+id/left_drawer"
        Android:orientation="vertical"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:layout_gravity="start"
        layout="@layout/drawer"/>
</Android.support.v4.widget.DrawerLayout>
_

ありがとう。

33
Martin

はい、DrawerLayoutを拡張し、いくつかのメソッドをオーバーライドする必要があります。なぜならMIN_DRAWER_MARGINprivateです

考えられる解決策は次のとおりです。

public class FullDrawerLayout extends DrawerLayout {

    private static final int MIN_DRAWER_MARGIN = 0; // dp

    public FullDrawerLayout(Context context) {
        super(context);
    }

    public FullDrawerLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FullDrawerLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) {
            throw new IllegalArgumentException(
                    "DrawerLayout must be measured with MeasureSpec.EXACTLY.");
        }

        setMeasuredDimension(widthSize, heightSize);

        // Gravity value for each drawer we've seen. Only one of each permitted.
        int foundDrawers = 0;
        final int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);

            if (child.getVisibility() == GONE) {
                continue;
            }

            final LayoutParams lp = (LayoutParams) child.getLayoutParams();

            if (isContentView(child)) {
                // Content views get measured at exactly the layout's size.
                final int contentWidthSpec = MeasureSpec.makeMeasureSpec(
                        widthSize - lp.leftMargin - lp.rightMargin, MeasureSpec.EXACTLY);
                final int contentHeightSpec = MeasureSpec.makeMeasureSpec(
                        heightSize - lp.topMargin - lp.bottomMargin, MeasureSpec.EXACTLY);
                child.measure(contentWidthSpec, contentHeightSpec);
            } else if (isDrawerView(child)) {
                final int childGravity =
                        getDrawerViewGravity(child) & Gravity.HORIZONTAL_GRAVITY_MASK;
                if ((foundDrawers & childGravity) != 0) {
                    throw new IllegalStateException("Child drawer has absolute gravity " +
                            gravityToString(childGravity) + " but this already has a " +
                            "drawer view along that Edge");
                }
                final int drawerWidthSpec = getChildMeasureSpec(widthMeasureSpec,
                        MIN_DRAWER_MARGIN + lp.leftMargin + lp.rightMargin,
                        lp.width);
                final int drawerHeightSpec = getChildMeasureSpec(heightMeasureSpec,
                        lp.topMargin + lp.bottomMargin,
                        lp.height);
                child.measure(drawerWidthSpec, drawerHeightSpec);
            } else {
                throw new IllegalStateException("Child " + child + " at index " + i +
                        " does not have a valid layout_gravity - must be Gravity.LEFT, " +
                        "Gravity.RIGHT or Gravity.NO_GRAVITY");
            }
        }
    }

    boolean isContentView(View child) {
        return ((LayoutParams) child.getLayoutParams()).gravity == Gravity.NO_GRAVITY;
    }

    boolean isDrawerView(View child) {
        final int gravity = ((LayoutParams) child.getLayoutParams()).gravity;
        final int absGravity = Gravity.getAbsoluteGravity(gravity,
                child.getLayoutDirection());
        return (absGravity & (Gravity.LEFT | Gravity.RIGHT)) != 0;
    }

    int getDrawerViewGravity(View drawerView) {
        final int gravity = ((LayoutParams) drawerView.getLayoutParams()).gravity;
        return Gravity.getAbsoluteGravity(gravity, drawerView.getLayoutDirection());
    }

    static String gravityToString(int gravity) {
        if ((gravity & Gravity.LEFT) == Gravity.LEFT) {
            return "LEFT";
        }
        if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) {
            return "RIGHT";
        }
        return Integer.toHexString(gravity);
    }

}
30
Nipper

よりシンプルなソリューションが必要な場合は、負のマージンを設定するだけです

Android:layout_marginLeft="-64dp"

left_drawerの場合:

<include
        Android:id="@+id/left_drawer"
        Android:orientation="vertical"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:layout_gravity="start"
        layout="@layout/drawer"
        Android:layout_marginLeft="-64dp"/>
113
Robert

これらの答えはすべてOS 6.0.1では機能しなかったため、ここでDrawerLayout + NavigationViewと組み合わせて機能するソリューションを投稿します。

だから私がすることはすべて、プログラムでNavigationViewの幅を変更することです:

mNavigationView = (NavigationView) findViewById(R.id.nv_navigation);
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
DrawerLayout.LayoutParams params = (DrawerLayout.LayoutParams) mNavigationView.getLayoutParams();
params.width = metrics.widthPixels;
mNavigationView.setLayoutParams(params);

これはすべての画面サイズで機能します。

22
Aksiom

Robert's Answer に基づいて、layout_marginLeft=-64dpを使用してこの問題を簡単に解決できます。

しかし、Android 5.0以上)ではもう機能しないようです。だからここに私の解決策があります。

<?xml version="1.0" encoding="utf-8"?>
<Android.support.v4.widget.DrawerLayout
    Android:id="@+id/drawer_layout"
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:layout_marginRight="-64dp"
    Android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        layout="@layout/content"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:layout_marginRight="64dp"/>

    <include
        Android:id="@+id/left_drawer"
        Android:orientation="vertical"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:layout_gravity="start"
        layout="@layout/drawer"/>

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

基本的に、Android:layout_marginRight="-64dp"をルートDrawerLayoutに追加すると、64dpのすべてのレイアウトが右側に移動します。

次に、layout_marginRight=64dpをコンテンツに追加して、元の位置に戻ります。その後、そこに完全な引き出しを置くことができます。

11
gentra

Grogoryのソリューションのバリアント:

サブクラス化する代わりに、ドロワーレイアウトへの参照を取得した直後に、次のユーティリティメソッドを呼び出します。

/**
 * The specs tell that
 * <ol>
 * <li>Navigation Drawer should be at most 5*56dp wide on phones and 5*64dp wide on tablets.</li>
 * <li>Navigation Drawer should have right margin of 56dp on phones and 64dp on tablets.</li>
 * </ol>
 * yet the minimum margin is hardcoded to be 64dp instead of 56dp. This fixes it.
 */
public static void fixMinDrawerMargin(DrawerLayout drawerLayout) {
  try {
    Field f = DrawerLayout.class.getDeclaredField("mMinDrawerMargin");
    f.setAccessible(true);
    f.set(drawerLayout, 0);

    drawerLayout.requestLayout();
  } catch (Exception e) {
    e.printStackTrace();
  }
}
9
Eugen Pechanec

NipperのFullDrawerLayoutクラスは単純に素晴らしいです。パフォーマンスもデフォルトのドロワーよりも高速です。 (つまり、クラスはすべてのGingerbreadデバイスで動作しません)

だから私がやったことは

すべてを置き換えました

view.getLayoutDirection();

以下のコードで

GravityCompat.getAbsoluteGravity(gravity,ViewCompat.getLayoutDirection(this));

サポートライブラリを最新に更新し、fullDrawerlayoutをサポートナビゲーションドロワーに拡張しました。現在では、Gingerbreadデバイスでも問題なく動作します

4
Aman Satija

これが私のために働いたことを試してみてください:

<include
    Android:id="@+id/left_drawer"
    Android:orientation="vertical"
    Android:layout_width="320dp"
    Android:layout_height="match_parent"
    Android:layout_gravity="start"
    layout="@layout/drawer"/>

含まれるレイアウトの幅を設定Android:layout_width="320dp"。画面サイズが異なるデバイスの場合、この含まれるレイアウトの幅を動的に設定できます。

4
GOLDEE

過度にオーバーライドせずに問題を解決する別の可能な方法:

public class FullScreenDrawerLayout extends DrawerLayout {

... //List of constructors calling
... //super(...);
... //init();

/** Make DrawerLayout to take the whole screen. */
protected void init() {
    try {

        Field field = getClass().getSuperclass().getDeclaredField("mMinDrawerMargin");
        field.setAccessible(true);
        field.set(this, Integer.valueOf(0));

    } catch (Exception e) {
        throw new IllegalStateException("Android.support.v4.widget.DrawerLayout has changed and you have to fix this class.", e);
    }
}

}

ある時点でサポートライブラリが更新され、mminDrawerMarginがなくなった場合、次の更新を公開する前に例外が発生し、問題が修正されます。

測定しませんでしたが、パフォーマンスに影響するほど多くの反射がないと仮定します。さらに、ビューの作成ごとにのみ実行されます。

PSこの時点でDrawerLayoutが非常に柔軟性のないものになっているのは奇妙です(プライベート最小マージンについてです)...

4
GregoryK

これを使用できます。これに触発されて post 、私は第5版にアップグレードしました。バージョン5以降のStatusBarで問題があったためです。

mIN_DRAWER_MARGINはプライベートであるため、DrawerLayoutを拡張し、いくつかのメソッドをオーバーライドする必要があります

public class FullDrawerLayout extends DrawerLayout {

    private static final int MIN_DRAWER_MARGIN = 0; // dp

    public FullDrawerLayout(Context context) {
        super(context);
    }

    public FullDrawerLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FullDrawerLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) {
            throw new IllegalArgumentException(
                    "DrawerLayout must be measured with MeasureSpec.EXACTLY.");
        }

        setMeasuredDimension(widthSize, heightSize);

        //for support Android 5+
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Lollipop) {
            FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) getLayoutParams();
            params.topMargin = getStatusBarHeight();
            setLayoutParams(params);
        }

        // Gravity value for each drawer we've seen. Only one of each permitted.
        int foundDrawers = 0;
        final int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);

            if (child.getVisibility() == GONE) {
                continue;
            }

            final LayoutParams lp = (LayoutParams) child.getLayoutParams();

            if (isContentView(child)) {
                // Content views get measured at exactly the layout's size.
                final int contentWidthSpec = MeasureSpec.makeMeasureSpec(
                        widthSize - lp.leftMargin - lp.rightMargin, MeasureSpec.EXACTLY);
                final int contentHeightSpec = MeasureSpec.makeMeasureSpec(
                        heightSize - lp.topMargin - lp.bottomMargin, MeasureSpec.EXACTLY);
                child.measure(contentWidthSpec, contentHeightSpec);
            } else if (isDrawerView(child)) {
                final int childGravity =
                        getDrawerViewGravity(child) & Gravity.HORIZONTAL_GRAVITY_MASK;
                if ((foundDrawers & childGravity) != 0) {
                    throw new IllegalStateException("Child drawer has absolute gravity " +
                            gravityToString(childGravity) + " but this already has a " +
                            "drawer view along that Edge");
                }
                final int drawerWidthSpec = getChildMeasureSpec(widthMeasureSpec,
                        MIN_DRAWER_MARGIN + lp.leftMargin + lp.rightMargin,
                        lp.width);
                final int drawerHeightSpec = getChildMeasureSpec(heightMeasureSpec,
                        lp.topMargin + lp.bottomMargin,
                        lp.height);
                child.measure(drawerWidthSpec, drawerHeightSpec);
            } else {
                throw new IllegalStateException("Child " + child + " at index " + i +
                        " does not have a valid layout_gravity - must be Gravity.LEFT, " +
                        "Gravity.RIGHT or Gravity.NO_GRAVITY");
            }
        }
    }

    boolean isContentView(View child) {
        return ((LayoutParams) child.getLayoutParams()).gravity == Gravity.NO_GRAVITY;
    }

    boolean isDrawerView(View child) {
        final int gravity = ((LayoutParams) child.getLayoutParams()).gravity;
        final int absGravity = Gravity.getAbsoluteGravity(gravity,
                child.getLayoutDirection());
        return (absGravity & (Gravity.LEFT | Gravity.RIGHT)) != 0;
    }

    int getDrawerViewGravity(View drawerView) {
        final int gravity = ((LayoutParams) drawerView.getLayoutParams()).gravity;
        return Gravity.getAbsoluteGravity(gravity, drawerView.getLayoutDirection());
    }

    static String gravityToString(int gravity) {
        if ((gravity & Gravity.LEFT) == Gravity.LEFT) {
            return "LEFT";
        }
        if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) {
            return "RIGHT";
        }
        return Integer.toHexString(gravity);
    }


    public int getStatusBarHeight() {
        int result = 0;
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "Android");
        if (resourceId > 0) {
            result = getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }

}
3
Rasoul Miri
<?xml version="1.0" encoding="utf-8"?>
<Android.support.v4.widget.DrawerLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:id="@+id/drawer_layout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <FrameLayout
        Android:id="@+id/container"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent">

        <include
            layout="@layout/app_bar_dashboard"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent" />
    </FrameLayout>


    <Android.support.design.widget.NavigationView
        Android:id="@+id/nav_view"
        Android:layout_width="match_parent"
        Android:layout_marginRight="32dp"
        Android:layout_height="match_parent"
        Android:layout_gravity="start"
        Android:fitsSystemWindows="true">

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

    </Android.support.design.widget.NavigationView>

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

それは私にとって完璧に機能します。他の人を助けることを願っています。

1
Jamariya R

以下のコードでできます

 int width = getResources().getDisplayMetrics().widthPixels/2;
        DrawerLayout.LayoutParams params = (Android.support.v4.widget.DrawerLayout.LayoutParams) drawer_Linear_layout.getLayoutParams();
        params.width = width;
        drawer_Linear_layout.setLayoutParams(params);
1
Kirtikumar A.
<?xml version="1.0" encoding="utf-8"?><LinearLayout 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:orientation="vertical"
tools:context=".UserListActivity">

<LinearLayout
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:layout_alignParentTop="true"
    Android:background="@drawable/common_gradient"
    Android:layoutDirection="rtl"
    Android:orientation="vertical">

    <RelativeLayout
        Android:layout_width="match_parent"
        Android:layout_height="0dp"
        Android:layout_weight="0.2">

        <TextView
            Android:id="@+id/userType_textView"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:layout_centerHorizontal="true"
            Android:layout_centerVertical="true"
            Android:text="نوع المستخدم"
            Android:textColor="#000000"
            Android:textSize="20sp"
            tools:text="نوع المستخدم" />

        <TextView
            Android:id="@+id/className_textView"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:layout_below="@+id/userType_textView"
            Android:layout_centerHorizontal="true"
            Android:text="إسم القسم"
            Android:textColor="#000000"
            Android:textSize="16sp"
            tools:text="إسم القسم" />

        <ImageButton
            Android:layout_width="30dp"
            Android:layout_height="20dp"
            Android:layout_alignBottom="@+id/userType_textView"
            Android:layout_marginLeft="15dp"
            Android:layout_marginStart="15dp"
            Android:background="@Android:color/transparent"
            Android:contentDescription="@string/desc"
            Android:onClick="showMenuAction"
            Android:scaleType="fitCenter"
            Android:src="@drawable/menu" />
    </RelativeLayout>

    <RelativeLayout
        Android:layout_width="match_parent"
        Android:layout_height="0dp"
        Android:layout_weight="0.8"

        Android:background="#FAFAFA">

        <SearchView
            Android:id="@+id/user_searchView"
            Android:layout_width="match_parent"
            Android:layout_height="45dp"
            Android:layout_alignParentTop="true"
            Android:layout_centerHorizontal="true"
            Android:background="#9CC3D7" />

        <ListView
            Android:id="@+id/users_listView"
            Android:layout_width="100dp"
            Android:layout_height="100dp"

            Android:layout_alignParentBottom="true"
            Android:layout_below="@+id/user_searchView"
            Android:layout_centerHorizontal="true"
            Android:divider="#DFDEE1"
            Android:dividerHeight="1dp" />
    </RelativeLayout>

</LinearLayout>

<Android.support.v4.widget.DrawerLayout
    Android:id="@+id/navigationDrawerUser"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"

    Android:layoutDirection="rtl">


    <ExpandableListView
        Android:id="@+id/menu_listView_user"
        Android:layout_width="240dp"
        Android:layout_height="match_parent"
        Android:layout_gravity="start"
        Android:background="#195269"
        Android:choiceMode="singleChoice"
        Android:divider="#2C637D"
        Android:dividerHeight="1dp"
        Android:groupIndicator="@null">

    </ExpandableListView>

</Android.support.v4.widget.DrawerLayout>
0
khawlouta