DrawerLayout.java revision 12ba769d9e9b121829c69daf0f6350e808028a6a
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;
253cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powellimport android.graphics.Rect;
26b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powellimport android.graphics.drawable.Drawable;
2757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powellimport android.os.Parcel;
2857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powellimport android.os.Parcelable;
29cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powellimport android.os.SystemClock;
307d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powellimport android.support.v4.view.AccessibilityDelegateCompat;
311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.support.v4.view.GravityCompat;
32791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powellimport android.support.v4.view.KeyEventCompat;
331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.support.v4.view.MotionEventCompat;
341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.support.v4.view.ViewCompat;
351b8262b87426b2f766b40d6ab4eaeac296d5c2feAdam Powellimport android.support.v4.view.ViewGroupCompat;
367d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powellimport android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.util.AttributeSet;
381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.Gravity;
39791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powellimport android.view.KeyEvent;
401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.MotionEvent;
411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.View;
421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.ViewGroup;
4312ba769d9e9b121829c69daf0f6350e808028a6aAlan Viveretteimport android.view.ViewGroup.LayoutParams;
443cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powellimport android.view.ViewParent;
457d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powellimport android.view.accessibility.AccessibilityEvent;
461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
47526ba1382e61845ef23bf27d300883dea0966af5Alan Viveretteimport java.util.List;
48526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell/**
501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * DrawerLayout acts as a top-level container for window content that allows for
511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * interactive "drawer" views to be pulled out from the edge of the window.
521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell *
531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * <p>Drawer positioning and layout is controlled using the <code>android:layout_gravity</code>
5409c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * attribute on child views corresponding to which side of the view you want the drawer
5509c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * to emerge from: left or right. (Or start/end on platform versions that support layout direction.)
5609c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * </p>
5709c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell *
5809c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * <p>To use a DrawerLayout, position your primary content view as the first child with
5909c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * a width and height of <code>match_parent</code>. Add drawers as child views after the main
6009c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * content view and set the <code>layout_gravity</code> appropriately. Drawers commonly use
6109c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * <code>match_parent</code> for height with a fixed width.</p>
6209c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell *
6309c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * <p>{@link DrawerListener} can be used to monitor the state and motion of drawer views.
6409c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * Avoid performing expensive operations such as layout during animation as it can cause
6509c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * stuttering; try to perform expensive operations during the {@link #STATE_IDLE} state.
6609c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * {@link SimpleDrawerListener} offers default/no-op implementations of each callback method.</p>
671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell *
681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * <p>As per the Android Design guide, any drawers positioned to the left/start should
691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * always contain content for navigating around the application, whereas any drawers
701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * positioned to the right/end should always contain actions to take on the current content.
711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * This preserves the same navigation left, actions right structure present in the Action Bar
721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * and elsewhere.</p>
731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */
741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellpublic class DrawerLayout extends ViewGroup {
751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final String TAG = "DrawerLayout";
761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Indicates that any drawers are in an idle, settled state. No animation is in progress.
791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public static final int STATE_IDLE = ViewDragHelper.STATE_IDLE;
811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Indicates that a drawer is currently being dragged by the user.
841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public static final int STATE_DRAGGING = ViewDragHelper.STATE_DRAGGING;
861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Indicates that a drawer is in the process of settling to a final position.
891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public static final int STATE_SETTLING = ViewDragHelper.STATE_SETTLING;
911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
920492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
930492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * The drawer is unlocked.
940492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
950492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public static final int LOCK_MODE_UNLOCKED = 0;
960492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
970492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
980492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * The drawer is locked closed. The user may not open it, though
990492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * the app may open it programmatically.
1000492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
1010492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public static final int LOCK_MODE_LOCKED_CLOSED = 1;
1020492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
1030492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
1040492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * The drawer is locked open. The user may not close it, though the app
1050492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * may close it programmatically.
1060492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
1070492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public static final int LOCK_MODE_LOCKED_OPEN = 2;
1080492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
1091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final int MIN_DRAWER_MARGIN = 64; // dp
1101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final int DEFAULT_SCRIM_COLOR = 0x99000000;
1121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
113ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    /**
1141732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell     * Length of time to delay before peeking the drawer.
1151732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell     */
1161732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    private static final int PEEK_DELAY = 160; // ms
1171732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
1181732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    /**
11979f95ce3e660d267831067e514ff455156c4381fAdam Powell     * Minimum velocity that will be detected as a fling
12079f95ce3e660d267831067e514ff455156c4381fAdam Powell     */
12179f95ce3e660d267831067e514ff455156c4381fAdam Powell    private static final int MIN_FLING_VELOCITY = 400; // dips per second
12279f95ce3e660d267831067e514ff455156c4381fAdam Powell
12379f95ce3e660d267831067e514ff455156c4381fAdam Powell    /**
124ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell     * Experimental feature.
125ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell     */
126ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    private static final boolean ALLOW_EDGE_LOCK = false;
127ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell
12886559d86173efb890a8edf48d935cfebfaccf049Adam Powell    private static final boolean CHILDREN_DISALLOW_INTERCEPT = true;
12986559d86173efb890a8edf48d935cfebfaccf049Adam Powell
13086559d86173efb890a8edf48d935cfebfaccf049Adam Powell    private static final float TOUCH_SLOP_SENSITIVITY = 1.f;
13186559d86173efb890a8edf48d935cfebfaccf049Adam Powell
1321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final int[] LAYOUT_ATTRS = new int[] {
1331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            android.R.attr.layout_gravity
1341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    };
1351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
13612ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    private final ChildAccessibilityDelegate mChildAccessibilityDelegate =
13712ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            new ChildAccessibilityDelegate();
13812ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
1391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private int mMinDrawerMargin;
1401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private int mScrimColor = DEFAULT_SCRIM_COLOR;
1421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private float mScrimOpacity;
1431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private Paint mScrimPaint = new Paint();
1441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private final ViewDragHelper mLeftDragger;
1461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private final ViewDragHelper mRightDragger;
1471732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    private final ViewDragCallback mLeftCallback;
1481732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    private final ViewDragCallback mRightCallback;
1491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private int mDrawerState;
150b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    private boolean mInLayout;
15157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    private boolean mFirstLayout = true;
1520492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    private int mLockModeLeft;
1530492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    private int mLockModeRight;
1541732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    private boolean mDisallowInterceptRequested;
155cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell    private boolean mChildrenCanceledTouch;
1561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private DrawerListener mListener;
1581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private float mInitialMotionX;
1601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private float mInitialMotionY;
1611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
162b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    private Drawable mShadowLeft;
163b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    private Drawable mShadowRight;
164b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
165526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    private CharSequence mTitleLeft;
166526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    private CharSequence mTitleRight;
167526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
1681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
1691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Listener for monitoring events about drawers.
1701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
1711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public interface DrawerListener {
1721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
1731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when a drawer's position changes.
1741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param drawerView The child view that was moved
1751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param slideOffset The new offset of this drawer within its range, from 0-1
1761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
1771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onDrawerSlide(View drawerView, float slideOffset);
1781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
1801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when a drawer has settled in a completely open state.
1811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * The drawer is interactive at this point.
1821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         *
1831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param drawerView Drawer view that is now open
1841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
1851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onDrawerOpened(View drawerView);
1861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
1881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when a drawer has settled in a completely closed state.
1891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         *
1901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param drawerView Drawer view that is now closed
1911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
1921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onDrawerClosed(View drawerView);
1931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
1951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when the drawer motion state changes. The new state will
1961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * be one of {@link #STATE_IDLE}, {@link #STATE_DRAGGING} or {@link #STATE_SETTLING}.
1971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         *
1981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param newState The new drawer motion state
1991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
2001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onDrawerStateChanged(int newState);
2011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
2021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
203b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
204b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Stub/no-op implementations of all methods of {@link DrawerListener}.
205b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Override this if you only care about a few of the available callback methods.
206b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
207b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public static abstract class SimpleDrawerListener implements DrawerListener {
208b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
209b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerSlide(View drawerView, float slideOffset) {
210b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
211b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
212b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
213b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerOpened(View drawerView) {
214b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
215b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
216b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
217b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerClosed(View drawerView) {
218b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
219b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
220b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
221b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerStateChanged(int newState) {
222b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
223b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
224b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
2251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public DrawerLayout(Context context) {
2261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        this(context, null);
2271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
2281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public DrawerLayout(Context context, AttributeSet attrs) {
2301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        this(context, attrs, 0);
2311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
2321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public DrawerLayout(Context context, AttributeSet attrs, int defStyle) {
2341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        super(context, attrs, defStyle);
2351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final float density = getResources().getDisplayMetrics().density;
2371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mMinDrawerMargin = (int) (MIN_DRAWER_MARGIN * density + 0.5f);
23879f95ce3e660d267831067e514ff455156c4381fAdam Powell        final float minVel = MIN_FLING_VELOCITY * density;
2391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2401732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mLeftCallback = new ViewDragCallback(Gravity.LEFT);
2411732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mRightCallback = new ViewDragCallback(Gravity.RIGHT);
2421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
24386559d86173efb890a8edf48d935cfebfaccf049Adam Powell        mLeftDragger = ViewDragHelper.create(this, TOUCH_SLOP_SENSITIVITY, mLeftCallback);
2441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mLeftDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
24579f95ce3e660d267831067e514ff455156c4381fAdam Powell        mLeftDragger.setMinVelocity(minVel);
2461732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mLeftCallback.setDragger(mLeftDragger);
2471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
24886559d86173efb890a8edf48d935cfebfaccf049Adam Powell        mRightDragger = ViewDragHelper.create(this, TOUCH_SLOP_SENSITIVITY, mRightCallback);
2491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mRightDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_RIGHT);
25079f95ce3e660d267831067e514ff455156c4381fAdam Powell        mRightDragger.setMinVelocity(minVel);
2511732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mRightCallback.setDragger(mRightDragger);
252791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
253791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        // So that we can catch the back button
254791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        setFocusableInTouchMode(true);
2557d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell
25612ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        ViewCompat.setImportantForAccessibility(this,
25712ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
25812ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
2597d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell        ViewCompat.setAccessibilityDelegate(this, new AccessibilityDelegate());
2601b8262b87426b2f766b40d6ab4eaeac296d5c2feAdam Powell        ViewGroupCompat.setMotionEventSplittingEnabled(this, false);
2611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
2621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
264b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Set a simple drawable used for the left or right shadow.
265b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * The drawable provided must have a nonzero intrinsic width.
266b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
267b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param shadowDrawable Shadow drawable to use at the edge of a drawer
268b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param gravity Which drawer the shadow should apply to
269b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
270b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public void setDrawerShadow(Drawable shadowDrawable, int gravity) {
271b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        /*
272b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         * TODO Someone someday might want to set more complex drawables here.
273b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         * They're probably nuts, but we might want to consider registering callbacks,
274b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         * setting states, etc. properly.
275b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         */
276b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
277b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        final int absGravity = GravityCompat.getAbsoluteGravity(gravity,
278b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                ViewCompat.getLayoutDirection(this));
279b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if ((absGravity & Gravity.LEFT) == Gravity.LEFT) {
280b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowLeft = shadowDrawable;
281b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            invalidate();
282b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
283b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if ((absGravity & Gravity.RIGHT) == Gravity.RIGHT) {
284b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowRight = shadowDrawable;
285b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            invalidate();
286b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
287b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
288b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
289b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
290b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Set a simple drawable used for the left or right shadow.
291b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * The drawable provided must have a nonzero intrinsic width.
292b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
293b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param resId Resource id of a shadow drawable to use at the edge of a drawer
294b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param gravity Which drawer the shadow should apply to
295b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
296b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public void setDrawerShadow(int resId, int gravity) {
297b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        setDrawerShadow(getResources().getDrawable(resId), gravity);
298b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
299b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
300b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
301fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell     * Set a color to use for the scrim that obscures primary content while a drawer is open.
302fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell     *
303fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell     * @param color Color to use in 0xAARRGGBB format.
304fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell     */
305fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell    public void setScrimColor(int color) {
306fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell        mScrimColor = color;
307fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell        invalidate();
308fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell    }
309fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell
310fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell    /**
3111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Set a listener to be notified of drawer events.
3121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
3131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param listener Listener to notify when drawer events occur
3141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @see DrawerListener
3151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
3161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void setDrawerListener(DrawerListener listener) {
3171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mListener = listener;
3181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
3191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
3210492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Enable or disable interaction with all drawers.
3220492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
3230492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>This allows the application to restrict the user's ability to open or close
3240492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * any drawer within this layout. DrawerLayout will still respond to calls to
3250492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * {@link #openDrawer(int)}, {@link #closeDrawer(int)} and friends if a drawer is locked.</p>
3260492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
3270492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>Locking drawers open or closed will implicitly open or close
3280492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * any drawers as appropriate.</p>
3290492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
3300492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param lockMode The new lock mode for the given drawer. One of {@link #LOCK_MODE_UNLOCKED},
3310492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *                 {@link #LOCK_MODE_LOCKED_CLOSED} or {@link #LOCK_MODE_LOCKED_OPEN}.
3320492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
3330492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public void setDrawerLockMode(int lockMode) {
3340492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        setDrawerLockMode(lockMode, Gravity.LEFT);
3350492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        setDrawerLockMode(lockMode, Gravity.RIGHT);
3360492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
3370492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
3380492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
3390492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Enable or disable interaction with the given drawer.
3400492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
3410492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>This allows the application to restrict the user's ability to open or close
3420492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * the given drawer. DrawerLayout will still respond to calls to {@link #openDrawer(int)},
3430492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * {@link #closeDrawer(int)} and friends if a drawer is locked.</p>
3440492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
3450492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>Locking a drawer open or closed will implicitly open or close
3460492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * that drawer as appropriate.</p>
3470492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
3480492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param lockMode The new lock mode for the given drawer. One of {@link #LOCK_MODE_UNLOCKED},
3490492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *                 {@link #LOCK_MODE_LOCKED_CLOSED} or {@link #LOCK_MODE_LOCKED_OPEN}.
3500492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param edgeGravity Gravity.LEFT, RIGHT, START or END.
3510492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *                    Expresses which drawer to change the mode for.
3520492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
3530492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_UNLOCKED
3540492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_LOCKED_CLOSED
3550492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_LOCKED_OPEN
3560492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
3570492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public void setDrawerLockMode(int lockMode, int edgeGravity) {
358f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final int absGravity = GravityCompat.getAbsoluteGravity(edgeGravity,
3590492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                ViewCompat.getLayoutDirection(this));
360f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        if (absGravity == Gravity.LEFT) {
3610492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            mLockModeLeft = lockMode;
362f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        } else if (absGravity == Gravity.RIGHT) {
3630492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            mLockModeRight = lockMode;
3640492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
3650492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        if (lockMode != LOCK_MODE_UNLOCKED) {
3660492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            // Cancel interaction in progress
367f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            final ViewDragHelper helper = absGravity == Gravity.LEFT ? mLeftDragger : mRightDragger;
3680492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            helper.cancel();
3690492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
3700492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        switch (lockMode) {
3710492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            case LOCK_MODE_LOCKED_OPEN:
372f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                final View toOpen = findDrawerWithGravity(absGravity);
3730492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                if (toOpen != null) {
3740492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                    openDrawer(toOpen);
3750492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                }
3760492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                break;
3770492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            case LOCK_MODE_LOCKED_CLOSED:
378f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                final View toClose = findDrawerWithGravity(absGravity);
3790492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                if (toClose != null) {
3800492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                    closeDrawer(toClose);
3810492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                }
3820492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                break;
3830492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            // default: do nothing
3840492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
3850492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
3860492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
3870492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
3880492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Enable or disable interaction with the given drawer.
3890492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
3900492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>This allows the application to restrict the user's ability to open or close
3910492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * the given drawer. DrawerLayout will still respond to calls to {@link #openDrawer(int)},
3920492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * {@link #closeDrawer(int)} and friends if a drawer is locked.</p>
3930492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
3940492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>Locking a drawer open or closed will implicitly open or close
3950492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * that drawer as appropriate.</p>
3960492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
3970492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param lockMode The new lock mode for the given drawer. One of {@link #LOCK_MODE_UNLOCKED},
3980492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *                 {@link #LOCK_MODE_LOCKED_CLOSED} or {@link #LOCK_MODE_LOCKED_OPEN}.
3990492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param drawerView The drawer view to change the lock mode for
4000492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
4010492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_UNLOCKED
4020492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_LOCKED_CLOSED
4030492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_LOCKED_OPEN
4040492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
4050492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public void setDrawerLockMode(int lockMode, View drawerView) {
4060492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        if (!isDrawerView(drawerView)) {
4070492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            throw new IllegalArgumentException("View " + drawerView + " is not a " +
4080492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                    "drawer with appropriate layout_gravity");
4090492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
410f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final int gravity = ((LayoutParams) drawerView.getLayoutParams()).gravity;
411f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        setDrawerLockMode(lockMode, gravity);
4120492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
4130492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
4140492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
4150492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Check the lock mode of the drawer with the given gravity.
4160492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
4170492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param edgeGravity Gravity of the drawer to check
4180492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @return one of {@link #LOCK_MODE_UNLOCKED}, {@link #LOCK_MODE_LOCKED_CLOSED} or
4190492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *         {@link #LOCK_MODE_LOCKED_OPEN}.
4200492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
4210492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public int getDrawerLockMode(int edgeGravity) {
422f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final int absGravity = GravityCompat.getAbsoluteGravity(
423f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                edgeGravity, ViewCompat.getLayoutDirection(this));
424f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        if (absGravity == Gravity.LEFT) {
4250492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            return mLockModeLeft;
426f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        } else if (absGravity == Gravity.RIGHT) {
4270492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            return mLockModeRight;
4280492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
4290492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        return LOCK_MODE_UNLOCKED;
4300492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
4310492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
4320492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
4330492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Check the lock mode of the given drawer view.
4340492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
4350492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param drawerView Drawer view to check lock mode
4360492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @return one of {@link #LOCK_MODE_UNLOCKED}, {@link #LOCK_MODE_LOCKED_CLOSED} or
4370492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *         {@link #LOCK_MODE_LOCKED_OPEN}.
4380492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
4390492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public int getDrawerLockMode(View drawerView) {
440f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final int absGravity = getDrawerViewAbsoluteGravity(drawerView);
441f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        if (absGravity == Gravity.LEFT) {
4420492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            return mLockModeLeft;
443f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        } else if (absGravity == Gravity.RIGHT) {
4440492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            return mLockModeRight;
4450492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
4460492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        return LOCK_MODE_UNLOCKED;
4470492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
4480492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
4490492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
450526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * Sets the title of the drawer with the given gravity.
451526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * <p>
452526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * When accessibility is turned on, this is the title that will be used to
453526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * identify the drawer to the active accessibility service.
454526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     *
455526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * @param edgeGravity Gravity.LEFT, RIGHT, START or END. Expresses which
456526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     *            drawer to set the title for.
457526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * @param title The title for the drawer.
458526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     */
459526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    public void setDrawerTitle(int edgeGravity, CharSequence title) {
460526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        final int absGravity = GravityCompat.getAbsoluteGravity(
461526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                edgeGravity, ViewCompat.getLayoutDirection(this));
462526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        if (absGravity == Gravity.LEFT) {
463526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            mTitleLeft = title;
464526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        } else if (absGravity == Gravity.RIGHT) {
465526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            mTitleRight = title;
466526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        }
467526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    }
468526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
469526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    /**
470526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * Returns the title of the drawer with the given gravity.
471526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     *
472526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * @param edgeGravity Gravity.LEFT, RIGHT, START or END. Expresses which
473526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     *            drawer to return the title for.
474526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * @return The title of the drawer, or null if none set.
475526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * @see #setDrawerTitle(int, CharSequence)
476526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     */
477526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    public CharSequence getDrawerTitle(int edgeGravity) {
478526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        final int absGravity = GravityCompat.getAbsoluteGravity(
479526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                edgeGravity, ViewCompat.getLayoutDirection(this));
480526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        if (absGravity == Gravity.LEFT) {
481526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            return mTitleLeft;
482526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        } else if (absGravity == Gravity.RIGHT) {
483526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            return mTitleRight;
484526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        }
485526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        return null;
486526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    }
487526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
488526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    /**
4891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Resolve the shared state of all drawers from the component ViewDragHelpers.
4901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Should be called whenever a ViewDragHelper's state changes.
4911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
492b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    void updateDrawerState(int forGravity, int activeState, View activeDrawer) {
4931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int leftState = mLeftDragger.getViewDragState();
4941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int rightState = mRightDragger.getViewDragState();
4951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int state;
4971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (leftState == STATE_DRAGGING || rightState == STATE_DRAGGING) {
4981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            state = STATE_DRAGGING;
4991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        } else if (leftState == STATE_SETTLING || rightState == STATE_SETTLING) {
5001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            state = STATE_SETTLING;
5011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        } else {
5021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            state = STATE_IDLE;
5031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
5041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
505b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (activeDrawer != null && activeState == STATE_IDLE) {
506b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final LayoutParams lp = (LayoutParams) activeDrawer.getLayoutParams();
507b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            if (lp.onScreen == 0) {
508b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                dispatchOnDrawerClosed(activeDrawer);
509b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            } else if (lp.onScreen == 1) {
510b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                dispatchOnDrawerOpened(activeDrawer);
511b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            }
512b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
513b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
5141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (state != mDrawerState) {
5151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mDrawerState = state;
516b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
5171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (mListener != null) {
5181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mListener.onDrawerStateChanged(state);
5191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
5201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
5211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
5221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void dispatchOnDrawerClosed(View drawerView) {
5241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
5251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (lp.knownOpen) {
5261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            lp.knownOpen = false;
5271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (mListener != null) {
5281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mListener.onDrawerClosed(drawerView);
5291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
530aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette
53112ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            // If no drawer is opened, all drawers are not shown
53212ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            // for accessibility and the content is shown.
53312ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            View content = getChildAt(0);
53412ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            if (content != null) {
53512ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                ViewCompat.setImportantForAccessibility(content,
53612ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                        ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
53712ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            }
53812ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            ViewCompat.setImportantForAccessibility(drawerView,
53912ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                            ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
54012ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
541aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // Only send WINDOW_STATE_CHANGE if the host has window focus. This
542aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // may change if support for multiple foreground windows (e.g. IME)
543aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // improves.
544aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            if (hasWindowFocus()) {
545aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette                final View rootView = getRootView();
546aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette                if (rootView != null) {
547aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette                    rootView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
548aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette                }
549aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            }
5501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
5511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
5521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void dispatchOnDrawerOpened(View drawerView) {
5541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
5551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (!lp.knownOpen) {
5561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            lp.knownOpen = true;
5571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (mListener != null) {
5581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mListener.onDrawerOpened(drawerView);
5591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
56012ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
56112ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            // If a drawer is opened, only it is shown for
56212ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            // accessibility and the content is not shown.
56312ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            View content = getChildAt(0);
56412ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            if (content != null) {
56512ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                ViewCompat.setImportantForAccessibility(content,
56612ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                        ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
56712ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            }
56812ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            ViewCompat.setImportantForAccessibility(drawerView,
56912ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                    ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
57012ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
571526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
5721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
5731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
5741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void dispatchOnDrawerSlide(View drawerView, float slideOffset) {
5761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (mListener != null) {
5771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mListener.onDrawerSlide(drawerView, slideOffset);
5781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
5791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
5801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void setDrawerViewOffset(View drawerView, float slideOffset) {
5821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
583b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (slideOffset == lp.onScreen) {
5841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return;
5851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
5861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
587b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        lp.onScreen = slideOffset;
5881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        dispatchOnDrawerSlide(drawerView, slideOffset);
5891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
5901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    float getDrawerViewOffset(View drawerView) {
592b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        return ((LayoutParams) drawerView.getLayoutParams()).onScreen;
5931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
5941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
595f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette    /**
596f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     * @return the absolute gravity of the child drawerView, resolved according
597f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     *         to the current layout direction
598f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     */
599f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette    int getDrawerViewAbsoluteGravity(View drawerView) {
6001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int gravity = ((LayoutParams) drawerView.getLayoutParams()).gravity;
601f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        return GravityCompat.getAbsoluteGravity(gravity, ViewCompat.getLayoutDirection(this));
6021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
6031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
604f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette    boolean checkDrawerViewAbsoluteGravity(View drawerView, int checkFor) {
605f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final int absGravity = getDrawerViewAbsoluteGravity(drawerView);
606f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        return (absGravity & checkFor) == checkFor;
6071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
6081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6090492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    View findOpenDrawer() {
6100492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        final int childCount = getChildCount();
6110492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        for (int i = 0; i < childCount; i++) {
6120492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            final View child = getChildAt(i);
6130492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            if (((LayoutParams) child.getLayoutParams()).knownOpen) {
6140492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                return child;
6150492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            }
6160492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
6170492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        return null;
6180492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
6190492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
6201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void moveDrawerToOffset(View drawerView, float slideOffset) {
6211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final float oldOffset = getDrawerViewOffset(drawerView);
6221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int width = drawerView.getWidth();
6231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int oldPos = (int) (width * oldOffset);
6241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int newPos = (int) (width * slideOffset);
6251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int dx = newPos - oldPos;
6261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
627f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        drawerView.offsetLeftAndRight(
628f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                checkDrawerViewAbsoluteGravity(drawerView, Gravity.LEFT) ? dx : -dx);
6291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        setDrawerViewOffset(drawerView, slideOffset);
6301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
6311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
632f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette    /**
633f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     * @param gravity the gravity of the child to return. If specified as a
634f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     *            relative value, it will be resolved according to the current
635f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     *            layout direction.
636f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     * @return the drawer with the specified gravity
637f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     */
6381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    View findDrawerWithGravity(int gravity) {
639f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final int absHorizGravity = GravityCompat.getAbsoluteGravity(
640f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                gravity, ViewCompat.getLayoutDirection(this)) & Gravity.HORIZONTAL_GRAVITY_MASK;
6411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
6421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
6431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
644f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            final int childAbsGravity = getDrawerViewAbsoluteGravity(child);
645f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if ((childAbsGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == absHorizGravity) {
6461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                return child;
6471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
6481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
6491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return null;
6501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
6511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
6531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Simple gravity to string - only supports LEFT and RIGHT for debugging output.
6541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
6551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param gravity Absolute gravity value
6561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @return LEFT or RIGHT as appropriate, or a hex string
6571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
6581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    static String gravityToString(int gravity) {
6591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if ((gravity & Gravity.LEFT) == Gravity.LEFT) {
6601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return "LEFT";
6611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
6621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) {
6631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return "RIGHT";
6641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
6651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return Integer.toHexString(gravity);
6661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
6671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
66957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected void onDetachedFromWindow() {
67057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        super.onDetachedFromWindow();
67157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        mFirstLayout = true;
67257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
67357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
67457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
67557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected void onAttachedToWindow() {
67657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        super.onAttachedToWindow();
67757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        mFirstLayout = true;
67857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
67957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
68057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
6811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
682c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
683c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
684c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
685c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
6861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) {
688c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell            if (isInEditMode()) {
689c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                // Don't crash the layout editor. Consume all of the space if specified
690c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                // or pick a magic number from thin air otherwise.
691c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                // TODO Better communication with tools of this bogus state.
692c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                // It will crash on a real device.
693c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                if (widthMode == MeasureSpec.AT_MOST) {
694c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                    widthMode = MeasureSpec.EXACTLY;
695c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                } else if (widthMode == MeasureSpec.UNSPECIFIED) {
696c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                    widthMode = MeasureSpec.EXACTLY;
697c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                    widthSize = 300;
698c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                }
699c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                if (heightMode == MeasureSpec.AT_MOST) {
700c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                    heightMode = MeasureSpec.EXACTLY;
701c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                }
702c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                else if (heightMode == MeasureSpec.UNSPECIFIED) {
703c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                    heightMode = MeasureSpec.EXACTLY;
704c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                    heightSize = 300;
705c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                }
706c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell            } else {
707c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                throw new IllegalArgumentException(
708c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                        "DrawerLayout must be measured with MeasureSpec.EXACTLY.");
709c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell            }
7101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
7111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        setMeasuredDimension(widthSize, heightSize);
7131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        // Gravity value for each drawer we've seen. Only one of each permitted.
7151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        int foundDrawers = 0;
7161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
7171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
7181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
7191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (child.getVisibility() == GONE) {
7211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                continue;
7221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
7231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
72400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
72500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
7261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (isContentView(child)) {
7271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                // Content views get measured at exactly the layout's size.
72800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int contentWidthSpec = MeasureSpec.makeMeasureSpec(
72900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        widthSize - lp.leftMargin - lp.rightMargin, MeasureSpec.EXACTLY);
73000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int contentHeightSpec = MeasureSpec.makeMeasureSpec(
73100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        heightSize - lp.topMargin - lp.bottomMargin, MeasureSpec.EXACTLY);
73200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                child.measure(contentWidthSpec, contentHeightSpec);
7331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else if (isDrawerView(child)) {
7341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int childGravity =
735f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                        getDrawerViewAbsoluteGravity(child) & Gravity.HORIZONTAL_GRAVITY_MASK;
7361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                if ((foundDrawers & childGravity) != 0) {
7371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    throw new IllegalStateException("Child drawer has absolute gravity " +
7381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                            gravityToString(childGravity) + " but this " + TAG + " already has a " +
7391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                            "drawer view along that edge");
7401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
74100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int drawerWidthSpec = getChildMeasureSpec(widthMeasureSpec,
74200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        mMinDrawerMargin + lp.leftMargin + lp.rightMargin,
74300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.width);
74400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int drawerHeightSpec = getChildMeasureSpec(heightMeasureSpec,
74500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.topMargin + lp.bottomMargin,
74600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.height);
74700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                child.measure(drawerWidthSpec, drawerHeightSpec);
7481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
7491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                throw new IllegalStateException("Child " + child + " at index " + i +
7501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        " does not have a valid layout_gravity - must be Gravity.LEFT, " +
7511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        "Gravity.RIGHT or Gravity.NO_GRAVITY");
7521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
7531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
7541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
7551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
7571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected void onLayout(boolean changed, int l, int t, int r, int b) {
758b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        mInLayout = true;
759c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell        final int width = r - l;
7601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
7611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
7621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
7631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (child.getVisibility() == GONE) {
7651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                continue;
7661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
7671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
76800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
76900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
7701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (isContentView(child)) {
77100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                child.layout(lp.leftMargin, lp.topMargin,
77200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.leftMargin + child.getMeasuredWidth(),
77300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.topMargin + child.getMeasuredHeight());
7741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else { // Drawer, if it wasn't onMeasure would have thrown an exception.
7751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int childWidth = child.getMeasuredWidth();
77600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int childHeight = child.getMeasuredHeight();
7771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                int childLeft;
7781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
779c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                final float newOffset;
780f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                if (checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) {
781b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    childLeft = -childWidth + (int) (childWidth * lp.onScreen);
782c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                    newOffset = (float) (childWidth + childLeft) / childWidth;
7831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                } else { // Right; onMeasure checked for us.
784c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                    childLeft = width - (int) (childWidth * lp.onScreen);
785c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                    newOffset = (float) (width - childLeft) / childWidth;
7861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
7871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
788c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                final boolean changeOffset = newOffset != lp.onScreen;
789c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell
79000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK;
79100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
79200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                switch (vgrav) {
79300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    default:
79400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    case Gravity.TOP: {
7959b2fb1efe771e9927724b33242cbc3bc62b5b315Adam Powell                        child.layout(childLeft, lp.topMargin, childLeft + childWidth,
7969b2fb1efe771e9927724b33242cbc3bc62b5b315Adam Powell                                lp.topMargin + childHeight);
79700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        break;
79800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    }
79900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
80000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    case Gravity.BOTTOM: {
80100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        final int height = b - t;
80200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        child.layout(childLeft,
80300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                                height - lp.bottomMargin - child.getMeasuredHeight(),
80400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                                childLeft + childWidth,
80500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                                height - lp.bottomMargin);
80600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        break;
80700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    }
80800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
80900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    case Gravity.CENTER_VERTICAL: {
81000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        final int height = b - t;
81100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        int childTop = (height - childHeight) / 2;
81200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
81300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        // Offset for margins. If things don't fit right because of
81400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        // bad measurement before, oh well.
81500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        if (childTop < lp.topMargin) {
81600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                            childTop = lp.topMargin;
81700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        } else if (childTop + childHeight > height - lp.bottomMargin) {
81800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                            childTop = height - lp.bottomMargin - childHeight;
81900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        }
82000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        child.layout(childLeft, childTop, childLeft + childWidth,
82100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                                childTop + childHeight);
82200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        break;
82300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    }
82400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                }
825b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
826c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                if (changeOffset) {
827c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                    setDrawerViewOffset(child, newOffset);
828c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                }
829c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell
830c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                final int newVisibility = lp.onScreen > 0 ? VISIBLE : INVISIBLE;
831c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                if (child.getVisibility() != newVisibility) {
832c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                    child.setVisibility(newVisibility);
833b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                }
8341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
8351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
836b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        mInLayout = false;
83757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        mFirstLayout = false;
838b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
839b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
840b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    @Override
841b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public void requestLayout() {
842b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (!mInLayout) {
843b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            super.requestLayout();
844b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
8451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
8461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
8481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void computeScroll() {
8491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
8501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        float scrimOpacity = 0;
8511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
852b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final float onscreen = ((LayoutParams) getChildAt(i).getLayoutParams()).onScreen;
8531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            scrimOpacity = Math.max(scrimOpacity, onscreen);
8541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
8551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mScrimOpacity = scrimOpacity;
8561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        // "|" used on purpose; both need to run.
8581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (mLeftDragger.continueSettling(true) | mRightDragger.continueSettling(true)) {
8591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            ViewCompat.postInvalidateOnAnimation(this);
8601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
8611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
8621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
863b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    private static boolean hasOpaqueBackground(View v) {
864b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        final Drawable bg = v.getBackground();
865b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (bg != null) {
866b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            return bg.getOpacity() == PixelFormat.OPAQUE;
867b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
868b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        return false;
869b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
870b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
8711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
8721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
87300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        final int height = getHeight();
874b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        final boolean drawingContent = isContentView(child);
875b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        int clipLeft = 0, clipRight = getWidth();
876b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
8771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int restoreCount = canvas.save();
878b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (drawingContent) {
879b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int childCount = getChildCount();
880b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            for (int i = 0; i < childCount; i++) {
881b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                final View v = getChildAt(i);
882b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                if (v == child || v.getVisibility() != VISIBLE ||
88300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        !hasOpaqueBackground(v) || !isDrawerView(v) ||
88400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        v.getHeight() < height) {
885b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    continue;
886b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                }
887b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
888f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                if (checkDrawerViewAbsoluteGravity(v, Gravity.LEFT)) {
889b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    final int vright = v.getRight();
890b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    if (vright > clipLeft) clipLeft = vright;
891b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                } else {
892b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    final int vleft = v.getLeft();
893b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    if (vleft < clipRight) clipRight = vleft;
894b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                }
895b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            }
896b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            canvas.clipRect(clipLeft, 0, clipRight, getHeight());
897b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
8981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final boolean result = super.drawChild(canvas, child, drawingTime);
8991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        canvas.restoreToCount(restoreCount);
900b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
901b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (mScrimOpacity > 0 && drawingContent) {
9021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int baseAlpha = (mScrimColor & 0xff000000) >>> 24;
9031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int imag = (int) (baseAlpha * mScrimOpacity);
9041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int color = imag << 24 | (mScrimColor & 0xffffff);
9051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mScrimPaint.setColor(color);
9061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
907b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            canvas.drawRect(clipLeft, 0, clipRight, getHeight(), mScrimPaint);
908f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        } else if (mShadowLeft != null && checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) {
909b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int shadowWidth = mShadowLeft.getIntrinsicWidth();
910b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int childRight = child.getRight();
911ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            final int drawerPeekDistance = mLeftDragger.getEdgeSize();
912b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final float alpha =
913ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                    Math.max(0, Math.min((float) childRight / drawerPeekDistance, 1.f));
914b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowLeft.setBounds(childRight, child.getTop(),
915b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    childRight + shadowWidth, child.getBottom());
916b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowLeft.setAlpha((int) (0xff * alpha));
917b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowLeft.draw(canvas);
918f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        } else if (mShadowRight != null && checkDrawerViewAbsoluteGravity(child, Gravity.RIGHT)) {
919b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int shadowWidth = mShadowRight.getIntrinsicWidth();
920b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int childLeft = child.getLeft();
921b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int showing = getWidth() - childLeft;
922ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            final int drawerPeekDistance = mRightDragger.getEdgeSize();
923b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final float alpha =
924ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                    Math.max(0, Math.min((float) showing / drawerPeekDistance, 1.f));
925b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowRight.setBounds(childLeft - shadowWidth, child.getTop(),
926b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    childLeft, child.getBottom());
927b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowRight.setAlpha((int) (0xff * alpha));
928b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowRight.draw(canvas);
9291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return result;
9311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
9321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    boolean isContentView(View child) {
9341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return ((LayoutParams) child.getLayoutParams()).gravity == Gravity.NO_GRAVITY;
9351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
9361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    boolean isDrawerView(View child) {
9381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int gravity = ((LayoutParams) child.getLayoutParams()).gravity;
9391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int absGravity = GravityCompat.getAbsoluteGravity(gravity,
9401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                ViewCompat.getLayoutDirection(child));
9411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return (absGravity & (Gravity.LEFT | Gravity.RIGHT)) != 0;
9421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
9431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
9451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public boolean onInterceptTouchEvent(MotionEvent ev) {
9461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int action = MotionEventCompat.getActionMasked(ev);
9471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        // "|" used deliberately here; both methods should be invoked.
9491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final boolean interceptForDrag = mLeftDragger.shouldInterceptTouchEvent(ev) |
9501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mRightDragger.shouldInterceptTouchEvent(ev);
9511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean interceptForTap = false;
9531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        switch (action) {
9551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_DOWN: {
9561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float x = ev.getX();
9571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float y = ev.getY();
9581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionX = x;
9591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionY = y;
9601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                if (mScrimOpacity > 0 &&
9611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        isContentView(mLeftDragger.findTopChildUnder((int) x, (int) y))) {
9621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    interceptForTap = true;
9631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
9641732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
965cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                mChildrenCanceledTouch = false;
9661732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                break;
9671732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            }
9681732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
9691732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            case MotionEvent.ACTION_MOVE: {
9701732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                // If we cross the touch slop, don't perform the delayed peek for an edge touch.
9711732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                if (mLeftDragger.checkTouchSlop(ViewDragHelper.DIRECTION_ALL)) {
9721732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                    mLeftCallback.removeCallbacks();
9731732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                    mRightCallback.removeCallbacks();
9741732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                }
9751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
9761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
9771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_CANCEL:
9791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_UP: {
9801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawers(true);
9811732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
982cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                mChildrenCanceledTouch = false;
9831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
9841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9851732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
986cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell        return interceptForDrag || interceptForTap || hasPeekingDrawer() || mChildrenCanceledTouch;
9871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
9881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
9901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public boolean onTouchEvent(MotionEvent ev) {
9911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mLeftDragger.processTouchEvent(ev);
9921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mRightDragger.processTouchEvent(ev);
9931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int action = ev.getAction();
9951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean wantTouchEvents = true;
9961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        switch (action & MotionEventCompat.ACTION_MASK) {
9981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_DOWN: {
9991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float x = ev.getX();
10001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float y = ev.getY();
10011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionX = x;
10021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionY = y;
10031732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
1004cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                mChildrenCanceledTouch = false;
10051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
10061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
10071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_UP: {
10091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float x = ev.getX();
10101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float y = ev.getY();
10111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                boolean peekingOnly = true;
10128bc268e9c40e4ae375a0d65dc1293dccc541186fAdam Powell                final View touchedView = mLeftDragger.findTopChildUnder((int) x, (int) y);
10138bc268e9c40e4ae375a0d65dc1293dccc541186fAdam Powell                if (touchedView != null && isContentView(touchedView)) {
10141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    final float dx = x - mInitialMotionX;
10151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    final float dy = y - mInitialMotionY;
10161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    final int slop = mLeftDragger.getTouchSlop();
10171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    if (dx * dx + dy * dy < slop * slop) {
10180492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                        // Taps close a dimmed open drawer but only if it isn't locked open.
10190492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                        final View openDrawer = findOpenDrawer();
10200492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                        if (openDrawer != null) {
10210492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                            peekingOnly = getDrawerLockMode(openDrawer) == LOCK_MODE_LOCKED_OPEN;
10220492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                        }
10231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    }
10241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
10251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawers(peekingOnly);
10261732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
10271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
10281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
10291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_CANCEL: {
10311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawers(true);
10321732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
1033cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                mChildrenCanceledTouch = false;
10341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
10351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
10361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
10371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return wantTouchEvents;
10391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
10401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1041ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
104286559d86173efb890a8edf48d935cfebfaccf049Adam Powell        if (CHILDREN_DISALLOW_INTERCEPT ||
104386559d86173efb890a8edf48d935cfebfaccf049Adam Powell                (!mLeftDragger.isEdgeTouched(ViewDragHelper.EDGE_LEFT) &&
104486559d86173efb890a8edf48d935cfebfaccf049Adam Powell                !mRightDragger.isEdgeTouched(ViewDragHelper.EDGE_RIGHT))) {
10451732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            // If we have an edge touch we want to skip this and track it for later instead.
10461732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            super.requestDisallowInterceptTouchEvent(disallowIntercept);
10471732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        }
10481732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mDisallowInterceptRequested = disallowIntercept;
1049ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        if (disallowIntercept) {
1050ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            closeDrawers(true);
1051ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        }
1052ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    }
1053ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell
10541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
10551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Close all currently open drawer views by animating them out of view.
10561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
10571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void closeDrawers() {
10581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        closeDrawers(false);
10591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
10601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void closeDrawers(boolean peekingOnly) {
10621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean needsInvalidate = false;
10631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
10641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
10651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
10661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
10671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (!isDrawerView(child) || (peekingOnly && !lp.isPeeking)) {
10691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                continue;
10701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
10711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childWidth = child.getWidth();
10731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1074f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if (checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) {
10751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                needsInvalidate |= mLeftDragger.smoothSlideViewTo(child,
10761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        -childWidth, child.getTop());
10771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
10781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                needsInvalidate |= mRightDragger.smoothSlideViewTo(child,
10791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        getWidth(), child.getTop());
10801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
10811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            lp.isPeeking = false;
10831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
10841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10851732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mLeftCallback.removeCallbacks();
10861732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mRightCallback.removeCallbacks();
10871732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
10881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (needsInvalidate) {
10891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            invalidate();
10901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
10911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
10921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
10941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Open the specified drawer view by animating it into view.
10951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
10961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param drawerView Drawer view to open
10971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
10981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void openDrawer(View drawerView) {
10991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (!isDrawerView(drawerView)) {
11001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            throw new IllegalArgumentException("View " + drawerView + " is not a sliding drawer");
11011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
11021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
110357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        if (mFirstLayout) {
110457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
110557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            lp.onScreen = 1.f;
110657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            lp.knownOpen = true;
11071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        } else {
1108f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if (checkDrawerViewAbsoluteGravity(drawerView, Gravity.LEFT)) {
110957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mLeftDragger.smoothSlideViewTo(drawerView, 0, drawerView.getTop());
111057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            } else {
111157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mRightDragger.smoothSlideViewTo(drawerView, getWidth() - drawerView.getWidth(),
111257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                        drawerView.getTop());
111357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
11141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
11151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        invalidate();
11161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
11171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
11181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
11191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Open the specified drawer by animating it out of view.
11201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
11211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param gravity Gravity.LEFT to move the left drawer or Gravity.RIGHT for the right.
11221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *                GravityCompat.START or GravityCompat.END may also be used.
11231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
11241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void openDrawer(int gravity) {
1125f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final View drawerView = findDrawerWithGravity(gravity);
11261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (drawerView == null) {
1127f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            throw new IllegalArgumentException("No drawer view found with gravity " +
1128f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                    gravityToString(gravity));
11291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
11301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        openDrawer(drawerView);
11311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
11321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
11331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
11341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Close the specified drawer view by animating it into view.
11351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
11361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param drawerView Drawer view to close
11371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
11381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void closeDrawer(View drawerView) {
11391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (!isDrawerView(drawerView)) {
11401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            throw new IllegalArgumentException("View " + drawerView + " is not a sliding drawer");
11411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
11421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
114357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        if (mFirstLayout) {
114457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
114557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            lp.onScreen = 0.f;
114657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            lp.knownOpen = false;
11471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        } else {
1148f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if (checkDrawerViewAbsoluteGravity(drawerView, Gravity.LEFT)) {
114957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mLeftDragger.smoothSlideViewTo(drawerView, -drawerView.getWidth(),
115057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                        drawerView.getTop());
115157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            } else {
115257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mRightDragger.smoothSlideViewTo(drawerView, getWidth(), drawerView.getTop());
115357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
11541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
11551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        invalidate();
11561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
11571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
11581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
11591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Close the specified drawer by animating it out of view.
11601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
11611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param gravity Gravity.LEFT to move the left drawer or Gravity.RIGHT for the right.
11621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *                GravityCompat.START or GravityCompat.END may also be used.
11631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
11641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void closeDrawer(int gravity) {
1165f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final View drawerView = findDrawerWithGravity(gravity);
11661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (drawerView == null) {
1167f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            throw new IllegalArgumentException("No drawer view found with gravity " +
1168f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                    gravityToString(gravity));
11691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
11701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        closeDrawer(drawerView);
11711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
11721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1173b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
1174b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Check if the given drawer view is currently in an open state.
1175b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * To be considered "open" the drawer must have settled into its fully
1176b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * visible state. To check for partial visibility use
1177b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * {@link #isDrawerVisible(android.view.View)}.
1178b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
1179b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param drawer Drawer view to check
1180b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @return true if the given drawer view is in an open state
1181b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @see #isDrawerVisible(android.view.View)
1182b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
1183b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public boolean isDrawerOpen(View drawer) {
1184b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (!isDrawerView(drawer)) {
1185b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            throw new IllegalArgumentException("View " + drawer + " is not a drawer");
1186b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
1187b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        return ((LayoutParams) drawer.getLayoutParams()).knownOpen;
1188b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
1189b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
1190b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
119179f95ce3e660d267831067e514ff455156c4381fAdam Powell     * Check if the given drawer view is currently in an open state.
119279f95ce3e660d267831067e514ff455156c4381fAdam Powell     * To be considered "open" the drawer must have settled into its fully
119379f95ce3e660d267831067e514ff455156c4381fAdam Powell     * visible state. If there is no drawer with the given gravity this method
119479f95ce3e660d267831067e514ff455156c4381fAdam Powell     * will return false.
119579f95ce3e660d267831067e514ff455156c4381fAdam Powell     *
119679f95ce3e660d267831067e514ff455156c4381fAdam Powell     * @param drawerGravity Gravity of the drawer to check
119779f95ce3e660d267831067e514ff455156c4381fAdam Powell     * @return true if the given drawer view is in an open state
119879f95ce3e660d267831067e514ff455156c4381fAdam Powell     */
119979f95ce3e660d267831067e514ff455156c4381fAdam Powell    public boolean isDrawerOpen(int drawerGravity) {
120079f95ce3e660d267831067e514ff455156c4381fAdam Powell        final View drawerView = findDrawerWithGravity(drawerGravity);
120179f95ce3e660d267831067e514ff455156c4381fAdam Powell        if (drawerView != null) {
120279f95ce3e660d267831067e514ff455156c4381fAdam Powell            return isDrawerOpen(drawerView);
120379f95ce3e660d267831067e514ff455156c4381fAdam Powell        }
120479f95ce3e660d267831067e514ff455156c4381fAdam Powell        return false;
120579f95ce3e660d267831067e514ff455156c4381fAdam Powell    }
120679f95ce3e660d267831067e514ff455156c4381fAdam Powell
120779f95ce3e660d267831067e514ff455156c4381fAdam Powell    /**
1208b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Check if a given drawer view is currently visible on-screen. The drawer
1209b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * may be only peeking onto the screen, fully extended, or anywhere inbetween.
1210b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
1211b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param drawer Drawer view to check
1212b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @return true if the given drawer is visible on-screen
1213b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @see #isDrawerOpen(android.view.View)
1214b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
1215b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public boolean isDrawerVisible(View drawer) {
1216b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (!isDrawerView(drawer)) {
1217b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            throw new IllegalArgumentException("View " + drawer + " is not a drawer");
1218b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
1219b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        return ((LayoutParams) drawer.getLayoutParams()).onScreen > 0;
1220b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
1221b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
122279f95ce3e660d267831067e514ff455156c4381fAdam Powell    /**
122379f95ce3e660d267831067e514ff455156c4381fAdam Powell     * Check if a given drawer view is currently visible on-screen. The drawer
122479f95ce3e660d267831067e514ff455156c4381fAdam Powell     * may be only peeking onto the screen, fully extended, or anywhere inbetween.
122579f95ce3e660d267831067e514ff455156c4381fAdam Powell     * If there is no drawer with the given gravity this method will return false.
122679f95ce3e660d267831067e514ff455156c4381fAdam Powell     *
122779f95ce3e660d267831067e514ff455156c4381fAdam Powell     * @param drawerGravity Gravity of the drawer to check
122879f95ce3e660d267831067e514ff455156c4381fAdam Powell     * @return true if the given drawer is visible on-screen
122979f95ce3e660d267831067e514ff455156c4381fAdam Powell     */
123079f95ce3e660d267831067e514ff455156c4381fAdam Powell    public boolean isDrawerVisible(int drawerGravity) {
123179f95ce3e660d267831067e514ff455156c4381fAdam Powell        final View drawerView = findDrawerWithGravity(drawerGravity);
123279f95ce3e660d267831067e514ff455156c4381fAdam Powell        if (drawerView != null) {
123379f95ce3e660d267831067e514ff455156c4381fAdam Powell            return isDrawerVisible(drawerView);
123479f95ce3e660d267831067e514ff455156c4381fAdam Powell        }
123579f95ce3e660d267831067e514ff455156c4381fAdam Powell        return false;
123679f95ce3e660d267831067e514ff455156c4381fAdam Powell    }
123779f95ce3e660d267831067e514ff455156c4381fAdam Powell
1238ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    private boolean hasPeekingDrawer() {
1239ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        final int childCount = getChildCount();
1240ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        for (int i = 0; i < childCount; i++) {
1241ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            final LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams();
1242ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            if (lp.isPeeking) {
1243ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                return true;
1244ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            }
1245ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        }
1246ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        return false;
1247ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    }
1248ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell
12491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
12501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
12511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
12521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
12531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
12551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
12561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return p instanceof LayoutParams
12571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                ? new LayoutParams((LayoutParams) p)
125800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                : p instanceof ViewGroup.MarginLayoutParams
125900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                ? new LayoutParams((MarginLayoutParams) p)
12601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                : new LayoutParams(p);
12611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
12621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
12641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
12651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return p instanceof LayoutParams && super.checkLayoutParams(p);
12661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
12671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
12691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
12701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return new LayoutParams(getContext(), attrs);
12711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
12721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1273791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    private boolean hasVisibleDrawer() {
12740492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        return findVisibleDrawer() != null;
12750492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
12760492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
12770492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    private View findVisibleDrawer() {
1278791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        final int childCount = getChildCount();
1279791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        for (int i = 0; i < childCount; i++) {
1280791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            final View child = getChildAt(i);
1281791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            if (isDrawerView(child) && isDrawerVisible(child)) {
12820492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                return child;
1283791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            }
1284791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        }
12850492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        return null;
1286791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    }
1287791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
1288cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell    void cancelChildViewTouch() {
1289cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell        // Cancel child touches
1290cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell        if (!mChildrenCanceledTouch) {
1291cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            final long now = SystemClock.uptimeMillis();
1292cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            final MotionEvent cancelEvent = MotionEvent.obtain(now, now,
1293cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                    MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
1294cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            final int childCount = getChildCount();
1295cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            for (int i = 0; i < childCount; i++) {
1296cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                getChildAt(i).dispatchTouchEvent(cancelEvent);
1297cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            }
1298cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            cancelEvent.recycle();
1299cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            mChildrenCanceledTouch = true;
1300cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell        }
1301cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell    }
1302cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell
1303791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    @Override
1304791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    public boolean onKeyDown(int keyCode, KeyEvent event) {
1305791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        if (keyCode == KeyEvent.KEYCODE_BACK && hasVisibleDrawer()) {
1306791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            KeyEventCompat.startTracking(event);
1307791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            return true;
1308791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        }
1309791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        return super.onKeyDown(keyCode, event);
1310791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    }
1311791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
1312791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    @Override
1313791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    public boolean onKeyUp(int keyCode, KeyEvent event) {
13140492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        if (keyCode == KeyEvent.KEYCODE_BACK) {
13150492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            final View visibleDrawer = findVisibleDrawer();
13160492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            if (visibleDrawer != null && getDrawerLockMode(visibleDrawer) == LOCK_MODE_UNLOCKED) {
13170492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                closeDrawers();
13180492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            }
13190492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            return visibleDrawer != null;
1320791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        }
1321791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        return super.onKeyUp(keyCode, event);
1322791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    }
1323791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
132457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
132557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected void onRestoreInstanceState(Parcelable state) {
132657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        final SavedState ss = (SavedState) state;
132757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        super.onRestoreInstanceState(ss.getSuperState());
132857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
132957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        if (ss.openDrawerGravity != Gravity.NO_GRAVITY) {
133057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            final View toOpen = findDrawerWithGravity(ss.openDrawerGravity);
133157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            if (toOpen != null) {
133257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                openDrawer(toOpen);
133357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
133457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
13358e01d24e718d603974182cd48f648369c07edec1Adam Powell
13368e01d24e718d603974182cd48f648369c07edec1Adam Powell        setDrawerLockMode(ss.lockModeLeft, Gravity.LEFT);
13378e01d24e718d603974182cd48f648369c07edec1Adam Powell        setDrawerLockMode(ss.lockModeRight, Gravity.RIGHT);
133857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
133957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
134057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
134157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected Parcelable onSaveInstanceState() {
134257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        final Parcelable superState = super.onSaveInstanceState();
134357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
134457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        final SavedState ss = new SavedState(superState);
134557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
134657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        final int childCount = getChildCount();
134757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        for (int i = 0; i < childCount; i++) {
134857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            final View child = getChildAt(i);
134957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            if (!isDrawerView(child)) {
135057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                continue;
135157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
135257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
135357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
135457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            if (lp.knownOpen) {
135557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                ss.openDrawerGravity = lp.gravity;
135657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                // Only one drawer can be open at a time.
135757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                break;
135857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
135957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
136057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
13618e01d24e718d603974182cd48f648369c07edec1Adam Powell        ss.lockModeLeft = mLockModeLeft;
13628e01d24e718d603974182cd48f648369c07edec1Adam Powell        ss.lockModeRight = mLockModeRight;
13638e01d24e718d603974182cd48f648369c07edec1Adam Powell
136457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        return ss;
136557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
136657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
136712ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    @Override
136812ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    public void addView(View child, int index, ViewGroup.LayoutParams params) {
136912ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        // Until a drawer is open, it is hidden from accessibility.
137012ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        if (index > 0 || (index < 0 && getChildCount() > 0)) {
137112ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            ViewCompat.setImportantForAccessibility(child,
137212ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                    ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
137312ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            // Also set a delegate to break the child-parent relation if the
137412ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            // child is hidden. For details (see incluceChildForAccessibility).
137512ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            ViewCompat.setAccessibilityDelegate(child, mChildAccessibilityDelegate);
137612ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        } else  {
137712ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            // Initially, the content is shown for accessibility.
137812ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            ViewCompat.setImportantForAccessibility(child,
137912ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                    ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
138012ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        }
138112ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        super.addView(child, index, params);
138212ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    }
138312ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
138412ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    private static boolean includeChildForAccessibilitiy(View child) {
138512ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        // If the child is not important for accessibility we make
138612ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        // sure this hides the entire subtree rooted at it as the
138712ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        // IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDATS is not
138812ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        // supported on older platforms but we want to hide the entire
138912ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        // content and not opened drawers if a drawer is opened.
139012ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        return ViewCompat.getImportantForAccessibility(child)
139112ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                != ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
139212ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                    && ViewCompat.getImportantForAccessibility(child)
139312ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                != ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO;
139412ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    }
139512ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
139657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    /**
139757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell     * State persisted across instances
139857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell     */
139957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected static class SavedState extends BaseSavedState {
140057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        int openDrawerGravity = Gravity.NO_GRAVITY;
14018e01d24e718d603974182cd48f648369c07edec1Adam Powell        int lockModeLeft = LOCK_MODE_UNLOCKED;
14028e01d24e718d603974182cd48f648369c07edec1Adam Powell        int lockModeRight = LOCK_MODE_UNLOCKED;
140357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
140457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        public SavedState(Parcel in) {
140557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            super(in);
140657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            openDrawerGravity = in.readInt();
140757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
140857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
140957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        public SavedState(Parcelable superState) {
141057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            super(superState);
141157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
141257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
141357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        @Override
141457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        public void writeToParcel(Parcel dest, int flags) {
141557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            super.writeToParcel(dest, flags);
141657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            dest.writeInt(openDrawerGravity);
141757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
141857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
141957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        public static final Parcelable.Creator<SavedState> CREATOR =
142057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                new Parcelable.Creator<SavedState>() {
142157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            @Override
142257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            public SavedState createFromParcel(Parcel source) {
142357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                return new SavedState(source);
142457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
142557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
142657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            @Override
142757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            public SavedState[] newArray(int size) {
142857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                return new SavedState[size];
142957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
143057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        };
143157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
143257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
14331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private class ViewDragCallback extends ViewDragHelper.Callback {
1434f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        private final int mAbsGravity;
14351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        private ViewDragHelper mDragger;
14361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14371732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        private final Runnable mPeekRunnable = new Runnable() {
14381732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            @Override public void run() {
14391732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                peekDrawer();
14401732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            }
14411732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        };
14421732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
14431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public ViewDragCallback(int gravity) {
1444f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            mAbsGravity = gravity;
14451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
14461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void setDragger(ViewDragHelper dragger) {
14481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mDragger = dragger;
14491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
14501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14511732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        public void removeCallbacks() {
14521732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            DrawerLayout.this.removeCallbacks(mPeekRunnable);
14531732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        }
14541732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
14551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
14561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public boolean tryCaptureView(View child, int pointerId) {
14571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // Only capture views where the gravity matches what we're looking for.
14581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // This lets us use two ViewDragHelpers, one for each side drawer.
1459f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            return isDrawerView(child) && checkDrawerViewAbsoluteGravity(child, mAbsGravity)
1460f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                    && getDrawerLockMode(child) == LOCK_MODE_UNLOCKED;
14611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
14621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
14641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewDragStateChanged(int state) {
1465f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            updateDrawerState(mAbsGravity, state, mDragger.getCapturedView());
14661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
14671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
14691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
14701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            float offset;
14711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childWidth = changedView.getWidth();
14721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // This reverses the positioning shown in onLayout.
1474f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if (checkDrawerViewAbsoluteGravity(changedView, Gravity.LEFT)) {
14751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                offset = (float) (childWidth + left) / childWidth;
14761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
14771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int width = getWidth();
14781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                offset = (float) (width - left) / childWidth;
14791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
14801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            setDrawerViewOffset(changedView, offset);
1481b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            changedView.setVisibility(offset == 0 ? INVISIBLE : VISIBLE);
14821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            invalidate();
14831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
14841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
14861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewCaptured(View capturedChild, int activePointerId) {
14871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final LayoutParams lp = (LayoutParams) capturedChild.getLayoutParams();
14881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            lp.isPeeking = false;
14891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            closeOtherDrawer();
14911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
14921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        private void closeOtherDrawer() {
1494f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            final int otherGrav = mAbsGravity == Gravity.LEFT ? Gravity.RIGHT : Gravity.LEFT;
14951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View toClose = findDrawerWithGravity(otherGrav);
14961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (toClose != null) {
14971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawer(toClose);
14981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
14991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
15001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
15011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
15021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewReleased(View releasedChild, float xvel, float yvel) {
15031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // Offset is how open the drawer is, therefore left/right values
15041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // are reversed from one another.
15051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final float offset = getDrawerViewOffset(releasedChild);
15061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childWidth = releasedChild.getWidth();
15071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
15081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            int left;
1509f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if (checkDrawerViewAbsoluteGravity(releasedChild, Gravity.LEFT)) {
15101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                left = xvel > 0 || xvel == 0 && offset > 0.5f ? 0 : -childWidth;
15111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
15121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int width = getWidth();
15137d690eb050d901c7a7b4ebc3896471124ef98f7cAdam Powell                left = xvel < 0 || xvel == 0 && offset > 0.5f ? width - childWidth : width;
15141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
15151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
15161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mDragger.settleCapturedViewAt(left, releasedChild.getTop());
15171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            invalidate();
15181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
15191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
15201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
15211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onEdgeTouched(int edgeFlags, int pointerId) {
15221732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            postDelayed(mPeekRunnable, PEEK_DELAY);
15231732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        }
15241732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
15251732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        private void peekDrawer() {
15261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View toCapture;
15271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childLeft;
1528ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            final int peekDistance = mDragger.getEdgeSize();
1529f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            final boolean leftEdge = mAbsGravity == Gravity.LEFT;
1530b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            if (leftEdge) {
15311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.LEFT);
1532ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                childLeft = (toCapture != null ? -toCapture.getWidth() : 0) + peekDistance;
15331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
15341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.RIGHT);
1535ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                childLeft = getWidth() - peekDistance;
15361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
15370492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            // Only peek if it would mean making the drawer more visible and the drawer isn't locked
1538b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            if (toCapture != null && ((leftEdge && toCapture.getLeft() < childLeft) ||
15390492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                    (!leftEdge && toCapture.getLeft() > childLeft)) &&
15400492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                    getDrawerLockMode(toCapture) == LOCK_MODE_UNLOCKED) {
1541b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                final LayoutParams lp = (LayoutParams) toCapture.getLayoutParams();
15421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mDragger.smoothSlideViewTo(toCapture, childLeft, toCapture.getTop());
1543b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                lp.isPeeking = true;
15441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                invalidate();
15451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
15461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeOtherDrawer();
1547cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell
1548cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                cancelChildViewTouch();
15491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
15501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
15511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
15521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
1553ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        public boolean onEdgeLock(int edgeFlags) {
1554ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            if (ALLOW_EDGE_LOCK) {
1555f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                final View drawer = findDrawerWithGravity(mAbsGravity);
1556ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                if (drawer != null && !isDrawerOpen(drawer)) {
1557ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                    closeDrawer(drawer);
1558ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                }
1559ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                return true;
1560acc82321ad119706485db342eaa12b225fa9b667Adam Powell            }
1561ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            return false;
1562acc82321ad119706485db342eaa12b225fa9b667Adam Powell        }
1563acc82321ad119706485db342eaa12b225fa9b667Adam Powell
1564acc82321ad119706485db342eaa12b225fa9b667Adam Powell        @Override
15651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onEdgeDragStarted(int edgeFlags, int pointerId) {
15661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View toCapture;
15671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if ((edgeFlags & ViewDragHelper.EDGE_LEFT) == ViewDragHelper.EDGE_LEFT) {
15681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.LEFT);
15691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
15701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.RIGHT);
15711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
15721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
15730492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            if (toCapture != null && getDrawerLockMode(toCapture) == LOCK_MODE_UNLOCKED) {
15741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mDragger.captureChildView(toCapture, pointerId);
15751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
15761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
15771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
15781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
15791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public int getViewHorizontalDragRange(View child) {
15801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return child.getWidth();
15811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
15821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
15831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
15841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public int clampViewPositionHorizontal(View child, int left, int dx) {
1585f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if (checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) {
15861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                return Math.max(-child.getWidth(), Math.min(left, 0));
15871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
15881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int width = getWidth();
15891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                return Math.max(width - child.getWidth(), Math.min(left, width));
15901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
15911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
159200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
159300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        @Override
159400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        public int clampViewPositionVertical(View child, int top, int dy) {
159500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell            return child.getTop();
159600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        }
15971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
15981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
159900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell    public static class LayoutParams extends ViewGroup.MarginLayoutParams {
16001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public int gravity = Gravity.NO_GRAVITY;
1602b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        float onScreen;
16031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean isPeeking;
16041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean knownOpen;
16051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(Context c, AttributeSet attrs) {
16071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(c, attrs);
16081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final TypedArray a = c.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
16101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this.gravity = a.getInt(0, Gravity.NO_GRAVITY);
16111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            a.recycle();
16121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
16131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(int width, int height) {
16151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(width, height);
16161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
16171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(int width, int height, int gravity) {
16191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this(width, height);
16201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this.gravity = gravity;
16211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
16221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(LayoutParams source) {
16241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(source);
16251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this.gravity = source.gravity;
16261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
16271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(ViewGroup.LayoutParams source) {
16291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(source);
16301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
163100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
163200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        public LayoutParams(ViewGroup.MarginLayoutParams source) {
163300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell            super(source);
163400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        }
16351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
16367d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell
16377d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell    class AccessibilityDelegate extends AccessibilityDelegateCompat {
16383cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell        private final Rect mTmpRect = new Rect();
16393cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
16407d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell        @Override
16417d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
16423cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            final AccessibilityNodeInfoCompat superNode = AccessibilityNodeInfoCompat.obtain(info);
16433cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            super.onInitializeAccessibilityNodeInfo(host, superNode);
16443cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
1645526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            info.setClassName(DrawerLayout.class.getName());
16463cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            info.setSource(host);
16473cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            final ViewParent parent = ViewCompat.getParentForAccessibility(host);
16483cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            if (parent instanceof View) {
16493cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell                info.setParent((View) parent);
16503cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            }
16513cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            copyNodeInfoNoChildren(info, superNode);
16523cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
16533cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            superNode.recycle();
16543cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
1655d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette            addChildrenForAccessibility(info, (ViewGroup) host);
1656d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette        }
1657d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette
1658526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        @Override
1659526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
1660526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            super.onInitializeAccessibilityEvent(host, event);
1661526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
1662526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            event.setClassName(DrawerLayout.class.getName());
1663aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette        }
1664526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
1665aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette        @Override
1666aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
1667526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            // Special case to handle window state change events. As far as
1668aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // accessibility services are concerned, state changes from
1669aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // DrawerLayout invalidate the entire contents of the screen (like
1670aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // an Activity or Dialog) and they should announce the title of the
1671aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // new content.
1672526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
1673526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                final List<CharSequence> eventText = event.getText();
1674526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                final View visibleDrawer = findVisibleDrawer();
1675526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                if (visibleDrawer != null) {
1676526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                    final int edgeGravity = getDrawerViewAbsoluteGravity(visibleDrawer);
1677526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                    final CharSequence title = getDrawerTitle(edgeGravity);
1678526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                    if (title != null) {
1679526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                        eventText.add(title);
1680526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                    }
1681526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                }
1682aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette
1683aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette                return true;
1684526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            }
1685aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette
1686aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            return super.dispatchPopulateAccessibilityEvent(host, event);
1687526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        }
1688526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
1689d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette        private void addChildrenForAccessibility(AccessibilityNodeInfoCompat info, ViewGroup v) {
1690d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette            final int childCount = v.getChildCount();
16917d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell            for (int i = 0; i < childCount; i++) {
1692d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette                final View child = v.getChildAt(i);
169312ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                if (includeChildForAccessibilitiy(child)) {
169412ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                    info.addChild(child);
16957d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell                }
16967d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell            }
16977d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell        }
16987d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell
16997d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell        @Override
17007d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
17017d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell                AccessibilityEvent event) {
170212ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            if (includeChildForAccessibilitiy(child)) {
17037d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell                return super.onRequestSendAccessibilityEvent(host, child, event);
17047d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell            }
17057d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell            return false;
17067d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell        }
17077d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell
17083cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell        /**
17093cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell         * This should really be in AccessibilityNodeInfoCompat, but there unfortunately
17103cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell         * seem to be a few elements that are not easily cloneable using the underlying API.
17113cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell         * Leave it private here as it's not general-purpose useful.
17123cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell         */
17133cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell        private void copyNodeInfoNoChildren(AccessibilityNodeInfoCompat dest,
17143cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell                AccessibilityNodeInfoCompat src) {
17153cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            final Rect rect = mTmpRect;
17163cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
17173cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            src.getBoundsInParent(rect);
17183cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setBoundsInParent(rect);
17193cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
17203cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            src.getBoundsInScreen(rect);
17213cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setBoundsInScreen(rect);
17223cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
17233cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setVisibleToUser(src.isVisibleToUser());
17243cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setPackageName(src.getPackageName());
17253cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setClassName(src.getClassName());
17263cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setContentDescription(src.getContentDescription());
17273cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
17283cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setEnabled(src.isEnabled());
17293cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setClickable(src.isClickable());
17303cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setFocusable(src.isFocusable());
17313cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setFocused(src.isFocused());
17323cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setAccessibilityFocused(src.isAccessibilityFocused());
17333cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setSelected(src.isSelected());
17343cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setLongClickable(src.isLongClickable());
17353cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
17363cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.addAction(src.getActions());
17373cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell        }
17387d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell    }
173912ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
174012ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    final class ChildAccessibilityDelegate extends AccessibilityDelegateCompat {
174112ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        @Override
174212ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        public void onInitializeAccessibilityNodeInfo(View child,
174312ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                AccessibilityNodeInfoCompat info) {
174412ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            super.onInitializeAccessibilityNodeInfo(child, info);
174512ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            if (!includeChildForAccessibilitiy(child)) {
174612ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                // If we are ignoring the sub-tree rooted at the child,
174712ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                // break the connection to the rest of the node tree.
174812ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                // For details refer to includeChildForAccessibilitiy.
174912ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                info.setParent(null);
175012ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            }
175112ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        }
175212ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    }
17531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell}
1754