J'aimerais créer un tiroir de navigation sur toute la largeur. Régler layout_width
sur match_parent
sur @+id/left_drawer
donne une largeur d'environ 80% de l'espace d'écran. Cela semble être le comportement standard. Dois-je remplacer onMeasure()
of DrawerLayout
?
Mon code actuel:
<?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>
Merci.
Oui, vous devez étendre DrawerLayout et remplacer certaines méthodes car MIN_DRAWER_MARGIN
est private
Voici une solution possible:
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);
}
}
Si vous voulez une solution plus simple, vous pouvez simplement définir une marge négative
Android:layout_marginLeft="-64dp"
pour votre 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"/>
Étant donné que toutes ces réponses ne fonctionnaient pas sous OS 6.0.1, je vais publier ici la solution qui fonctionnait pour moi en combinaison avec DrawerLayout
+ NavigationView
.
Donc, tout ce que je fais est de changer la largeur de la NavigationView
par programme:
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);
Cela fonctionne pour toutes les tailles d'écran.
Basé sur le Réponse de Robert , vous pouvez utiliser le layout_marginLeft=-64dp
pour résoudre ce problème facilement.
Cependant cela ne semble plus fonctionner sous Android 5.0 et supérieur. Alors voici ma solution qui a fonctionné pour moi.
<?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>
Fondamentalement, ajoutez Android:layout_marginRight="-64dp"
à la racine DrawerLayout
afin que toute la présentation passe à droite pour 64dp.
Ensuite, j'ajoute le layout_marginRight=64dp
au contenu afin qu'il retourne à la position d'origine. Ensuite, vous pouvez avoir un tiroir complet là-bas.
Une variante de la solution de Grogory:
Au lieu de sous-classer, j'appelle la méthode d'utilitaire suivante juste après avoir saisi une référence à la disposition du tiroir:
/**
* 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();
}
}
La classe FullDrawerLayout de Nipper est tout simplement géniale ... ses performances sont également plus rapides que celles du tiroir par défaut; vous ne pouvez pas l’utiliser sur des appareils avec une API qui n’ont pas view.getLayoutDirection (); (I'e: Class ne fonctionne pas sur tous les appareils Gingerbread)
donc ce que j'ai fait était
remplacé tous
view.getLayoutDirection();
avec le code ci-dessous
GravityCompat.getAbsoluteGravity(gravity,ViewCompat.getLayoutDirection(this));
Ma bibliothèque de support a été mise à jour au plus tard et le fullDrawerlayout a également été étendu au tiroir de navigation du support. Maintenant, cela fonctionne très bien les appareils Gingerbread
Essayez ceci a fonctionné pour moi:
<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"/>
Définir la largeur de la disposition incluse Android:layout_width="320dp"
. Pour les appareils avec une taille d'écran différente, vous pouvez définir de manière dynamique la largeur de cette disposition incluse.
Un autre moyen possible de résoudre le problème sans trop insister:
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);
}
}
}
Si, à un moment donné, la bibliothèque de support est mise à jour et que mMinDrawerMargin n'y est plus, vous obtiendrez une exception et pourrez résoudre le problème avant de publier votre prochaine mise à jour.
Je n'ai pas pris de mesures, mais supposons qu'il n'y ait pas beaucoup de réflexions qui affectent les performances. De plus, il n'exécute qu'une création de vue.
PS C'est étrange pourquoi DrawerLayout est si inflexible (je suis sur la marge minimale privée) à ce stade ...
Vous pouvez utiliser ceci. Inspiré par ce post , je me suis mis à jour pour la 5ème édition. Parce qu'il avait des problèmes avec StatusBar dans les versions 5 et ultérieures.
vous devez étendre DrawerLayout et remplacer certaines méthodes car MIN_DRAWER_MARGIN est privé
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;
}
}
<?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>
Cela fonctionne parfaitement pour moi. J'espère aider les autres.
vous pouvez par code ci-dessous
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);
<?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>