Search code examples
androidlistviewgravitydrawerlayout

Why i can't lock DrawerLayout with layout gravity


I use DrawerLayout and recently i want to change gravity of listView in drawerLayout. But after i change gravity of listView to android:layout_gravity="start|bottom"from android:layout_gravity="start", drawerLayout can't be lock to

mDrawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);

setDrawerLockMode() work with;

<android.support.v4.widget.DrawerLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
</RelativeLayout>

<ListView
    android:id="@+id/drawer_list"
    android:layout_width="320dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:background="#F3F3F4"
    android:choiceMode="singleChoice" >
</ListView>

But it doesn't lock with;

<android.support.v4.widget.DrawerLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
</RelativeLayout>

<ListView
    android:id="@+id/drawer_list"
    android:layout_width="320dp"
    android:layout_height="match_parent"
    android:layout_gravity="start|bottom"
    android:background="#F3F3F4"
    android:choiceMode="singleChoice" >
</ListView>

`

Any clues of why can't I use lock mode with other gravities?

Thanks!


Solution

  • Based on the documentation, the only available gravities that can be used are Gravity.LEFT, Gravity.RIGHT or GravityCompat.START, GravityCompat.END.

    (Emphasis mine):

    Drawer positioning and layout is controlled using the android:layout_gravity attribute on child views corresponding to which side of the view you want the drawer to emerge from: left or right. (Or start/end on platform versions that support layout direction.)

    Looking at the source code

    public void setDrawerLockMode(int lockMode, int edgeGravity) {
      final int absGrav = GravityCompat.getAbsoluteGravity(edgeGravity,
                                                           ViewCompat.getLayoutDirection(this));
      if (absGrav == Gravity.LEFT) {
        mLockModeLeft = lockMode;
      } else if (absGrav == Gravity.RIGHT) {
        mLockModeRight = lockMode;
      }
      if (lockMode != LOCK_MODE_UNLOCKED) {
        // Cancel interaction in progress
        final ViewDragHelper helper = absGrav == Gravity.LEFT ? mLeftDragger : mRightDragger;
        helper.cancel();
      }
      switch (lockMode) {
        case LOCK_MODE_LOCKED_OPEN:
          final View toOpen = findDrawerWithGravity(absGrav);
          if (toOpen != null) {
            openDrawer(toOpen);
          }
          break;
        case LOCK_MODE_LOCKED_CLOSED:
          final View toClose = findDrawerWithGravity(absGrav);
          if (toClose != null) {
            closeDrawer(toClose);
          }
          break;
          // default: do nothing
      }
    }
    

    The method itself only checks if the gravity is LEFT or RIGHT (but uses a GravityCompat method, so START and END should be appropriately translated).

    This would mean that by setting a gravity of "start|bottom", you're introducing an invalid gravity, which causes setDrawerLockMode() to do nothing.