DrawerLayout.java revision cde2707260e8241ffb816a03cbf5d52c28004b8a
11d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell/*
21d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Copyright (C) 2013 The Android Open Source Project
31d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell *
41d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Licensed under the Apache License, Version 2.0 (the "License");
51d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * you may not use this file except in compliance with the License.
61d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * You may obtain a copy of the License at
71d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell *
81d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell *      http://www.apache.org/licenses/LICENSE-2.0
91d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell *
101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Unless required by applicable law or agreed to in writing, software
111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * distributed under the License is distributed on an "AS IS" BASIS,
121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * See the License for the specific language governing permissions and
141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * limitations under the License.
151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */
161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellpackage android.support.v4.widget;
191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.content.Context;
211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.content.res.TypedArray;
221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.graphics.Canvas;
231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.graphics.Paint;
24b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powellimport android.graphics.PixelFormat;
25b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powellimport android.graphics.drawable.Drawable;
2657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powellimport android.os.Parcel;
2757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powellimport android.os.Parcelable;
28cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powellimport android.os.SystemClock;
291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.support.v4.view.GravityCompat;
30791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powellimport android.support.v4.view.KeyEventCompat;
311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.support.v4.view.MotionEventCompat;
321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.support.v4.view.ViewCompat;
331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.util.AttributeSet;
341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.Gravity;
35791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powellimport android.view.KeyEvent;
361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.MotionEvent;
371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.View;
381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.ViewGroup;
391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell/**
411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * DrawerLayout acts as a top-level container for window content that allows for
421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * interactive "drawer" views to be pulled out from the edge of the window.
431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell *
441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * <p>Drawer positioning and layout is controlled using the <code>android:layout_gravity</code>
451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * attribute on child views corresponding to </p>
461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell *
471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * <p>As per the Android Design guide, any drawers positioned to the left/start should
481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * always contain content for navigating around the application, whereas any drawers
491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * positioned to the right/end should always contain actions to take on the current content.
501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * This preserves the same navigation left, actions right structure present in the Action Bar
511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * and elsewhere.</p>
521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */
531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellpublic class DrawerLayout extends ViewGroup {
541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final String TAG = "DrawerLayout";
551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Indicates that any drawers are in an idle, settled state. No animation is in progress.
581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public static final int STATE_IDLE = ViewDragHelper.STATE_IDLE;
601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Indicates that a drawer is currently being dragged by the user.
631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public static final int STATE_DRAGGING = ViewDragHelper.STATE_DRAGGING;
651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Indicates that a drawer is in the process of settling to a final position.
681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public static final int STATE_SETTLING = ViewDragHelper.STATE_SETTLING;
701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
710492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
720492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * The drawer is unlocked.
730492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
740492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public static final int LOCK_MODE_UNLOCKED = 0;
750492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
760492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
770492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * The drawer is locked closed. The user may not open it, though
780492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * the app may open it programmatically.
790492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
800492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public static final int LOCK_MODE_LOCKED_CLOSED = 1;
810492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
820492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
830492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * The drawer is locked open. The user may not close it, though the app
840492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * may close it programmatically.
850492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
860492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public static final int LOCK_MODE_LOCKED_OPEN = 2;
870492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final int MIN_DRAWER_MARGIN = 64; // dp
891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final int DEFAULT_SCRIM_COLOR = 0x99000000;
911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
92ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    /**
931732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell     * Length of time to delay before peeking the drawer.
941732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell     */
951732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    private static final int PEEK_DELAY = 160; // ms
961732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
971732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    /**
98ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell     * Experimental feature.
99ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell     */
100ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    private static final boolean ALLOW_EDGE_LOCK = false;
101ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell
1021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final int[] LAYOUT_ATTRS = new int[] {
1031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            android.R.attr.layout_gravity
1041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    };
1051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private int mMinDrawerMargin;
1071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private int mScrimColor = DEFAULT_SCRIM_COLOR;
1091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private float mScrimOpacity;
1101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private Paint mScrimPaint = new Paint();
1111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private final ViewDragHelper mLeftDragger;
1131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private final ViewDragHelper mRightDragger;
1141732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    private final ViewDragCallback mLeftCallback;
1151732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    private final ViewDragCallback mRightCallback;
1161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private int mDrawerState;
117b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    private boolean mInLayout;
11857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    private boolean mFirstLayout = true;
1190492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    private int mLockModeLeft;
1200492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    private int mLockModeRight;
1211732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    private boolean mDisallowInterceptRequested;
122cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell    private boolean mChildrenCanceledTouch;
1231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private DrawerListener mListener;
1251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private float mInitialMotionX;
1271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private float mInitialMotionY;
1281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
129b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    private Drawable mShadowLeft;
130b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    private Drawable mShadowRight;
131b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
1321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
1331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Listener for monitoring events about drawers.
1341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
1351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public interface DrawerListener {
1361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
1371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when a drawer's position changes.
1381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param drawerView The child view that was moved
1391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param slideOffset The new offset of this drawer within its range, from 0-1
1401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
1411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onDrawerSlide(View drawerView, float slideOffset);
1421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
1441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when a drawer has settled in a completely open state.
1451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * The drawer is interactive at this point.
1461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         *
1471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param drawerView Drawer view that is now open
1481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
1491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onDrawerOpened(View drawerView);
1501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
1521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when a drawer has settled in a completely closed state.
1531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         *
1541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param drawerView Drawer view that is now closed
1551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
1561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onDrawerClosed(View drawerView);
1571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
1591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when the drawer motion state changes. The new state will
1601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * be one of {@link #STATE_IDLE}, {@link #STATE_DRAGGING} or {@link #STATE_SETTLING}.
1611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         *
1621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param newState The new drawer motion state
1631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
1641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onDrawerStateChanged(int newState);
1651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
1661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
167b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
168b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Stub/no-op implementations of all methods of {@link DrawerListener}.
169b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Override this if you only care about a few of the available callback methods.
170b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
171b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public static abstract class SimpleDrawerListener implements DrawerListener {
172b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
173b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerSlide(View drawerView, float slideOffset) {
174b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
175b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
176b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
177b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerOpened(View drawerView) {
178b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
179b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
180b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
181b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerClosed(View drawerView) {
182b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
183b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
184b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
185b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerStateChanged(int newState) {
186b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
187b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
188b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
1891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public DrawerLayout(Context context) {
1901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        this(context, null);
1911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
1921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public DrawerLayout(Context context, AttributeSet attrs) {
1941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        this(context, attrs, 0);
1951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
1961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public DrawerLayout(Context context, AttributeSet attrs, int defStyle) {
1981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        super(context, attrs, defStyle);
1991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final float density = getResources().getDisplayMetrics().density;
2011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mMinDrawerMargin = (int) (MIN_DRAWER_MARGIN * density + 0.5f);
2021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2031732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mLeftCallback = new ViewDragCallback(Gravity.LEFT);
2041732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mRightCallback = new ViewDragCallback(Gravity.RIGHT);
2051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2061732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mLeftDragger = ViewDragHelper.create(this, 0.5f, mLeftCallback);
2071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mLeftDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
2081732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mLeftCallback.setDragger(mLeftDragger);
2091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2101732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mRightDragger = ViewDragHelper.create(this, 0.5f, mRightCallback);
2111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mRightDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_RIGHT);
2121732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mRightCallback.setDragger(mRightDragger);
213791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
214791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        // So that we can catch the back button
215791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        setFocusableInTouchMode(true);
2161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
2171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
219b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Set a simple drawable used for the left or right shadow.
220b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * The drawable provided must have a nonzero intrinsic width.
221b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
222b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param shadowDrawable Shadow drawable to use at the edge of a drawer
223b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param gravity Which drawer the shadow should apply to
224b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
225b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public void setDrawerShadow(Drawable shadowDrawable, int gravity) {
226b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        /*
227b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         * TODO Someone someday might want to set more complex drawables here.
228b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         * They're probably nuts, but we might want to consider registering callbacks,
229b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         * setting states, etc. properly.
230b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         */
231b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
232b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        final int absGravity = GravityCompat.getAbsoluteGravity(gravity,
233b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                ViewCompat.getLayoutDirection(this));
234b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if ((absGravity & Gravity.LEFT) == Gravity.LEFT) {
235b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowLeft = shadowDrawable;
236b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            invalidate();
237b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
238b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if ((absGravity & Gravity.RIGHT) == Gravity.RIGHT) {
239b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowRight = shadowDrawable;
240b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            invalidate();
241b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
242b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
243b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
244b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
245b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Set a simple drawable used for the left or right shadow.
246b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * The drawable provided must have a nonzero intrinsic width.
247b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
248b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param resId Resource id of a shadow drawable to use at the edge of a drawer
249b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param gravity Which drawer the shadow should apply to
250b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
251b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public void setDrawerShadow(int resId, int gravity) {
252b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        setDrawerShadow(getResources().getDrawable(resId), gravity);
253b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
254b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
255b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
256fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell     * Set a color to use for the scrim that obscures primary content while a drawer is open.
257fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell     *
258fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell     * @param color Color to use in 0xAARRGGBB format.
259fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell     */
260fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell    public void setScrimColor(int color) {
261fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell        mScrimColor = color;
262fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell        invalidate();
263fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell    }
264fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell
265fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell    /**
2661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Set a listener to be notified of drawer events.
2671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
2681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param listener Listener to notify when drawer events occur
2691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @see DrawerListener
2701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
2711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void setDrawerListener(DrawerListener listener) {
2721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mListener = listener;
2731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
2741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
2760492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Enable or disable interaction with all drawers.
2770492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
2780492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>This allows the application to restrict the user's ability to open or close
2790492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * any drawer within this layout. DrawerLayout will still respond to calls to
2800492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * {@link #openDrawer(int)}, {@link #closeDrawer(int)} and friends if a drawer is locked.</p>
2810492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
2820492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>Locking drawers open or closed will implicitly open or close
2830492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * any drawers as appropriate.</p>
2840492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
2850492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param lockMode The new lock mode for the given drawer. One of {@link #LOCK_MODE_UNLOCKED},
2860492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *                 {@link #LOCK_MODE_LOCKED_CLOSED} or {@link #LOCK_MODE_LOCKED_OPEN}.
2870492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
2880492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public void setDrawerLockMode(int lockMode) {
2890492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        setDrawerLockMode(lockMode, Gravity.LEFT);
2900492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        setDrawerLockMode(lockMode, Gravity.RIGHT);
2910492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
2920492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
2930492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
2940492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Enable or disable interaction with the given drawer.
2950492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
2960492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>This allows the application to restrict the user's ability to open or close
2970492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * the given drawer. DrawerLayout will still respond to calls to {@link #openDrawer(int)},
2980492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * {@link #closeDrawer(int)} and friends if a drawer is locked.</p>
2990492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
3000492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>Locking a drawer open or closed will implicitly open or close
3010492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * that drawer as appropriate.</p>
3020492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
3030492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param lockMode The new lock mode for the given drawer. One of {@link #LOCK_MODE_UNLOCKED},
3040492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *                 {@link #LOCK_MODE_LOCKED_CLOSED} or {@link #LOCK_MODE_LOCKED_OPEN}.
3050492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param edgeGravity Gravity.LEFT, RIGHT, START or END.
3060492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *                    Expresses which drawer to change the mode for.
3070492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
3080492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_UNLOCKED
3090492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_LOCKED_CLOSED
3100492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_LOCKED_OPEN
3110492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
3120492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public void setDrawerLockMode(int lockMode, int edgeGravity) {
3130492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        final int absGrav = GravityCompat.getAbsoluteGravity(edgeGravity,
3140492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                ViewCompat.getLayoutDirection(this));
3150492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        if (absGrav == Gravity.LEFT) {
3160492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            mLockModeLeft = lockMode;
3170492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        } else if (absGrav == Gravity.RIGHT) {
3180492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            mLockModeRight = lockMode;
3190492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
3200492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        if (lockMode != LOCK_MODE_UNLOCKED) {
3210492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            // Cancel interaction in progress
3220492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            final ViewDragHelper helper = absGrav == Gravity.LEFT ? mLeftDragger : mRightDragger;
3230492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            helper.cancel();
3240492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
3250492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        switch (lockMode) {
3260492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            case LOCK_MODE_LOCKED_OPEN:
3270492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                final View toOpen = findDrawerWithGravity(absGrav);
3280492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                if (toOpen != null) {
3290492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                    openDrawer(toOpen);
3300492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                }
3310492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                break;
3320492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            case LOCK_MODE_LOCKED_CLOSED:
3330492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                final View toClose = findDrawerWithGravity(absGrav);
3340492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                if (toClose != null) {
3350492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                    closeDrawer(toClose);
3360492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                }
3370492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                break;
3380492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            // default: do nothing
3390492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
3400492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
3410492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
3420492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
3430492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Enable or disable interaction with the given drawer.
3440492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
3450492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>This allows the application to restrict the user's ability to open or close
3460492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * the given drawer. DrawerLayout will still respond to calls to {@link #openDrawer(int)},
3470492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * {@link #closeDrawer(int)} and friends if a drawer is locked.</p>
3480492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
3490492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>Locking a drawer open or closed will implicitly open or close
3500492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * that drawer as appropriate.</p>
3510492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
3520492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param lockMode The new lock mode for the given drawer. One of {@link #LOCK_MODE_UNLOCKED},
3530492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *                 {@link #LOCK_MODE_LOCKED_CLOSED} or {@link #LOCK_MODE_LOCKED_OPEN}.
3540492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param drawerView The drawer view to change the lock mode for
3550492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
3560492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_UNLOCKED
3570492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_LOCKED_CLOSED
3580492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_LOCKED_OPEN
3590492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
3600492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public void setDrawerLockMode(int lockMode, View drawerView) {
3610492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        if (!isDrawerView(drawerView)) {
3620492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            throw new IllegalArgumentException("View " + drawerView + " is not a " +
3630492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                    "drawer with appropriate layout_gravity");
3640492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
3650492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        setDrawerLockMode(lockMode, getDrawerViewGravity(drawerView));
3660492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
3670492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
3680492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
3690492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Check the lock mode of the drawer with the given gravity.
3700492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
3710492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param edgeGravity Gravity of the drawer to check
3720492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @return one of {@link #LOCK_MODE_UNLOCKED}, {@link #LOCK_MODE_LOCKED_CLOSED} or
3730492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *         {@link #LOCK_MODE_LOCKED_OPEN}.
3740492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
3750492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public int getDrawerLockMode(int edgeGravity) {
3760492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        final int absGrav = GravityCompat.getAbsoluteGravity(edgeGravity,
3770492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                ViewCompat.getLayoutDirection(this));
3780492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        if (absGrav == Gravity.LEFT) {
3790492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            return mLockModeLeft;
3800492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        } else if (absGrav == Gravity.RIGHT) {
3810492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            return mLockModeRight;
3820492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
3830492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        return LOCK_MODE_UNLOCKED;
3840492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
3850492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
3860492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
3870492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Check the lock mode of the given drawer view.
3880492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
3890492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param drawerView Drawer view to check lock mode
3900492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @return one of {@link #LOCK_MODE_UNLOCKED}, {@link #LOCK_MODE_LOCKED_CLOSED} or
3910492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *         {@link #LOCK_MODE_LOCKED_OPEN}.
3920492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
3930492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public int getDrawerLockMode(View drawerView) {
3940492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        final int gravity = getDrawerViewGravity(drawerView);
3950492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        if (gravity == Gravity.LEFT) {
3960492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            return mLockModeLeft;
3970492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        } else if (gravity == Gravity.RIGHT) {
3980492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            return mLockModeRight;
3990492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
4000492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
4010492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        return LOCK_MODE_UNLOCKED;
4020492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
4030492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
4040492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
4051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Resolve the shared state of all drawers from the component ViewDragHelpers.
4061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Should be called whenever a ViewDragHelper's state changes.
4071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
408b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    void updateDrawerState(int forGravity, int activeState, View activeDrawer) {
4091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int leftState = mLeftDragger.getViewDragState();
4101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int rightState = mRightDragger.getViewDragState();
4111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int state;
4131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (leftState == STATE_DRAGGING || rightState == STATE_DRAGGING) {
4141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            state = STATE_DRAGGING;
4151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        } else if (leftState == STATE_SETTLING || rightState == STATE_SETTLING) {
4161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            state = STATE_SETTLING;
4171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        } else {
4181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            state = STATE_IDLE;
4191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
4201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
421b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (activeDrawer != null && activeState == STATE_IDLE) {
422b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final LayoutParams lp = (LayoutParams) activeDrawer.getLayoutParams();
423b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            if (lp.onScreen == 0) {
424b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                dispatchOnDrawerClosed(activeDrawer);
425b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            } else if (lp.onScreen == 1) {
426b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                dispatchOnDrawerOpened(activeDrawer);
427b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            }
428b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
429b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
4301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (state != mDrawerState) {
4311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mDrawerState = state;
432b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
4331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (mListener != null) {
4341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mListener.onDrawerStateChanged(state);
4351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
4361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
4371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
4381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void dispatchOnDrawerClosed(View drawerView) {
4401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
4411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (lp.knownOpen) {
4421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            lp.knownOpen = false;
4431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (mListener != null) {
4441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mListener.onDrawerClosed(drawerView);
4451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
4461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
4471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
4481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void dispatchOnDrawerOpened(View drawerView) {
4501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
4511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (!lp.knownOpen) {
4521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            lp.knownOpen = true;
4531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (mListener != null) {
4541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mListener.onDrawerOpened(drawerView);
4551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
4561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
4571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
4581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void dispatchOnDrawerSlide(View drawerView, float slideOffset) {
4601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (mListener != null) {
4611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mListener.onDrawerSlide(drawerView, slideOffset);
4621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
4631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
4641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void setDrawerViewOffset(View drawerView, float slideOffset) {
4661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
467b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (slideOffset == lp.onScreen) {
4681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return;
4691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
4701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
471b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        lp.onScreen = slideOffset;
4721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        dispatchOnDrawerSlide(drawerView, slideOffset);
4731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
4741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    float getDrawerViewOffset(View drawerView) {
476b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        return ((LayoutParams) drawerView.getLayoutParams()).onScreen;
4771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
4781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    int getDrawerViewGravity(View drawerView) {
4801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int gravity = ((LayoutParams) drawerView.getLayoutParams()).gravity;
4811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return GravityCompat.getAbsoluteGravity(gravity, ViewCompat.getLayoutDirection(drawerView));
4821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
4831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    boolean checkDrawerViewGravity(View drawerView, int checkFor) {
4851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int absGrav = getDrawerViewGravity(drawerView);
4861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return (absGrav & checkFor) == checkFor;
4871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
4881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4890492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    View findOpenDrawer() {
4900492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        final int childCount = getChildCount();
4910492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        for (int i = 0; i < childCount; i++) {
4920492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            final View child = getChildAt(i);
4930492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            if (((LayoutParams) child.getLayoutParams()).knownOpen) {
4940492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                return child;
4950492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            }
4960492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
4970492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        return null;
4980492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
4990492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
5001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void moveDrawerToOffset(View drawerView, float slideOffset) {
5011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final float oldOffset = getDrawerViewOffset(drawerView);
5021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int width = drawerView.getWidth();
5031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int oldPos = (int) (width * oldOffset);
5041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int newPos = (int) (width * slideOffset);
5051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int dx = newPos - oldPos;
5061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        drawerView.offsetLeftAndRight(checkDrawerViewGravity(drawerView, Gravity.LEFT) ? dx : -dx);
5081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        setDrawerViewOffset(drawerView, slideOffset);
5091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
5101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    View findDrawerWithGravity(int gravity) {
5121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
5131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
5141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
5151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childGravity = getDrawerViewGravity(child);
5161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if ((childGravity & Gravity.HORIZONTAL_GRAVITY_MASK) ==
5171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    (gravity & Gravity.HORIZONTAL_GRAVITY_MASK)) {
5181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                return child;
5191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
5201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
5211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return null;
5221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
5231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
5251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Simple gravity to string - only supports LEFT and RIGHT for debugging output.
5261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
5271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param gravity Absolute gravity value
5281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @return LEFT or RIGHT as appropriate, or a hex string
5291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
5301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    static String gravityToString(int gravity) {
5311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if ((gravity & Gravity.LEFT) == Gravity.LEFT) {
5321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return "LEFT";
5331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
5341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) {
5351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return "RIGHT";
5361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
5371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return Integer.toHexString(gravity);
5381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
5391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
54157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected void onDetachedFromWindow() {
54257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        super.onDetachedFromWindow();
54357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        mFirstLayout = true;
54457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
54557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
54657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
54757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected void onAttachedToWindow() {
54857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        super.onAttachedToWindow();
54957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        mFirstLayout = true;
55057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
55157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
55257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
5531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
5541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
5551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
5561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
5571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
5581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) {
5601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            throw new IllegalArgumentException(
5611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    "DrawerLayout must be measured with MeasureSpec.EXACTLY.");
5621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
5631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        setMeasuredDimension(widthSize, heightSize);
5651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        // Gravity value for each drawer we've seen. Only one of each permitted.
5671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        int foundDrawers = 0;
5681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
5691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
5701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
5711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (child.getVisibility() == GONE) {
5731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                continue;
5741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
5751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
57600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
57700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
5781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (isContentView(child)) {
5791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                // Content views get measured at exactly the layout's size.
58000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int contentWidthSpec = MeasureSpec.makeMeasureSpec(
58100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        widthSize - lp.leftMargin - lp.rightMargin, MeasureSpec.EXACTLY);
58200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int contentHeightSpec = MeasureSpec.makeMeasureSpec(
58300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        heightSize - lp.topMargin - lp.bottomMargin, MeasureSpec.EXACTLY);
58400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                child.measure(contentWidthSpec, contentHeightSpec);
5851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else if (isDrawerView(child)) {
5861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int childGravity =
5871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        getDrawerViewGravity(child) & Gravity.HORIZONTAL_GRAVITY_MASK;
5881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                if ((foundDrawers & childGravity) != 0) {
5891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    throw new IllegalStateException("Child drawer has absolute gravity " +
5901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                            gravityToString(childGravity) + " but this " + TAG + " already has a " +
5911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                            "drawer view along that edge");
5921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
59300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int drawerWidthSpec = getChildMeasureSpec(widthMeasureSpec,
59400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        mMinDrawerMargin + lp.leftMargin + lp.rightMargin,
59500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.width);
59600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int drawerHeightSpec = getChildMeasureSpec(heightMeasureSpec,
59700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.topMargin + lp.bottomMargin,
59800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.height);
59900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                child.measure(drawerWidthSpec, drawerHeightSpec);
6001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
6011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                throw new IllegalStateException("Child " + child + " at index " + i +
6021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        " does not have a valid layout_gravity - must be Gravity.LEFT, " +
6031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        "Gravity.RIGHT or Gravity.NO_GRAVITY");
6041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
6051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
6061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
6071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
6091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected void onLayout(boolean changed, int l, int t, int r, int b) {
610b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        mInLayout = true;
6111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
6121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
6131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
6141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (child.getVisibility() == GONE) {
6161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                continue;
6171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
6181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
61900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
62000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
6211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (isContentView(child)) {
62200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                child.layout(lp.leftMargin, lp.topMargin,
62300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.leftMargin + child.getMeasuredWidth(),
62400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.topMargin + child.getMeasuredHeight());
6251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else { // Drawer, if it wasn't onMeasure would have thrown an exception.
6261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int childWidth = child.getMeasuredWidth();
62700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int childHeight = child.getMeasuredHeight();
6281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                int childLeft;
6291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                if (checkDrawerViewGravity(child, Gravity.LEFT)) {
631b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    childLeft = -childWidth + (int) (childWidth * lp.onScreen);
6321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                } else { // Right; onMeasure checked for us.
633b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    childLeft = r - l - (int) (childWidth * lp.onScreen);
6341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
6351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
63600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK;
63700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
63800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                switch (vgrav) {
63900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    default:
64000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    case Gravity.TOP: {
64100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        child.layout(childLeft, lp.topMargin, childLeft + childWidth, childHeight);
64200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        break;
64300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    }
64400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
64500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    case Gravity.BOTTOM: {
64600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        final int height = b - t;
64700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        child.layout(childLeft,
64800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                                height - lp.bottomMargin - child.getMeasuredHeight(),
64900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                                childLeft + childWidth,
65000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                                height - lp.bottomMargin);
65100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        break;
65200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    }
65300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
65400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    case Gravity.CENTER_VERTICAL: {
65500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        final int height = b - t;
65600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        int childTop = (height - childHeight) / 2;
65700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
65800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        // Offset for margins. If things don't fit right because of
65900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        // bad measurement before, oh well.
66000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        if (childTop < lp.topMargin) {
66100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                            childTop = lp.topMargin;
66200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        } else if (childTop + childHeight > height - lp.bottomMargin) {
66300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                            childTop = height - lp.bottomMargin - childHeight;
66400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        }
66500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        child.layout(childLeft, childTop, childLeft + childWidth,
66600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                                childTop + childHeight);
66700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        break;
66800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    }
66900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                }
670b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
671b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                if (lp.onScreen == 0) {
672b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    child.setVisibility(INVISIBLE);
673b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                }
6741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
6751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
676b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        mInLayout = false;
67757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        mFirstLayout = false;
678b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
679b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
680b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    @Override
681b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public void requestLayout() {
682b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (!mInLayout) {
683b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            super.requestLayout();
684b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
6851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
6861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
6881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void computeScroll() {
6891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
6901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        float scrimOpacity = 0;
6911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
692b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final float onscreen = ((LayoutParams) getChildAt(i).getLayoutParams()).onScreen;
6931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            scrimOpacity = Math.max(scrimOpacity, onscreen);
6941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
6951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mScrimOpacity = scrimOpacity;
6961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        // "|" used on purpose; both need to run.
6981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (mLeftDragger.continueSettling(true) | mRightDragger.continueSettling(true)) {
6991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            ViewCompat.postInvalidateOnAnimation(this);
7001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
7011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
7021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
703b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    private static boolean hasOpaqueBackground(View v) {
704b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        final Drawable bg = v.getBackground();
705b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (bg != null) {
706b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            return bg.getOpacity() == PixelFormat.OPAQUE;
707b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
708b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        return false;
709b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
710b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
7111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
7121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
71300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        final int height = getHeight();
714b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        final boolean drawingContent = isContentView(child);
715b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        int clipLeft = 0, clipRight = getWidth();
716b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
7171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int restoreCount = canvas.save();
718b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (drawingContent) {
719b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int childCount = getChildCount();
720b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            for (int i = 0; i < childCount; i++) {
721b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                final View v = getChildAt(i);
722b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                if (v == child || v.getVisibility() != VISIBLE ||
72300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        !hasOpaqueBackground(v) || !isDrawerView(v) ||
72400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        v.getHeight() < height) {
725b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    continue;
726b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                }
727b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
728b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                if (checkDrawerViewGravity(v, Gravity.LEFT)) {
729b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    final int vright = v.getRight();
730b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    if (vright > clipLeft) clipLeft = vright;
731b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                } else {
732b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    final int vleft = v.getLeft();
733b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    if (vleft < clipRight) clipRight = vleft;
734b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                }
735b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            }
736b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            canvas.clipRect(clipLeft, 0, clipRight, getHeight());
737b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
7381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final boolean result = super.drawChild(canvas, child, drawingTime);
7391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        canvas.restoreToCount(restoreCount);
740b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
741b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (mScrimOpacity > 0 && drawingContent) {
7421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int baseAlpha = (mScrimColor & 0xff000000) >>> 24;
7431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int imag = (int) (baseAlpha * mScrimOpacity);
7441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int color = imag << 24 | (mScrimColor & 0xffffff);
7451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mScrimPaint.setColor(color);
7461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
747b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            canvas.drawRect(clipLeft, 0, clipRight, getHeight(), mScrimPaint);
748b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        } else if (mShadowLeft != null && checkDrawerViewGravity(child, Gravity.LEFT)) {
749b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int shadowWidth = mShadowLeft.getIntrinsicWidth();
750b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int childRight = child.getRight();
751ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            final int drawerPeekDistance = mLeftDragger.getEdgeSize();
752b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final float alpha =
753ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                    Math.max(0, Math.min((float) childRight / drawerPeekDistance, 1.f));
754b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowLeft.setBounds(childRight, child.getTop(),
755b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    childRight + shadowWidth, child.getBottom());
756b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowLeft.setAlpha((int) (0xff * alpha));
757b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowLeft.draw(canvas);
758b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        } else if (mShadowRight != null && checkDrawerViewGravity(child, Gravity.RIGHT)) {
759b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int shadowWidth = mShadowRight.getIntrinsicWidth();
760b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int childLeft = child.getLeft();
761b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int showing = getWidth() - childLeft;
762ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            final int drawerPeekDistance = mRightDragger.getEdgeSize();
763b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final float alpha =
764ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                    Math.max(0, Math.min((float) showing / drawerPeekDistance, 1.f));
765b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowRight.setBounds(childLeft - shadowWidth, child.getTop(),
766b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    childLeft, child.getBottom());
767b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowRight.setAlpha((int) (0xff * alpha));
768b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowRight.draw(canvas);
7691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
7701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return result;
7711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
7721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    boolean isContentView(View child) {
7741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return ((LayoutParams) child.getLayoutParams()).gravity == Gravity.NO_GRAVITY;
7751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
7761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    boolean isDrawerView(View child) {
7781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int gravity = ((LayoutParams) child.getLayoutParams()).gravity;
7791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int absGravity = GravityCompat.getAbsoluteGravity(gravity,
7801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                ViewCompat.getLayoutDirection(child));
7811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return (absGravity & (Gravity.LEFT | Gravity.RIGHT)) != 0;
7821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
7831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
7851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public boolean onInterceptTouchEvent(MotionEvent ev) {
7861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int action = MotionEventCompat.getActionMasked(ev);
7871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        // "|" used deliberately here; both methods should be invoked.
7891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final boolean interceptForDrag = mLeftDragger.shouldInterceptTouchEvent(ev) |
7901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mRightDragger.shouldInterceptTouchEvent(ev);
7911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean interceptForTap = false;
7931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        switch (action) {
7951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_DOWN: {
7961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float x = ev.getX();
7971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float y = ev.getY();
7981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionX = x;
7991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionY = y;
8001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                if (mScrimOpacity > 0 &&
8011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        isContentView(mLeftDragger.findTopChildUnder((int) x, (int) y))) {
8021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    interceptForTap = true;
8031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
8041732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
805cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                mChildrenCanceledTouch = false;
8061732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                break;
8071732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            }
8081732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
8091732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            case MotionEvent.ACTION_MOVE: {
8101732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                // If we cross the touch slop, don't perform the delayed peek for an edge touch.
8111732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                if (mLeftDragger.checkTouchSlop(ViewDragHelper.DIRECTION_ALL)) {
8121732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                    mLeftCallback.removeCallbacks();
8131732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                    mRightCallback.removeCallbacks();
8141732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                }
8151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
8161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
8171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_CANCEL:
8191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_UP: {
8201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawers(true);
8211732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
822cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                mChildrenCanceledTouch = false;
8231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
8241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
8251732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
826cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell        return interceptForDrag || interceptForTap || hasPeekingDrawer() || mChildrenCanceledTouch;
8271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
8281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
8301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public boolean onTouchEvent(MotionEvent ev) {
8311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mLeftDragger.processTouchEvent(ev);
8321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mRightDragger.processTouchEvent(ev);
8331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int action = ev.getAction();
8351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean wantTouchEvents = true;
8361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        switch (action & MotionEventCompat.ACTION_MASK) {
8381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_DOWN: {
8391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float x = ev.getX();
8401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float y = ev.getY();
8411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionX = x;
8421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionY = y;
8431732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
844cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                mChildrenCanceledTouch = false;
8451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
8461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
8471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_UP: {
8491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float x = ev.getX();
8501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float y = ev.getY();
8511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                boolean peekingOnly = true;
8528bc268e9c40e4ae375a0d65dc1293dccc541186fAdam Powell                final View touchedView = mLeftDragger.findTopChildUnder((int) x, (int) y);
8538bc268e9c40e4ae375a0d65dc1293dccc541186fAdam Powell                if (touchedView != null && isContentView(touchedView)) {
8541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    final float dx = x - mInitialMotionX;
8551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    final float dy = y - mInitialMotionY;
8561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    final int slop = mLeftDragger.getTouchSlop();
8571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    if (dx * dx + dy * dy < slop * slop) {
8580492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                        // Taps close a dimmed open drawer but only if it isn't locked open.
8590492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                        final View openDrawer = findOpenDrawer();
8600492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                        if (openDrawer != null) {
8610492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                            peekingOnly = getDrawerLockMode(openDrawer) == LOCK_MODE_LOCKED_OPEN;
8620492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                        }
8631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    }
8641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
8651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawers(peekingOnly);
8661732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
8671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
8681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
8691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_CANCEL: {
8711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawers(true);
8721732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
873cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                mChildrenCanceledTouch = false;
8741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
8751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
8761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
8771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return wantTouchEvents;
8791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
8801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
881ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
8821732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        if (!mLeftDragger.isEdgeTouched(ViewDragHelper.EDGE_LEFT) &&
8831732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                !mRightDragger.isEdgeTouched(ViewDragHelper.EDGE_RIGHT)) {
8841732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            // If we have an edge touch we want to skip this and track it for later instead.
8851732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            super.requestDisallowInterceptTouchEvent(disallowIntercept);
8861732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        }
8871732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mDisallowInterceptRequested = disallowIntercept;
888ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        if (disallowIntercept) {
889ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            closeDrawers(true);
890ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        }
891ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    }
892ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell
8931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
8941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Close all currently open drawer views by animating them out of view.
8951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
8961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void closeDrawers() {
8971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        closeDrawers(false);
8981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
8991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void closeDrawers(boolean peekingOnly) {
9011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean needsInvalidate = false;
9021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
9031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
9041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
9051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
9061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (!isDrawerView(child) || (peekingOnly && !lp.isPeeking)) {
9081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                continue;
9091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
9101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childWidth = child.getWidth();
9121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (checkDrawerViewGravity(child, Gravity.LEFT)) {
9141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                needsInvalidate |= mLeftDragger.smoothSlideViewTo(child,
9151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        -childWidth, child.getTop());
9161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
9171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                needsInvalidate |= mRightDragger.smoothSlideViewTo(child,
9181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        getWidth(), child.getTop());
9191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
9201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            lp.isPeeking = false;
9221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9241732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mLeftCallback.removeCallbacks();
9251732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mRightCallback.removeCallbacks();
9261732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
9271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (needsInvalidate) {
9281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            invalidate();
9291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
9311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
9331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Open the specified drawer view by animating it into view.
9341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
9351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param drawerView Drawer view to open
9361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
9371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void openDrawer(View drawerView) {
9381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (!isDrawerView(drawerView)) {
9391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            throw new IllegalArgumentException("View " + drawerView + " is not a sliding drawer");
9401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
94257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        if (mFirstLayout) {
94357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
94457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            lp.onScreen = 1.f;
94557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            lp.knownOpen = true;
9461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        } else {
94757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            if (checkDrawerViewGravity(drawerView, Gravity.LEFT)) {
94857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mLeftDragger.smoothSlideViewTo(drawerView, 0, drawerView.getTop());
94957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            } else {
95057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mRightDragger.smoothSlideViewTo(drawerView, getWidth() - drawerView.getWidth(),
95157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                        drawerView.getTop());
95257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
9531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        invalidate();
9551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
9561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
9581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Open the specified drawer by animating it out of view.
9591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
9601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param gravity Gravity.LEFT to move the left drawer or Gravity.RIGHT for the right.
9611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *                GravityCompat.START or GravityCompat.END may also be used.
9621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
9631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void openDrawer(int gravity) {
9641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int absGravity = GravityCompat.getAbsoluteGravity(gravity,
9651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                ViewCompat.getLayoutDirection(this));
9661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final View drawerView = findDrawerWithGravity(absGravity);
9671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (drawerView == null) {
9691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            throw new IllegalArgumentException("No drawer view found with absolute gravity " +
9701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    gravityToString(absGravity));
9711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        openDrawer(drawerView);
9731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
9741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
9761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Close the specified drawer view by animating it into view.
9771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
9781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param drawerView Drawer view to close
9791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
9801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void closeDrawer(View drawerView) {
9811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (!isDrawerView(drawerView)) {
9821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            throw new IllegalArgumentException("View " + drawerView + " is not a sliding drawer");
9831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
98557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        if (mFirstLayout) {
98657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
98757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            lp.onScreen = 0.f;
98857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            lp.knownOpen = false;
9891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        } else {
99057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            if (checkDrawerViewGravity(drawerView, Gravity.LEFT)) {
99157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mLeftDragger.smoothSlideViewTo(drawerView, -drawerView.getWidth(),
99257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                        drawerView.getTop());
99357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            } else {
99457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mRightDragger.smoothSlideViewTo(drawerView, getWidth(), drawerView.getTop());
99557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
9961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        invalidate();
9981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
9991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
10011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Close the specified drawer by animating it out of view.
10021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
10031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param gravity Gravity.LEFT to move the left drawer or Gravity.RIGHT for the right.
10041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *                GravityCompat.START or GravityCompat.END may also be used.
10051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
10061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void closeDrawer(int gravity) {
10071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int absGravity = GravityCompat.getAbsoluteGravity(gravity,
10081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                ViewCompat.getLayoutDirection(this));
10091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final View drawerView = findDrawerWithGravity(absGravity);
10101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (drawerView == null) {
10121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            throw new IllegalArgumentException("No drawer view found with absolute gravity " +
10131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    gravityToString(absGravity));
10141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
10151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        closeDrawer(drawerView);
10161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
10171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1018b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
1019b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Check if the given drawer view is currently in an open state.
1020b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * To be considered "open" the drawer must have settled into its fully
1021b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * visible state. To check for partial visibility use
1022b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * {@link #isDrawerVisible(android.view.View)}.
1023b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
1024b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param drawer Drawer view to check
1025b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @return true if the given drawer view is in an open state
1026b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @see #isDrawerVisible(android.view.View)
1027b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
1028b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public boolean isDrawerOpen(View drawer) {
1029b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (!isDrawerView(drawer)) {
1030b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            throw new IllegalArgumentException("View " + drawer + " is not a drawer");
1031b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
1032b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        return ((LayoutParams) drawer.getLayoutParams()).knownOpen;
1033b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
1034b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
1035b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
1036b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Check if a given drawer view is currently visible on-screen. The drawer
1037b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * may be only peeking onto the screen, fully extended, or anywhere inbetween.
1038b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
1039b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param drawer Drawer view to check
1040b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @return true if the given drawer is visible on-screen
1041b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @see #isDrawerOpen(android.view.View)
1042b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
1043b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public boolean isDrawerVisible(View drawer) {
1044b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (!isDrawerView(drawer)) {
1045b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            throw new IllegalArgumentException("View " + drawer + " is not a drawer");
1046b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
1047b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        return ((LayoutParams) drawer.getLayoutParams()).onScreen > 0;
1048b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
1049b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
1050ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    private boolean hasPeekingDrawer() {
1051ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        final int childCount = getChildCount();
1052ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        for (int i = 0; i < childCount; i++) {
1053ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            final LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams();
1054ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            if (lp.isPeeking) {
1055ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                return true;
1056ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            }
1057ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        }
1058ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        return false;
1059ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    }
1060ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell
10611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
10621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
10631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
10641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
10651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
10671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
10681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return p instanceof LayoutParams
10691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                ? new LayoutParams((LayoutParams) p)
107000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                : p instanceof ViewGroup.MarginLayoutParams
107100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                ? new LayoutParams((MarginLayoutParams) p)
10721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                : new LayoutParams(p);
10731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
10741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
10761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
10771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return p instanceof LayoutParams && super.checkLayoutParams(p);
10781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
10791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
10811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
10821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return new LayoutParams(getContext(), attrs);
10831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
10841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1085791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    private boolean hasVisibleDrawer() {
10860492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        return findVisibleDrawer() != null;
10870492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
10880492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
10890492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    private View findVisibleDrawer() {
1090791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        final int childCount = getChildCount();
1091791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        for (int i = 0; i < childCount; i++) {
1092791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            final View child = getChildAt(i);
1093791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            if (isDrawerView(child) && isDrawerVisible(child)) {
10940492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                return child;
1095791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            }
1096791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        }
10970492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        return null;
1098791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    }
1099791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
1100cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell    void cancelChildViewTouch() {
1101cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell        // Cancel child touches
1102cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell        if (!mChildrenCanceledTouch) {
1103cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            final long now = SystemClock.uptimeMillis();
1104cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            final MotionEvent cancelEvent = MotionEvent.obtain(now, now,
1105cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                    MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
1106cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            final int childCount = getChildCount();
1107cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            for (int i = 0; i < childCount; i++) {
1108cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                getChildAt(i).dispatchTouchEvent(cancelEvent);
1109cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            }
1110cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            cancelEvent.recycle();
1111cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            mChildrenCanceledTouch = true;
1112cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell        }
1113cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell    }
1114cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell
1115791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    @Override
1116791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    public boolean onKeyDown(int keyCode, KeyEvent event) {
1117791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        if (keyCode == KeyEvent.KEYCODE_BACK && hasVisibleDrawer()) {
1118791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            KeyEventCompat.startTracking(event);
1119791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            return true;
1120791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        }
1121791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        return super.onKeyDown(keyCode, event);
1122791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    }
1123791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
1124791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    @Override
1125791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    public boolean onKeyUp(int keyCode, KeyEvent event) {
11260492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        if (keyCode == KeyEvent.KEYCODE_BACK) {
11270492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            final View visibleDrawer = findVisibleDrawer();
11280492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            if (visibleDrawer != null && getDrawerLockMode(visibleDrawer) == LOCK_MODE_UNLOCKED) {
11290492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                closeDrawers();
11300492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            }
11310492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            return visibleDrawer != null;
1132791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        }
1133791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        return super.onKeyUp(keyCode, event);
1134791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    }
1135791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
113657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
113757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected void onRestoreInstanceState(Parcelable state) {
113857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        final SavedState ss = (SavedState) state;
113957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        super.onRestoreInstanceState(ss.getSuperState());
114057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
114157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        if (ss.openDrawerGravity != Gravity.NO_GRAVITY) {
114257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            final View toOpen = findDrawerWithGravity(ss.openDrawerGravity);
114357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            if (toOpen != null) {
114457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                openDrawer(toOpen);
114557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
114657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
11478e01d24e718d603974182cd48f648369c07edec1Adam Powell
11488e01d24e718d603974182cd48f648369c07edec1Adam Powell        setDrawerLockMode(ss.lockModeLeft, Gravity.LEFT);
11498e01d24e718d603974182cd48f648369c07edec1Adam Powell        setDrawerLockMode(ss.lockModeRight, Gravity.RIGHT);
115057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
115157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
115257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
115357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected Parcelable onSaveInstanceState() {
115457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        final Parcelable superState = super.onSaveInstanceState();
115557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
115657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        final SavedState ss = new SavedState(superState);
115757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
115857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        final int childCount = getChildCount();
115957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        for (int i = 0; i < childCount; i++) {
116057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            final View child = getChildAt(i);
116157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            if (!isDrawerView(child)) {
116257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                continue;
116357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
116457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
116557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
116657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            if (lp.knownOpen) {
116757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                ss.openDrawerGravity = lp.gravity;
116857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                // Only one drawer can be open at a time.
116957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                break;
117057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
117157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
117257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
11738e01d24e718d603974182cd48f648369c07edec1Adam Powell        ss.lockModeLeft = mLockModeLeft;
11748e01d24e718d603974182cd48f648369c07edec1Adam Powell        ss.lockModeRight = mLockModeRight;
11758e01d24e718d603974182cd48f648369c07edec1Adam Powell
117657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        return ss;
117757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
117857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
117957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    /**
118057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell     * State persisted across instances
118157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell     */
118257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected static class SavedState extends BaseSavedState {
118357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        int openDrawerGravity = Gravity.NO_GRAVITY;
11848e01d24e718d603974182cd48f648369c07edec1Adam Powell        int lockModeLeft = LOCK_MODE_UNLOCKED;
11858e01d24e718d603974182cd48f648369c07edec1Adam Powell        int lockModeRight = LOCK_MODE_UNLOCKED;
118657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
118757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        public SavedState(Parcel in) {
118857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            super(in);
118957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            openDrawerGravity = in.readInt();
119057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
119157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
119257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        public SavedState(Parcelable superState) {
119357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            super(superState);
119457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
119557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
119657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        @Override
119757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        public void writeToParcel(Parcel dest, int flags) {
119857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            super.writeToParcel(dest, flags);
119957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            dest.writeInt(openDrawerGravity);
120057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
120157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
120257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        public static final Parcelable.Creator<SavedState> CREATOR =
120357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                new Parcelable.Creator<SavedState>() {
120457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            @Override
120557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            public SavedState createFromParcel(Parcel source) {
120657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                return new SavedState(source);
120757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
120857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
120957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            @Override
121057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            public SavedState[] newArray(int size) {
121157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                return new SavedState[size];
121257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
121357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        };
121457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
121557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
12161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private class ViewDragCallback extends ViewDragHelper.Callback {
12171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        private final int mGravity;
12181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        private ViewDragHelper mDragger;
12191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12201732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        private final Runnable mPeekRunnable = new Runnable() {
12211732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            @Override public void run() {
12221732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                peekDrawer();
12231732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            }
12241732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        };
12251732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
12261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public ViewDragCallback(int gravity) {
12271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mGravity = gravity;
12281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
12291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void setDragger(ViewDragHelper dragger) {
12311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mDragger = dragger;
12321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
12331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12341732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        public void removeCallbacks() {
12351732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            DrawerLayout.this.removeCallbacks(mPeekRunnable);
12361732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        }
12371732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
12381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
12391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public boolean tryCaptureView(View child, int pointerId) {
12401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // Only capture views where the gravity matches what we're looking for.
12411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // This lets us use two ViewDragHelpers, one for each side drawer.
12420492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            return isDrawerView(child) && checkDrawerViewGravity(child, mGravity) &&
12430492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                    getDrawerLockMode(child) == LOCK_MODE_UNLOCKED;
12441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
12451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
12471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewDragStateChanged(int state) {
1248b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            updateDrawerState(mGravity, state, mDragger.getCapturedView());
12491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
12501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
12521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
12531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            float offset;
12541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childWidth = changedView.getWidth();
12551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // This reverses the positioning shown in onLayout.
12571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (checkDrawerViewGravity(changedView, Gravity.LEFT)) {
12581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                offset = (float) (childWidth + left) / childWidth;
12591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
12601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int width = getWidth();
12611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                offset = (float) (width - left) / childWidth;
12621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
12631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            setDrawerViewOffset(changedView, offset);
1264b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            changedView.setVisibility(offset == 0 ? INVISIBLE : VISIBLE);
12651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            invalidate();
12661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
12671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
12691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewCaptured(View capturedChild, int activePointerId) {
12701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final LayoutParams lp = (LayoutParams) capturedChild.getLayoutParams();
12711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            lp.isPeeking = false;
12721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            closeOtherDrawer();
12741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
12751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        private void closeOtherDrawer() {
12771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int otherGrav = mGravity == Gravity.LEFT ? Gravity.RIGHT : Gravity.LEFT;
12781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View toClose = findDrawerWithGravity(otherGrav);
12791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (toClose != null) {
12801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawer(toClose);
12811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
12821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
12831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
12851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewReleased(View releasedChild, float xvel, float yvel) {
12861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // Offset is how open the drawer is, therefore left/right values
12871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // are reversed from one another.
12881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final float offset = getDrawerViewOffset(releasedChild);
12891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childWidth = releasedChild.getWidth();
12901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            int left;
12921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (checkDrawerViewGravity(releasedChild, Gravity.LEFT)) {
12931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                left = xvel > 0 || xvel == 0 && offset > 0.5f ? 0 : -childWidth;
12941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
12951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int width = getWidth();
12961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                left = xvel < 0 || xvel == 0 && offset < 0.5f ? width - childWidth : width;
12971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
12981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mDragger.settleCapturedViewAt(left, releasedChild.getTop());
13001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            invalidate();
13011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
13021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
13031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
13041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onEdgeTouched(int edgeFlags, int pointerId) {
13051732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            postDelayed(mPeekRunnable, PEEK_DELAY);
13061732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        }
13071732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
13081732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        private void peekDrawer() {
13091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View toCapture;
13101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childLeft;
1311ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            final int peekDistance = mDragger.getEdgeSize();
13121732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            final boolean leftEdge = mGravity == Gravity.LEFT;
1313b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            if (leftEdge) {
13141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.LEFT);
1315ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                childLeft = (toCapture != null ? -toCapture.getWidth() : 0) + peekDistance;
13161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
13171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.RIGHT);
1318ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                childLeft = getWidth() - peekDistance;
13191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
13200492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            // Only peek if it would mean making the drawer more visible and the drawer isn't locked
1321b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            if (toCapture != null && ((leftEdge && toCapture.getLeft() < childLeft) ||
13220492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                    (!leftEdge && toCapture.getLeft() > childLeft)) &&
13230492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                    getDrawerLockMode(toCapture) == LOCK_MODE_UNLOCKED) {
1324b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                final LayoutParams lp = (LayoutParams) toCapture.getLayoutParams();
13251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mDragger.smoothSlideViewTo(toCapture, childLeft, toCapture.getTop());
1326b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                lp.isPeeking = true;
13271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                invalidate();
13281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
13291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeOtherDrawer();
1330cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell
1331cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                cancelChildViewTouch();
13321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
13331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
13341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
13351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
1336ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        public boolean onEdgeLock(int edgeFlags) {
1337ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            if (ALLOW_EDGE_LOCK) {
1338ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                final View drawer = findDrawerWithGravity(mGravity);
1339ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                if (drawer != null && !isDrawerOpen(drawer)) {
1340ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                    closeDrawer(drawer);
1341ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                }
1342ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                return true;
1343acc82321ad119706485db342eaa12b225fa9b667Adam Powell            }
1344ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            return false;
1345acc82321ad119706485db342eaa12b225fa9b667Adam Powell        }
1346acc82321ad119706485db342eaa12b225fa9b667Adam Powell
1347acc82321ad119706485db342eaa12b225fa9b667Adam Powell        @Override
13481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onEdgeDragStarted(int edgeFlags, int pointerId) {
13491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View toCapture;
13501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if ((edgeFlags & ViewDragHelper.EDGE_LEFT) == ViewDragHelper.EDGE_LEFT) {
13511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.LEFT);
13521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
13531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.RIGHT);
13541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
13551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
13560492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            if (toCapture != null && getDrawerLockMode(toCapture) == LOCK_MODE_UNLOCKED) {
13571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mDragger.captureChildView(toCapture, pointerId);
13581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
13591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
13601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
13611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
13621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public int getViewHorizontalDragRange(View child) {
13631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return child.getWidth();
13641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
13651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
13661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
13671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public int clampViewPositionHorizontal(View child, int left, int dx) {
13681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (checkDrawerViewGravity(child, Gravity.LEFT)) {
13691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                return Math.max(-child.getWidth(), Math.min(left, 0));
13701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
13711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int width = getWidth();
13721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                return Math.max(width - child.getWidth(), Math.min(left, width));
13731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
13741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
137500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
137600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        @Override
137700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        public int clampViewPositionVertical(View child, int top, int dy) {
137800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell            return child.getTop();
137900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        }
13801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
13811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
138200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell    public static class LayoutParams extends ViewGroup.MarginLayoutParams {
13831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
13841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public int gravity = Gravity.NO_GRAVITY;
1385b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        float onScreen;
13861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean isPeeking;
13871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean knownOpen;
13881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
13891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(Context c, AttributeSet attrs) {
13901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(c, attrs);
13911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
13921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final TypedArray a = c.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
13931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this.gravity = a.getInt(0, Gravity.NO_GRAVITY);
13941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            a.recycle();
13951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
13961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
13971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(int width, int height) {
13981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(width, height);
13991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
14001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(int width, int height, int gravity) {
14021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this(width, height);
14031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this.gravity = gravity;
14041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
14051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(LayoutParams source) {
14071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(source);
14081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this.gravity = source.gravity;
14091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
14101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(ViewGroup.LayoutParams source) {
14121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(source);
14131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
141400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
141500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        public LayoutParams(ViewGroup.MarginLayoutParams source) {
141600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell            super(source);
141700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        }
14181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
14191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell}
1420