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;
26f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powellimport android.graphics.drawable.ColorDrawable;
27b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powellimport android.graphics.drawable.Drawable;
28f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powellimport android.os.Build;
2957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powellimport android.os.Parcel;
3057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powellimport android.os.Parcelable;
31cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powellimport android.os.SystemClock;
32a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbyeimport android.support.annotation.DrawableRes;
33a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbyeimport android.support.annotation.IntDef;
34a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbyeimport android.support.annotation.Nullable;
35f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powellimport android.support.v4.content.ContextCompat;
367d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powellimport android.support.v4.view.AccessibilityDelegateCompat;
371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.support.v4.view.GravityCompat;
38791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powellimport android.support.v4.view.KeyEventCompat;
391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.support.v4.view.MotionEventCompat;
401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.support.v4.view.ViewCompat;
411b8262b87426b2f766b40d6ab4eaeac296d5c2feAdam Powellimport android.support.v4.view.ViewGroupCompat;
427d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powellimport android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.util.AttributeSet;
441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.Gravity;
45791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powellimport android.view.KeyEvent;
461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.MotionEvent;
471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.View;
481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.ViewGroup;
493cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powellimport android.view.ViewParent;
507d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powellimport android.view.accessibility.AccessibilityEvent;
511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
52a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbyeimport java.lang.annotation.Retention;
53a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbyeimport java.lang.annotation.RetentionPolicy;
54526ba1382e61845ef23bf27d300883dea0966af5Alan Viveretteimport java.util.List;
55526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell/**
571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * DrawerLayout acts as a top-level container for window content that allows for
581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * interactive "drawer" views to be pulled out from the edge of the window.
591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell *
601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * <p>Drawer positioning and layout is controlled using the <code>android:layout_gravity</code>
6109c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * attribute on child views corresponding to which side of the view you want the drawer
6209c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * to emerge from: left or right. (Or start/end on platform versions that support layout direction.)
6309c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * </p>
6409c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell *
6509c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * <p>To use a DrawerLayout, position your primary content view as the first child with
6609c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * a width and height of <code>match_parent</code>. Add drawers as child views after the main
6709c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * content view and set the <code>layout_gravity</code> appropriately. Drawers commonly use
6809c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * <code>match_parent</code> for height with a fixed width.</p>
6909c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell *
7009c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * <p>{@link DrawerListener} can be used to monitor the state and motion of drawer views.
7109c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * Avoid performing expensive operations such as layout during animation as it can cause
7209c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * stuttering; try to perform expensive operations during the {@link #STATE_IDLE} state.
7309c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * {@link SimpleDrawerListener} offers default/no-op implementations of each callback method.</p>
741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell *
7595572937e188a6f5724bfe1217efd04073e2c705Scott Main * <p>As per the <a href="{@docRoot}design/patterns/navigation-drawer.html">Android Design
7695572937e188a6f5724bfe1217efd04073e2c705Scott Main * guide</a>, any drawers positioned to the left/start should
771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * always contain content for navigating around the application, whereas any drawers
781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * positioned to the right/end should always contain actions to take on the current content.
791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * This preserves the same navigation left, actions right structure present in the Action Bar
801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * and elsewhere.</p>
8195572937e188a6f5724bfe1217efd04073e2c705Scott Main *
8295572937e188a6f5724bfe1217efd04073e2c705Scott Main * <p>For more information about how to use DrawerLayout, read <a
8395572937e188a6f5724bfe1217efd04073e2c705Scott Main * href="{@docRoot}training/implementing-navigation/nav-drawer.html">Creating a Navigation
8495572937e188a6f5724bfe1217efd04073e2c705Scott Main * Drawer</a>.</p>
851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */
86f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powellpublic class DrawerLayout extends ViewGroup implements DrawerLayoutImpl {
871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final String TAG = "DrawerLayout";
881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
89a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    @IntDef({STATE_IDLE, STATE_DRAGGING, STATE_SETTLING})
90a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    @Retention(RetentionPolicy.SOURCE)
91a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    private @interface State {}
92a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye
931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Indicates that any drawers are in an idle, settled state. No animation is in progress.
951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public static final int STATE_IDLE = ViewDragHelper.STATE_IDLE;
971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Indicates that a drawer is currently being dragged by the user.
1001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
1011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public static final int STATE_DRAGGING = ViewDragHelper.STATE_DRAGGING;
1021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
1041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Indicates that a drawer is in the process of settling to a final position.
1051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
1061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public static final int STATE_SETTLING = ViewDragHelper.STATE_SETTLING;
1071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
108a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    /** @hide */
109a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    @IntDef({LOCK_MODE_UNLOCKED, LOCK_MODE_LOCKED_CLOSED, LOCK_MODE_LOCKED_OPEN})
110a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    @Retention(RetentionPolicy.SOURCE)
111a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    private @interface LockMode {}
112a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye
1130492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
1140492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * The drawer is unlocked.
1150492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
1160492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public static final int LOCK_MODE_UNLOCKED = 0;
1170492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
1180492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
1190492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * The drawer is locked closed. The user may not open it, though
1200492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * the app may open it programmatically.
1210492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
1220492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public static final int LOCK_MODE_LOCKED_CLOSED = 1;
1230492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
1240492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
1250492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * The drawer is locked open. The user may not close it, though the app
1260492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * may close it programmatically.
1270492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
1280492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public static final int LOCK_MODE_LOCKED_OPEN = 2;
1290492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
130a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    /** @hide */
131a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    @IntDef({Gravity.LEFT, Gravity.RIGHT, GravityCompat.START, GravityCompat.END})
132a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    @Retention(RetentionPolicy.SOURCE)
133a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    private @interface EdgeGravity {}
134a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye
135a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye
1361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final int MIN_DRAWER_MARGIN = 64; // dp
1371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final int DEFAULT_SCRIM_COLOR = 0x99000000;
1391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
140ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    /**
1411732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell     * Length of time to delay before peeking the drawer.
1421732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell     */
1431732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    private static final int PEEK_DELAY = 160; // ms
1441732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
1451732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    /**
14679f95ce3e660d267831067e514ff455156c4381fAdam Powell     * Minimum velocity that will be detected as a fling
14779f95ce3e660d267831067e514ff455156c4381fAdam Powell     */
14879f95ce3e660d267831067e514ff455156c4381fAdam Powell    private static final int MIN_FLING_VELOCITY = 400; // dips per second
14979f95ce3e660d267831067e514ff455156c4381fAdam Powell
15079f95ce3e660d267831067e514ff455156c4381fAdam Powell    /**
151ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell     * Experimental feature.
152ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell     */
153ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    private static final boolean ALLOW_EDGE_LOCK = false;
154ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell
15586559d86173efb890a8edf48d935cfebfaccf049Adam Powell    private static final boolean CHILDREN_DISALLOW_INTERCEPT = true;
15686559d86173efb890a8edf48d935cfebfaccf049Adam Powell
15786559d86173efb890a8edf48d935cfebfaccf049Adam Powell    private static final float TOUCH_SLOP_SENSITIVITY = 1.f;
15886559d86173efb890a8edf48d935cfebfaccf049Adam Powell
1591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final int[] LAYOUT_ATTRS = new int[] {
1601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            android.R.attr.layout_gravity
1611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    };
1621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1632bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette    /** Whether we can use NO_HIDE_DESCENDANTS accessibility importance. */
1642bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette    private static final boolean CAN_HIDE_DESCENDANTS = Build.VERSION.SDK_INT >= 19;
1652bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette
16612ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    private final ChildAccessibilityDelegate mChildAccessibilityDelegate =
16712ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            new ChildAccessibilityDelegate();
16812ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
1691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private int mMinDrawerMargin;
1701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private int mScrimColor = DEFAULT_SCRIM_COLOR;
1721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private float mScrimOpacity;
1731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private Paint mScrimPaint = new Paint();
1741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private final ViewDragHelper mLeftDragger;
1761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private final ViewDragHelper mRightDragger;
1771732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    private final ViewDragCallback mLeftCallback;
1781732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    private final ViewDragCallback mRightCallback;
1791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private int mDrawerState;
180b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    private boolean mInLayout;
18157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    private boolean mFirstLayout = true;
1820492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    private int mLockModeLeft;
1830492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    private int mLockModeRight;
1841732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    private boolean mDisallowInterceptRequested;
185cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell    private boolean mChildrenCanceledTouch;
1861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private DrawerListener mListener;
1881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private float mInitialMotionX;
1901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private float mInitialMotionY;
1911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
192b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    private Drawable mShadowLeft;
193b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    private Drawable mShadowRight;
194f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    private Drawable mStatusBarBackground;
195b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
196526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    private CharSequence mTitleLeft;
197526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    private CharSequence mTitleRight;
198526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
199f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    private Object mLastInsets;
200f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    private boolean mDrawStatusBarBackground;
201f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
2021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
2031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Listener for monitoring events about drawers.
2041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
2051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public interface DrawerListener {
2061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
2071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when a drawer's position changes.
2081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param drawerView The child view that was moved
2091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param slideOffset The new offset of this drawer within its range, from 0-1
2101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
2111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onDrawerSlide(View drawerView, float slideOffset);
2121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
2141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when a drawer has settled in a completely open state.
2151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * The drawer is interactive at this point.
2161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         *
2171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param drawerView Drawer view that is now open
2181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
2191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onDrawerOpened(View drawerView);
2201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
2221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when a drawer has settled in a completely closed state.
2231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         *
2241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param drawerView Drawer view that is now closed
2251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
2261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onDrawerClosed(View drawerView);
2271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
2291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when the drawer motion state changes. The new state will
2301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * be one of {@link #STATE_IDLE}, {@link #STATE_DRAGGING} or {@link #STATE_SETTLING}.
2311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         *
2321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param newState The new drawer motion state
2331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
234a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye        public void onDrawerStateChanged(@State int newState);
2351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
2361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
237b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
238b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Stub/no-op implementations of all methods of {@link DrawerListener}.
239b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Override this if you only care about a few of the available callback methods.
240b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
241b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public static abstract class SimpleDrawerListener implements DrawerListener {
242b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
243b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerSlide(View drawerView, float slideOffset) {
244b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
245b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
246b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
247b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerOpened(View drawerView) {
248b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
249b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
250b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
251b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerClosed(View drawerView) {
252b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
253b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
254b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
255b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerStateChanged(int newState) {
256b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
257b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
258b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
259f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    interface DrawerLayoutCompatImpl {
260f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        void configureApplyInsets(View drawerLayout);
261f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        void dispatchChildInsets(View child, Object insets, int drawerGravity);
262f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        void applyMarginInsets(MarginLayoutParams lp, Object insets, int drawerGravity);
263f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        int getTopInset(Object lastInsets);
26484cdd567de45ea632670d51da5fb4545248d073bChris Banes        Drawable getDefaultStatusBarBackground(Context context);
265f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    }
266f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
267f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    static class DrawerLayoutCompatImplBase implements DrawerLayoutCompatImpl {
268f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        public void configureApplyInsets(View drawerLayout) {
269f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            // This space for rent
270f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
271f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
272f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        public void dispatchChildInsets(View child, Object insets, int drawerGravity) {
273f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            // This space for rent
274f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
275f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
276f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        public void applyMarginInsets(MarginLayoutParams lp, Object insets, int drawerGravity) {
277f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            // This space for rent
278f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
279f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
280f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        public int getTopInset(Object insets) {
281f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            return 0;
282f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
28384cdd567de45ea632670d51da5fb4545248d073bChris Banes
28484cdd567de45ea632670d51da5fb4545248d073bChris Banes        @Override
28584cdd567de45ea632670d51da5fb4545248d073bChris Banes        public Drawable getDefaultStatusBarBackground(Context context) {
28684cdd567de45ea632670d51da5fb4545248d073bChris Banes            return null;
28784cdd567de45ea632670d51da5fb4545248d073bChris Banes        }
288f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    }
289f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
290f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    static class DrawerLayoutCompatImplApi21 implements DrawerLayoutCompatImpl {
291f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        public void configureApplyInsets(View drawerLayout) {
292f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            DrawerLayoutCompatApi21.configureApplyInsets(drawerLayout);
293f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
294f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
295f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        public void dispatchChildInsets(View child, Object insets, int drawerGravity) {
296f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            DrawerLayoutCompatApi21.dispatchChildInsets(child, insets, drawerGravity);
297f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
298f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
299f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        public void applyMarginInsets(MarginLayoutParams lp, Object insets, int drawerGravity) {
300f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            DrawerLayoutCompatApi21.applyMarginInsets(lp, insets, drawerGravity);
301f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
302f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
303f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        public int getTopInset(Object insets) {
304f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            return DrawerLayoutCompatApi21.getTopInset(insets);
305f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
30684cdd567de45ea632670d51da5fb4545248d073bChris Banes
30784cdd567de45ea632670d51da5fb4545248d073bChris Banes        @Override
30884cdd567de45ea632670d51da5fb4545248d073bChris Banes        public Drawable getDefaultStatusBarBackground(Context context) {
30984cdd567de45ea632670d51da5fb4545248d073bChris Banes            return DrawerLayoutCompatApi21.getDefaultStatusBarBackground(context);
31084cdd567de45ea632670d51da5fb4545248d073bChris Banes        }
311f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    }
312f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
313f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    static {
314f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        final int version = Build.VERSION.SDK_INT;
315f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        if (version >= 21) {
316f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            IMPL = new DrawerLayoutCompatImplApi21();
317f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        } else {
318f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            IMPL = new DrawerLayoutCompatImplBase();
319f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
320f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    }
321f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
322f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    static final DrawerLayoutCompatImpl IMPL;
323f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
3241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public DrawerLayout(Context context) {
3251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        this(context, null);
3261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
3271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public DrawerLayout(Context context, AttributeSet attrs) {
3291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        this(context, attrs, 0);
3301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
3311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public DrawerLayout(Context context, AttributeSet attrs, int defStyle) {
3331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        super(context, attrs, defStyle);
3344a069be655204ec079c03a09157e5d4ec223a0f7Yigit Boyar        setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
3351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final float density = getResources().getDisplayMetrics().density;
3361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mMinDrawerMargin = (int) (MIN_DRAWER_MARGIN * density + 0.5f);
33779f95ce3e660d267831067e514ff455156c4381fAdam Powell        final float minVel = MIN_FLING_VELOCITY * density;
3381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3391732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mLeftCallback = new ViewDragCallback(Gravity.LEFT);
3401732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mRightCallback = new ViewDragCallback(Gravity.RIGHT);
3411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
34286559d86173efb890a8edf48d935cfebfaccf049Adam Powell        mLeftDragger = ViewDragHelper.create(this, TOUCH_SLOP_SENSITIVITY, mLeftCallback);
3431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mLeftDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
34479f95ce3e660d267831067e514ff455156c4381fAdam Powell        mLeftDragger.setMinVelocity(minVel);
3451732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mLeftCallback.setDragger(mLeftDragger);
3461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
34786559d86173efb890a8edf48d935cfebfaccf049Adam Powell        mRightDragger = ViewDragHelper.create(this, TOUCH_SLOP_SENSITIVITY, mRightCallback);
3481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mRightDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_RIGHT);
34979f95ce3e660d267831067e514ff455156c4381fAdam Powell        mRightDragger.setMinVelocity(minVel);
3501732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mRightCallback.setDragger(mRightDragger);
351791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
352791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        // So that we can catch the back button
353791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        setFocusableInTouchMode(true);
3547d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell
35512ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        ViewCompat.setImportantForAccessibility(this,
35612ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
35712ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
3587d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell        ViewCompat.setAccessibilityDelegate(this, new AccessibilityDelegate());
3591b8262b87426b2f766b40d6ab4eaeac296d5c2feAdam Powell        ViewGroupCompat.setMotionEventSplittingEnabled(this, false);
36099cb2bbfcd84bdc2e89a5a2d11b6b69132169ea6Adam Powell        if (ViewCompat.getFitsSystemWindows(this)) {
36199cb2bbfcd84bdc2e89a5a2d11b6b69132169ea6Adam Powell            IMPL.configureApplyInsets(this);
36284cdd567de45ea632670d51da5fb4545248d073bChris Banes            mStatusBarBackground = IMPL.getDefaultStatusBarBackground(context);
36399cb2bbfcd84bdc2e89a5a2d11b6b69132169ea6Adam Powell        }
364f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    }
365f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
366f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    /**
367f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * @hide Internal use only; called to apply window insets when configured
368f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * with fitsSystemWindows="true"
369f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     */
370f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    @Override
371f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    public void setChildInsets(Object insets, boolean draw) {
372f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        mLastInsets = insets;
373f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        mDrawStatusBarBackground = draw;
374f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        setWillNotDraw(!draw && getBackground() == null);
375f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        requestLayout();
3761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
3771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
379b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Set a simple drawable used for the left or right shadow.
380b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * The drawable provided must have a nonzero intrinsic width.
381b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
382b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param shadowDrawable Shadow drawable to use at the edge of a drawer
383b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param gravity Which drawer the shadow should apply to
384b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
385a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public void setDrawerShadow(Drawable shadowDrawable, @EdgeGravity int gravity) {
386b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        /*
387b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         * TODO Someone someday might want to set more complex drawables here.
388b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         * They're probably nuts, but we might want to consider registering callbacks,
389b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         * setting states, etc. properly.
390b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         */
391b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
392b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        final int absGravity = GravityCompat.getAbsoluteGravity(gravity,
393b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                ViewCompat.getLayoutDirection(this));
394b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if ((absGravity & Gravity.LEFT) == Gravity.LEFT) {
395b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowLeft = shadowDrawable;
396b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            invalidate();
397b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
398b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if ((absGravity & Gravity.RIGHT) == Gravity.RIGHT) {
399b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowRight = shadowDrawable;
400b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            invalidate();
401b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
402b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
403b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
404b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
405b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Set a simple drawable used for the left or right shadow.
406b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * The drawable provided must have a nonzero intrinsic width.
407b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
408b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param resId Resource id of a shadow drawable to use at the edge of a drawer
409b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param gravity Which drawer the shadow should apply to
410b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
411a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public void setDrawerShadow(@DrawableRes int resId, @EdgeGravity int gravity) {
412b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        setDrawerShadow(getResources().getDrawable(resId), gravity);
413b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
414b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
415b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
416fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell     * Set a color to use for the scrim that obscures primary content while a drawer is open.
417fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell     *
418fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell     * @param color Color to use in 0xAARRGGBB format.
419fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell     */
420fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell    public void setScrimColor(int color) {
421fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell        mScrimColor = color;
422fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell        invalidate();
423fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell    }
424fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell
425fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell    /**
4261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Set a listener to be notified of drawer events.
4271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
4281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param listener Listener to notify when drawer events occur
4291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @see DrawerListener
4301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
4311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void setDrawerListener(DrawerListener listener) {
4321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mListener = listener;
4331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
4341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
4360492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Enable or disable interaction with all drawers.
4370492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
4380492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>This allows the application to restrict the user's ability to open or close
4390492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * any drawer within this layout. DrawerLayout will still respond to calls to
4400492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * {@link #openDrawer(int)}, {@link #closeDrawer(int)} and friends if a drawer is locked.</p>
4410492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
4420492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>Locking drawers open or closed will implicitly open or close
4430492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * any drawers as appropriate.</p>
4440492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
4450492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param lockMode The new lock mode for the given drawer. One of {@link #LOCK_MODE_UNLOCKED},
4460492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *                 {@link #LOCK_MODE_LOCKED_CLOSED} or {@link #LOCK_MODE_LOCKED_OPEN}.
4470492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
448a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public void setDrawerLockMode(@LockMode int lockMode) {
4490492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        setDrawerLockMode(lockMode, Gravity.LEFT);
4500492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        setDrawerLockMode(lockMode, Gravity.RIGHT);
4510492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
4520492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
4530492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
4540492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Enable or disable interaction with the given drawer.
4550492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
4560492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>This allows the application to restrict the user's ability to open or close
4570492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * the given drawer. DrawerLayout will still respond to calls to {@link #openDrawer(int)},
4580492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * {@link #closeDrawer(int)} and friends if a drawer is locked.</p>
4590492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
4600492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>Locking a drawer open or closed will implicitly open or close
4610492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * that drawer as appropriate.</p>
4620492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
4630492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param lockMode The new lock mode for the given drawer. One of {@link #LOCK_MODE_UNLOCKED},
4640492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *                 {@link #LOCK_MODE_LOCKED_CLOSED} or {@link #LOCK_MODE_LOCKED_OPEN}.
4650492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param edgeGravity Gravity.LEFT, RIGHT, START or END.
4660492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *                    Expresses which drawer to change the mode for.
4670492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
4680492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_UNLOCKED
4690492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_LOCKED_CLOSED
4700492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_LOCKED_OPEN
4710492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
472a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public void setDrawerLockMode(@LockMode int lockMode, @EdgeGravity int edgeGravity) {
473f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final int absGravity = GravityCompat.getAbsoluteGravity(edgeGravity,
4740492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                ViewCompat.getLayoutDirection(this));
475f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        if (absGravity == Gravity.LEFT) {
4760492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            mLockModeLeft = lockMode;
477f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        } else if (absGravity == Gravity.RIGHT) {
4780492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            mLockModeRight = lockMode;
4790492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
4800492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        if (lockMode != LOCK_MODE_UNLOCKED) {
4810492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            // Cancel interaction in progress
482f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            final ViewDragHelper helper = absGravity == Gravity.LEFT ? mLeftDragger : mRightDragger;
4830492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            helper.cancel();
4840492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
4850492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        switch (lockMode) {
4860492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            case LOCK_MODE_LOCKED_OPEN:
487f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                final View toOpen = findDrawerWithGravity(absGravity);
4880492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                if (toOpen != null) {
4890492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                    openDrawer(toOpen);
4900492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                }
4910492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                break;
4920492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            case LOCK_MODE_LOCKED_CLOSED:
493f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                final View toClose = findDrawerWithGravity(absGravity);
4940492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                if (toClose != null) {
4950492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                    closeDrawer(toClose);
4960492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                }
4970492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                break;
4980492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            // default: do nothing
4990492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
5000492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
5010492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
5020492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
5030492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Enable or disable interaction with the given drawer.
5040492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
5050492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>This allows the application to restrict the user's ability to open or close
5060492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * the given drawer. DrawerLayout will still respond to calls to {@link #openDrawer(int)},
5070492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * {@link #closeDrawer(int)} and friends if a drawer is locked.</p>
5080492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
5090492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>Locking a drawer open or closed will implicitly open or close
5100492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * that drawer as appropriate.</p>
5110492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
5120492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param lockMode The new lock mode for the given drawer. One of {@link #LOCK_MODE_UNLOCKED},
5130492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *                 {@link #LOCK_MODE_LOCKED_CLOSED} or {@link #LOCK_MODE_LOCKED_OPEN}.
5140492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param drawerView The drawer view to change the lock mode for
5150492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
5160492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_UNLOCKED
5170492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_LOCKED_CLOSED
5180492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_LOCKED_OPEN
5190492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
520a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public void setDrawerLockMode(@LockMode int lockMode, View drawerView) {
5210492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        if (!isDrawerView(drawerView)) {
5220492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            throw new IllegalArgumentException("View " + drawerView + " is not a " +
5230492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                    "drawer with appropriate layout_gravity");
5240492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
525f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final int gravity = ((LayoutParams) drawerView.getLayoutParams()).gravity;
526f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        setDrawerLockMode(lockMode, gravity);
5270492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
5280492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
5290492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
5300492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Check the lock mode of the drawer with the given gravity.
5310492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
5320492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param edgeGravity Gravity of the drawer to check
5330492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @return one of {@link #LOCK_MODE_UNLOCKED}, {@link #LOCK_MODE_LOCKED_CLOSED} or
5340492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *         {@link #LOCK_MODE_LOCKED_OPEN}.
5350492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
536a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    @LockMode
537a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public int getDrawerLockMode(@EdgeGravity int edgeGravity) {
538f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final int absGravity = GravityCompat.getAbsoluteGravity(
539f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                edgeGravity, ViewCompat.getLayoutDirection(this));
540f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        if (absGravity == Gravity.LEFT) {
5410492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            return mLockModeLeft;
542f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        } else if (absGravity == Gravity.RIGHT) {
5430492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            return mLockModeRight;
5440492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
5450492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        return LOCK_MODE_UNLOCKED;
5460492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
5470492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
5480492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
5490492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Check the lock mode of the given drawer view.
5500492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
5510492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param drawerView Drawer view to check lock mode
5520492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @return one of {@link #LOCK_MODE_UNLOCKED}, {@link #LOCK_MODE_LOCKED_CLOSED} or
5530492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *         {@link #LOCK_MODE_LOCKED_OPEN}.
5540492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
555a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    @LockMode
5560492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public int getDrawerLockMode(View drawerView) {
557f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final int absGravity = getDrawerViewAbsoluteGravity(drawerView);
558f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        if (absGravity == Gravity.LEFT) {
5590492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            return mLockModeLeft;
560f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        } else if (absGravity == Gravity.RIGHT) {
5610492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            return mLockModeRight;
5620492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
5630492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        return LOCK_MODE_UNLOCKED;
5640492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
5650492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
5660492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
567526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * Sets the title of the drawer with the given gravity.
568526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * <p>
569526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * When accessibility is turned on, this is the title that will be used to
570526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * identify the drawer to the active accessibility service.
571526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     *
572526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * @param edgeGravity Gravity.LEFT, RIGHT, START or END. Expresses which
573526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     *            drawer to set the title for.
574526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * @param title The title for the drawer.
575526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     */
576a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public void setDrawerTitle(@EdgeGravity int edgeGravity, CharSequence title) {
577526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        final int absGravity = GravityCompat.getAbsoluteGravity(
578526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                edgeGravity, ViewCompat.getLayoutDirection(this));
579526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        if (absGravity == Gravity.LEFT) {
580526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            mTitleLeft = title;
581526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        } else if (absGravity == Gravity.RIGHT) {
582526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            mTitleRight = title;
583526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        }
584526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    }
585526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
586526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    /**
587526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * Returns the title of the drawer with the given gravity.
588526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     *
589526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * @param edgeGravity Gravity.LEFT, RIGHT, START or END. Expresses which
590526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     *            drawer to return the title for.
591526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * @return The title of the drawer, or null if none set.
592526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * @see #setDrawerTitle(int, CharSequence)
593526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     */
594a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    @Nullable
595a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public CharSequence getDrawerTitle(@EdgeGravity int edgeGravity) {
596526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        final int absGravity = GravityCompat.getAbsoluteGravity(
597526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                edgeGravity, ViewCompat.getLayoutDirection(this));
598526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        if (absGravity == Gravity.LEFT) {
599526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            return mTitleLeft;
600526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        } else if (absGravity == Gravity.RIGHT) {
601526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            return mTitleRight;
602526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        }
603526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        return null;
604526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    }
605526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
606526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    /**
6071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Resolve the shared state of all drawers from the component ViewDragHelpers.
6081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Should be called whenever a ViewDragHelper's state changes.
6091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
610a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    void updateDrawerState(int forGravity, @State int activeState, View activeDrawer) {
6111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int leftState = mLeftDragger.getViewDragState();
6121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int rightState = mRightDragger.getViewDragState();
6131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int state;
6151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (leftState == STATE_DRAGGING || rightState == STATE_DRAGGING) {
6161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            state = STATE_DRAGGING;
6171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        } else if (leftState == STATE_SETTLING || rightState == STATE_SETTLING) {
6181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            state = STATE_SETTLING;
6191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        } else {
6201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            state = STATE_IDLE;
6211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
6221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
623b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (activeDrawer != null && activeState == STATE_IDLE) {
624b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final LayoutParams lp = (LayoutParams) activeDrawer.getLayoutParams();
625b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            if (lp.onScreen == 0) {
626b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                dispatchOnDrawerClosed(activeDrawer);
627b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            } else if (lp.onScreen == 1) {
628b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                dispatchOnDrawerOpened(activeDrawer);
629b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            }
630b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
631b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
6321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (state != mDrawerState) {
6331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mDrawerState = state;
634b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
6351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (mListener != null) {
6361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mListener.onDrawerStateChanged(state);
6371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
6381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
6391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
6401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void dispatchOnDrawerClosed(View drawerView) {
6421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
6431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (lp.knownOpen) {
6441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            lp.knownOpen = false;
6451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (mListener != null) {
6461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mListener.onDrawerClosed(drawerView);
6471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
648aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette
6492bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            updateChildrenImportantForAccessibility(drawerView, false);
65012ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
651aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // Only send WINDOW_STATE_CHANGE if the host has window focus. This
652aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // may change if support for multiple foreground windows (e.g. IME)
653aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // improves.
654aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            if (hasWindowFocus()) {
655aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette                final View rootView = getRootView();
656aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette                if (rootView != null) {
657aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette                    rootView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
658aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette                }
659aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            }
6601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
6611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
6621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void dispatchOnDrawerOpened(View drawerView) {
6641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
6651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (!lp.knownOpen) {
6661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            lp.knownOpen = true;
6671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (mListener != null) {
6681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mListener.onDrawerOpened(drawerView);
6691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
67012ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
6712bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            updateChildrenImportantForAccessibility(drawerView, true);
67212ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
673d2f68007428ed6785adcf572d47ed0f8c5c99556Alan Viverette            // Only send WINDOW_STATE_CHANGE if the host has window focus.
674d2f68007428ed6785adcf572d47ed0f8c5c99556Alan Viverette            if (hasWindowFocus()) {
675d2f68007428ed6785adcf572d47ed0f8c5c99556Alan Viverette                sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
676d2f68007428ed6785adcf572d47ed0f8c5c99556Alan Viverette            }
677d2f68007428ed6785adcf572d47ed0f8c5c99556Alan Viverette
678e47e038146dcc220f48a5275949da8c32218270aFabrice Di Meglio            drawerView.requestFocus();
6791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
6801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
6811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6822bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette    private void updateChildrenImportantForAccessibility(View drawerView, boolean isDrawerOpen) {
6832bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        final int childCount = getChildCount();
6842bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        for (int i = 0; i < childCount; i++) {
6852bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            final View child = getChildAt(i);
6862bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            if (!isDrawerOpen && !isDrawerView(child)
6872bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                    || isDrawerOpen && child == drawerView) {
6882bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                // Drawer is closed and this is a content view or this is an
6892bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                // open drawer view, so it should be visible.
6902bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                ViewCompat.setImportantForAccessibility(child,
6912bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                        ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
6922bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            } else {
6932bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                ViewCompat.setImportantForAccessibility(child,
6942bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                        ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
6952bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            }
6962bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        }
6972bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette    }
6982bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette
6991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void dispatchOnDrawerSlide(View drawerView, float slideOffset) {
7001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (mListener != null) {
7011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mListener.onDrawerSlide(drawerView, slideOffset);
7021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
7031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
7041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void setDrawerViewOffset(View drawerView, float slideOffset) {
7061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
707b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (slideOffset == lp.onScreen) {
7081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return;
7091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
7101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
711b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        lp.onScreen = slideOffset;
7121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        dispatchOnDrawerSlide(drawerView, slideOffset);
7131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
7141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    float getDrawerViewOffset(View drawerView) {
716b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        return ((LayoutParams) drawerView.getLayoutParams()).onScreen;
7171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
7181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
719f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette    /**
720f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     * @return the absolute gravity of the child drawerView, resolved according
721f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     *         to the current layout direction
722f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     */
723f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette    int getDrawerViewAbsoluteGravity(View drawerView) {
7241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int gravity = ((LayoutParams) drawerView.getLayoutParams()).gravity;
725f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        return GravityCompat.getAbsoluteGravity(gravity, ViewCompat.getLayoutDirection(this));
7261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
7271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
728f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette    boolean checkDrawerViewAbsoluteGravity(View drawerView, int checkFor) {
729f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final int absGravity = getDrawerViewAbsoluteGravity(drawerView);
730f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        return (absGravity & checkFor) == checkFor;
7311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
7321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7330492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    View findOpenDrawer() {
7340492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        final int childCount = getChildCount();
7350492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        for (int i = 0; i < childCount; i++) {
7360492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            final View child = getChildAt(i);
7370492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            if (((LayoutParams) child.getLayoutParams()).knownOpen) {
7380492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                return child;
7390492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            }
7400492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
7410492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        return null;
7420492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
7430492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
7441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void moveDrawerToOffset(View drawerView, float slideOffset) {
7451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final float oldOffset = getDrawerViewOffset(drawerView);
7461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int width = drawerView.getWidth();
7471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int oldPos = (int) (width * oldOffset);
7481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int newPos = (int) (width * slideOffset);
7491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int dx = newPos - oldPos;
7501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
751f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        drawerView.offsetLeftAndRight(
752f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                checkDrawerViewAbsoluteGravity(drawerView, Gravity.LEFT) ? dx : -dx);
7531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        setDrawerViewOffset(drawerView, slideOffset);
7541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
7551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
756f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette    /**
757f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     * @param gravity the gravity of the child to return. If specified as a
758f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     *            relative value, it will be resolved according to the current
759f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     *            layout direction.
760f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     * @return the drawer with the specified gravity
761f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     */
7621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    View findDrawerWithGravity(int gravity) {
763f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final int absHorizGravity = GravityCompat.getAbsoluteGravity(
764f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                gravity, ViewCompat.getLayoutDirection(this)) & Gravity.HORIZONTAL_GRAVITY_MASK;
7651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
7661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
7671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
768f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            final int childAbsGravity = getDrawerViewAbsoluteGravity(child);
769f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if ((childAbsGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == absHorizGravity) {
7701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                return child;
7711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
7721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
7731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return null;
7741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
7751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
7771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Simple gravity to string - only supports LEFT and RIGHT for debugging output.
7781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
7791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param gravity Absolute gravity value
7801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @return LEFT or RIGHT as appropriate, or a hex string
7811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
782a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    static String gravityToString(@EdgeGravity int gravity) {
7831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if ((gravity & Gravity.LEFT) == Gravity.LEFT) {
7841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return "LEFT";
7851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
7861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) {
7871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return "RIGHT";
7881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
7891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return Integer.toHexString(gravity);
7901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
7911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
79357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected void onDetachedFromWindow() {
79457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        super.onDetachedFromWindow();
79557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        mFirstLayout = true;
79657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
79757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
79857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
79957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected void onAttachedToWindow() {
80057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        super.onAttachedToWindow();
80157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        mFirstLayout = true;
80257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
80357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
80457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
8051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
806c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
807c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
808c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
809c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
8101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) {
812c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell            if (isInEditMode()) {
813c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                // Don't crash the layout editor. Consume all of the space if specified
814c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                // or pick a magic number from thin air otherwise.
815c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                // TODO Better communication with tools of this bogus state.
816c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                // It will crash on a real device.
817c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                if (widthMode == MeasureSpec.AT_MOST) {
818c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                    widthMode = MeasureSpec.EXACTLY;
819c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                } else if (widthMode == MeasureSpec.UNSPECIFIED) {
820c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                    widthMode = MeasureSpec.EXACTLY;
821c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                    widthSize = 300;
822c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                }
823c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                if (heightMode == MeasureSpec.AT_MOST) {
824c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                    heightMode = MeasureSpec.EXACTLY;
825c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                }
826c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                else if (heightMode == MeasureSpec.UNSPECIFIED) {
827c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                    heightMode = MeasureSpec.EXACTLY;
828c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                    heightSize = 300;
829c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                }
830c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell            } else {
831c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                throw new IllegalArgumentException(
832c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                        "DrawerLayout must be measured with MeasureSpec.EXACTLY.");
833c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell            }
8341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
8351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        setMeasuredDimension(widthSize, heightSize);
8371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
838f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        final boolean applyInsets = mLastInsets != null && ViewCompat.getFitsSystemWindows(this);
839f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        final int layoutDirection = ViewCompat.getLayoutDirection(this);
840f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
8411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        // Gravity value for each drawer we've seen. Only one of each permitted.
8421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        int foundDrawers = 0;
8431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
8441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
8451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
8461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (child.getVisibility() == GONE) {
8481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                continue;
8491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
8501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
85100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
85200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
853f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            if (applyInsets) {
854f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell                final int cgrav = GravityCompat.getAbsoluteGravity(lp.gravity, layoutDirection);
855f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell                if (ViewCompat.getFitsSystemWindows(child)) {
856f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell                    IMPL.dispatchChildInsets(child, mLastInsets, cgrav);
857f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell                } else {
858f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell                    IMPL.applyMarginInsets(lp, mLastInsets, cgrav);
859f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell                }
860f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            }
861f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
8621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (isContentView(child)) {
8631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                // Content views get measured at exactly the layout's size.
86400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int contentWidthSpec = MeasureSpec.makeMeasureSpec(
86500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        widthSize - lp.leftMargin - lp.rightMargin, MeasureSpec.EXACTLY);
86600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int contentHeightSpec = MeasureSpec.makeMeasureSpec(
86700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        heightSize - lp.topMargin - lp.bottomMargin, MeasureSpec.EXACTLY);
86800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                child.measure(contentWidthSpec, contentHeightSpec);
8691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else if (isDrawerView(child)) {
8701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int childGravity =
871f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                        getDrawerViewAbsoluteGravity(child) & Gravity.HORIZONTAL_GRAVITY_MASK;
8721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                if ((foundDrawers & childGravity) != 0) {
8731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    throw new IllegalStateException("Child drawer has absolute gravity " +
8741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                            gravityToString(childGravity) + " but this " + TAG + " already has a " +
8751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                            "drawer view along that edge");
8761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
87700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int drawerWidthSpec = getChildMeasureSpec(widthMeasureSpec,
87800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        mMinDrawerMargin + lp.leftMargin + lp.rightMargin,
87900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.width);
88000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int drawerHeightSpec = getChildMeasureSpec(heightMeasureSpec,
88100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.topMargin + lp.bottomMargin,
88200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.height);
88300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                child.measure(drawerWidthSpec, drawerHeightSpec);
8841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
8851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                throw new IllegalStateException("Child " + child + " at index " + i +
8861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        " does not have a valid layout_gravity - must be Gravity.LEFT, " +
8871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        "Gravity.RIGHT or Gravity.NO_GRAVITY");
8881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
8891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
8901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
8911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
8931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected void onLayout(boolean changed, int l, int t, int r, int b) {
894b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        mInLayout = true;
895c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell        final int width = r - l;
8961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
8971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
8981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
8991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (child.getVisibility() == GONE) {
9011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                continue;
9021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
9031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
90400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
90500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
9061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (isContentView(child)) {
90700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                child.layout(lp.leftMargin, lp.topMargin,
90800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.leftMargin + child.getMeasuredWidth(),
90900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.topMargin + child.getMeasuredHeight());
9101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else { // Drawer, if it wasn't onMeasure would have thrown an exception.
9111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int childWidth = child.getMeasuredWidth();
91200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int childHeight = child.getMeasuredHeight();
9131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                int childLeft;
9141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
915c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                final float newOffset;
916f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                if (checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) {
917b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    childLeft = -childWidth + (int) (childWidth * lp.onScreen);
918c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                    newOffset = (float) (childWidth + childLeft) / childWidth;
9191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                } else { // Right; onMeasure checked for us.
920c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                    childLeft = width - (int) (childWidth * lp.onScreen);
921c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                    newOffset = (float) (width - childLeft) / childWidth;
9221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
9231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
924c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                final boolean changeOffset = newOffset != lp.onScreen;
925c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell
92600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK;
92700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
92800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                switch (vgrav) {
92900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    default:
93000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    case Gravity.TOP: {
9319b2fb1efe771e9927724b33242cbc3bc62b5b315Adam Powell                        child.layout(childLeft, lp.topMargin, childLeft + childWidth,
9329b2fb1efe771e9927724b33242cbc3bc62b5b315Adam Powell                                lp.topMargin + childHeight);
93300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        break;
93400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    }
93500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
93600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    case Gravity.BOTTOM: {
93700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        final int height = b - t;
93800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        child.layout(childLeft,
93900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                                height - lp.bottomMargin - child.getMeasuredHeight(),
94000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                                childLeft + childWidth,
94100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                                height - lp.bottomMargin);
94200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        break;
94300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    }
94400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
94500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    case Gravity.CENTER_VERTICAL: {
94600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        final int height = b - t;
94700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        int childTop = (height - childHeight) / 2;
94800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
94900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        // Offset for margins. If things don't fit right because of
95000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        // bad measurement before, oh well.
95100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        if (childTop < lp.topMargin) {
95200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                            childTop = lp.topMargin;
95300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        } else if (childTop + childHeight > height - lp.bottomMargin) {
95400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                            childTop = height - lp.bottomMargin - childHeight;
95500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        }
95600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        child.layout(childLeft, childTop, childLeft + childWidth,
95700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                                childTop + childHeight);
95800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        break;
95900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    }
96000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                }
961b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
962c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                if (changeOffset) {
963c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                    setDrawerViewOffset(child, newOffset);
964c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                }
965c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell
966c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                final int newVisibility = lp.onScreen > 0 ? VISIBLE : INVISIBLE;
967c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                if (child.getVisibility() != newVisibility) {
968c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                    child.setVisibility(newVisibility);
969b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                }
9701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
9711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
972b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        mInLayout = false;
97357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        mFirstLayout = false;
974b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
975b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
976b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    @Override
977b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public void requestLayout() {
978b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (!mInLayout) {
979b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            super.requestLayout();
980b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
9811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
9821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
9841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void computeScroll() {
9851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
9861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        float scrimOpacity = 0;
9871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
988b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final float onscreen = ((LayoutParams) getChildAt(i).getLayoutParams()).onScreen;
9891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            scrimOpacity = Math.max(scrimOpacity, onscreen);
9901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mScrimOpacity = scrimOpacity;
9921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        // "|" used on purpose; both need to run.
9941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (mLeftDragger.continueSettling(true) | mRightDragger.continueSettling(true)) {
9951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            ViewCompat.postInvalidateOnAnimation(this);
9961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
9981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
999b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    private static boolean hasOpaqueBackground(View v) {
1000b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        final Drawable bg = v.getBackground();
1001b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (bg != null) {
1002b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            return bg.getOpacity() == PixelFormat.OPAQUE;
1003b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
1004b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        return false;
1005b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
1006b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
1007f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    /**
1008f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * Set a drawable to draw in the insets area for the status bar.
1009f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * Note that this will only be activated if this DrawerLayout fitsSystemWindows.
1010f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     *
1011f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * @param bg Background drawable to draw behind the status bar
1012f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     */
1013f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    public void setStatusBarBackground(Drawable bg) {
1014f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        mStatusBarBackground = bg;
1015f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    }
1016f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
1017f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    /**
1018753354ca64f8528ddc3b76d0ce69635de743e506Scott Kennedy     * Gets the drawable used to draw in the insets area for the status bar.
1019753354ca64f8528ddc3b76d0ce69635de743e506Scott Kennedy     *
1020753354ca64f8528ddc3b76d0ce69635de743e506Scott Kennedy     * @return The status bar background drawable, or null if none set
1021753354ca64f8528ddc3b76d0ce69635de743e506Scott Kennedy     */
1022753354ca64f8528ddc3b76d0ce69635de743e506Scott Kennedy    public Drawable getStatusBarBackgroundDrawable() {
1023753354ca64f8528ddc3b76d0ce69635de743e506Scott Kennedy        return mStatusBarBackground;
1024753354ca64f8528ddc3b76d0ce69635de743e506Scott Kennedy    }
1025753354ca64f8528ddc3b76d0ce69635de743e506Scott Kennedy
1026753354ca64f8528ddc3b76d0ce69635de743e506Scott Kennedy    /**
1027f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * Set a drawable to draw in the insets area for the status bar.
1028f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * Note that this will only be activated if this DrawerLayout fitsSystemWindows.
1029f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     *
1030f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * @param resId Resource id of a background drawable to draw behind the status bar
1031f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     */
1032f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    public void setStatusBarBackground(int resId) {
1033f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        mStatusBarBackground = resId != 0 ? ContextCompat.getDrawable(getContext(), resId) : null;
1034f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    }
1035f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
1036f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    /**
1037f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * Set a drawable to draw in the insets area for the status bar.
1038f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * Note that this will only be activated if this DrawerLayout fitsSystemWindows.
1039f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     *
1040f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * @param color Color to use as a background drawable to draw behind the status bar
1041f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     *              in 0xAARRGGBB format.
1042f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     */
1043f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    public void setStatusBarBackgroundColor(int color) {
1044f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        mStatusBarBackground = new ColorDrawable(color);
1045f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    }
1046f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
1047f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    @Override
1048f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    public void onDraw(Canvas c) {
1049f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        super.onDraw(c);
1050f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        if (mDrawStatusBarBackground && mStatusBarBackground != null) {
1051f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            final int inset = IMPL.getTopInset(mLastInsets);
1052f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            if (inset > 0) {
1053f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell                mStatusBarBackground.setBounds(0, 0, getWidth(), inset);
1054f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell                mStatusBarBackground.draw(c);
1055f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            }
1056f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
1057f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    }
1058f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
10591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
10601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
106100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        final int height = getHeight();
1062b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        final boolean drawingContent = isContentView(child);
1063b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        int clipLeft = 0, clipRight = getWidth();
1064b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
10651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int restoreCount = canvas.save();
1066b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (drawingContent) {
1067b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int childCount = getChildCount();
1068b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            for (int i = 0; i < childCount; i++) {
1069b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                final View v = getChildAt(i);
1070b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                if (v == child || v.getVisibility() != VISIBLE ||
107100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        !hasOpaqueBackground(v) || !isDrawerView(v) ||
107200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        v.getHeight() < height) {
1073b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    continue;
1074b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                }
1075b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
1076f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                if (checkDrawerViewAbsoluteGravity(v, Gravity.LEFT)) {
1077b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    final int vright = v.getRight();
1078b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    if (vright > clipLeft) clipLeft = vright;
1079b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                } else {
1080b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    final int vleft = v.getLeft();
1081b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    if (vleft < clipRight) clipRight = vleft;
1082b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                }
1083b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            }
1084b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            canvas.clipRect(clipLeft, 0, clipRight, getHeight());
1085b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
10861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final boolean result = super.drawChild(canvas, child, drawingTime);
10871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        canvas.restoreToCount(restoreCount);
1088b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
1089b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (mScrimOpacity > 0 && drawingContent) {
10901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int baseAlpha = (mScrimColor & 0xff000000) >>> 24;
10911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int imag = (int) (baseAlpha * mScrimOpacity);
10921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int color = imag << 24 | (mScrimColor & 0xffffff);
10931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mScrimPaint.setColor(color);
10941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1095b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            canvas.drawRect(clipLeft, 0, clipRight, getHeight(), mScrimPaint);
1096f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        } else if (mShadowLeft != null && checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) {
1097b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int shadowWidth = mShadowLeft.getIntrinsicWidth();
1098b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int childRight = child.getRight();
1099ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            final int drawerPeekDistance = mLeftDragger.getEdgeSize();
1100b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final float alpha =
1101ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                    Math.max(0, Math.min((float) childRight / drawerPeekDistance, 1.f));
1102b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowLeft.setBounds(childRight, child.getTop(),
1103b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    childRight + shadowWidth, child.getBottom());
1104b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowLeft.setAlpha((int) (0xff * alpha));
1105b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowLeft.draw(canvas);
1106f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        } else if (mShadowRight != null && checkDrawerViewAbsoluteGravity(child, Gravity.RIGHT)) {
1107b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int shadowWidth = mShadowRight.getIntrinsicWidth();
1108b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int childLeft = child.getLeft();
1109b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int showing = getWidth() - childLeft;
1110ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            final int drawerPeekDistance = mRightDragger.getEdgeSize();
1111b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final float alpha =
1112ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                    Math.max(0, Math.min((float) showing / drawerPeekDistance, 1.f));
1113b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowRight.setBounds(childLeft - shadowWidth, child.getTop(),
1114b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    childLeft, child.getBottom());
1115b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowRight.setAlpha((int) (0xff * alpha));
1116b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowRight.draw(canvas);
11171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
11181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return result;
11191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
11201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
11211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    boolean isContentView(View child) {
11221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return ((LayoutParams) child.getLayoutParams()).gravity == Gravity.NO_GRAVITY;
11231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
11241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
11251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    boolean isDrawerView(View child) {
11261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int gravity = ((LayoutParams) child.getLayoutParams()).gravity;
11271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int absGravity = GravityCompat.getAbsoluteGravity(gravity,
11281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                ViewCompat.getLayoutDirection(child));
11291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return (absGravity & (Gravity.LEFT | Gravity.RIGHT)) != 0;
11301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
11311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
11321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
11331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public boolean onInterceptTouchEvent(MotionEvent ev) {
11341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int action = MotionEventCompat.getActionMasked(ev);
11351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
11361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        // "|" used deliberately here; both methods should be invoked.
11371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final boolean interceptForDrag = mLeftDragger.shouldInterceptTouchEvent(ev) |
11381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mRightDragger.shouldInterceptTouchEvent(ev);
11391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
11401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean interceptForTap = false;
11411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
11421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        switch (action) {
11431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_DOWN: {
11441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float x = ev.getX();
11451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float y = ev.getY();
11461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionX = x;
11471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionY = y;
11482bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                if (mScrimOpacity > 0) {
11492bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                    final View child = mLeftDragger.findTopChildUnder((int) x, (int) y);
11502bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                    if (child != null && isContentView(child)) {
11512bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                        interceptForTap = true;
11522bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                    }
11531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
11541732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
1155cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                mChildrenCanceledTouch = false;
11561732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                break;
11571732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            }
11581732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
11591732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            case MotionEvent.ACTION_MOVE: {
11601732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                // If we cross the touch slop, don't perform the delayed peek for an edge touch.
11611732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                if (mLeftDragger.checkTouchSlop(ViewDragHelper.DIRECTION_ALL)) {
11621732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                    mLeftCallback.removeCallbacks();
11631732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                    mRightCallback.removeCallbacks();
11641732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                }
11651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
11661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
11671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
11681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_CANCEL:
11691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_UP: {
11701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawers(true);
11711732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
1172cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                mChildrenCanceledTouch = false;
11731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
11741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
11751732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
1176cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell        return interceptForDrag || interceptForTap || hasPeekingDrawer() || mChildrenCanceledTouch;
11771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
11781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
11791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
11801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public boolean onTouchEvent(MotionEvent ev) {
11811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mLeftDragger.processTouchEvent(ev);
11821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mRightDragger.processTouchEvent(ev);
11831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
11841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int action = ev.getAction();
11851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean wantTouchEvents = true;
11861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
11871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        switch (action & MotionEventCompat.ACTION_MASK) {
11881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_DOWN: {
11891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float x = ev.getX();
11901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float y = ev.getY();
11911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionX = x;
11921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionY = y;
11931732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
1194cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                mChildrenCanceledTouch = false;
11951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
11961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
11971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
11981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_UP: {
11991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float x = ev.getX();
12001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float y = ev.getY();
12011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                boolean peekingOnly = true;
12028bc268e9c40e4ae375a0d65dc1293dccc541186fAdam Powell                final View touchedView = mLeftDragger.findTopChildUnder((int) x, (int) y);
12038bc268e9c40e4ae375a0d65dc1293dccc541186fAdam Powell                if (touchedView != null && isContentView(touchedView)) {
12041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    final float dx = x - mInitialMotionX;
12051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    final float dy = y - mInitialMotionY;
12061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    final int slop = mLeftDragger.getTouchSlop();
12071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    if (dx * dx + dy * dy < slop * slop) {
12080492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                        // Taps close a dimmed open drawer but only if it isn't locked open.
12090492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                        final View openDrawer = findOpenDrawer();
12100492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                        if (openDrawer != null) {
12110492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                            peekingOnly = getDrawerLockMode(openDrawer) == LOCK_MODE_LOCKED_OPEN;
12120492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                        }
12131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    }
12141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
12151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawers(peekingOnly);
12161732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
12171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
12181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
12191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_CANCEL: {
12211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawers(true);
12221732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
1223cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                mChildrenCanceledTouch = false;
12241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
12251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
12261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
12271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return wantTouchEvents;
12291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
12301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1231ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
123286559d86173efb890a8edf48d935cfebfaccf049Adam Powell        if (CHILDREN_DISALLOW_INTERCEPT ||
123386559d86173efb890a8edf48d935cfebfaccf049Adam Powell                (!mLeftDragger.isEdgeTouched(ViewDragHelper.EDGE_LEFT) &&
123486559d86173efb890a8edf48d935cfebfaccf049Adam Powell                !mRightDragger.isEdgeTouched(ViewDragHelper.EDGE_RIGHT))) {
12351732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            // If we have an edge touch we want to skip this and track it for later instead.
12361732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            super.requestDisallowInterceptTouchEvent(disallowIntercept);
12371732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        }
12381732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mDisallowInterceptRequested = disallowIntercept;
1239ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        if (disallowIntercept) {
1240ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            closeDrawers(true);
1241ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        }
1242ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    }
1243ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell
12441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
12451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Close all currently open drawer views by animating them out of view.
12461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
12471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void closeDrawers() {
12481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        closeDrawers(false);
12491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
12501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void closeDrawers(boolean peekingOnly) {
12521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean needsInvalidate = false;
12531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
12541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
12551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
12561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
12571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (!isDrawerView(child) || (peekingOnly && !lp.isPeeking)) {
12591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                continue;
12601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
12611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childWidth = child.getWidth();
12631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1264f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if (checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) {
12651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                needsInvalidate |= mLeftDragger.smoothSlideViewTo(child,
12661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        -childWidth, child.getTop());
12671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
12681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                needsInvalidate |= mRightDragger.smoothSlideViewTo(child,
12691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        getWidth(), child.getTop());
12701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
12711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            lp.isPeeking = false;
12731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
12741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12751732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mLeftCallback.removeCallbacks();
12761732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mRightCallback.removeCallbacks();
12771732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
12781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (needsInvalidate) {
12791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            invalidate();
12801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
12811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
12821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
12841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Open the specified drawer view by animating it into view.
12851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
12861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param drawerView Drawer view to open
12871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
12881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void openDrawer(View drawerView) {
12891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (!isDrawerView(drawerView)) {
12901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            throw new IllegalArgumentException("View " + drawerView + " is not a sliding drawer");
12911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
12921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
129357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        if (mFirstLayout) {
129457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
129557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            lp.onScreen = 1.f;
129657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            lp.knownOpen = true;
129749733ad715bcf68cc178f53e17a79380d332e5ccAlan Viverette
12982bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            updateChildrenImportantForAccessibility(drawerView, true);
12991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        } else {
1300f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if (checkDrawerViewAbsoluteGravity(drawerView, Gravity.LEFT)) {
130157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mLeftDragger.smoothSlideViewTo(drawerView, 0, drawerView.getTop());
130257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            } else {
130357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mRightDragger.smoothSlideViewTo(drawerView, getWidth() - drawerView.getWidth(),
130457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                        drawerView.getTop());
130557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
13061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
13071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        invalidate();
13081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
13091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
13101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
13111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Open the specified drawer by animating it out of view.
13121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
13131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param gravity Gravity.LEFT to move the left drawer or Gravity.RIGHT for the right.
13141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *                GravityCompat.START or GravityCompat.END may also be used.
13151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
1316a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public void openDrawer(@EdgeGravity int gravity) {
1317f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final View drawerView = findDrawerWithGravity(gravity);
13181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (drawerView == null) {
1319f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            throw new IllegalArgumentException("No drawer view found with gravity " +
1320f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                    gravityToString(gravity));
13211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
13221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        openDrawer(drawerView);
13231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
13241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
13251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
13261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Close the specified drawer view by animating it into view.
13271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
13281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param drawerView Drawer view to close
13291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
13301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void closeDrawer(View drawerView) {
13311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (!isDrawerView(drawerView)) {
13321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            throw new IllegalArgumentException("View " + drawerView + " is not a sliding drawer");
13331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
13341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
133557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        if (mFirstLayout) {
133657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
133757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            lp.onScreen = 0.f;
133857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            lp.knownOpen = false;
13391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        } else {
1340f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if (checkDrawerViewAbsoluteGravity(drawerView, Gravity.LEFT)) {
134157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mLeftDragger.smoothSlideViewTo(drawerView, -drawerView.getWidth(),
134257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                        drawerView.getTop());
134357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            } else {
134457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mRightDragger.smoothSlideViewTo(drawerView, getWidth(), drawerView.getTop());
134557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
13461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
13471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        invalidate();
13481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
13491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
13501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
13511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Close the specified drawer by animating it out of view.
13521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
13531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param gravity Gravity.LEFT to move the left drawer or Gravity.RIGHT for the right.
13541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *                GravityCompat.START or GravityCompat.END may also be used.
13551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
1356a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public void closeDrawer(@EdgeGravity int gravity) {
1357f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final View drawerView = findDrawerWithGravity(gravity);
13581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (drawerView == null) {
1359f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            throw new IllegalArgumentException("No drawer view found with gravity " +
1360f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                    gravityToString(gravity));
13611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
13621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        closeDrawer(drawerView);
13631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
13641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1365b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
1366b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Check if the given drawer view is currently in an open state.
1367b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * To be considered "open" the drawer must have settled into its fully
1368b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * visible state. To check for partial visibility use
1369b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * {@link #isDrawerVisible(android.view.View)}.
1370b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
1371b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param drawer Drawer view to check
1372b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @return true if the given drawer view is in an open state
1373b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @see #isDrawerVisible(android.view.View)
1374b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
1375b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public boolean isDrawerOpen(View drawer) {
1376b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (!isDrawerView(drawer)) {
1377b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            throw new IllegalArgumentException("View " + drawer + " is not a drawer");
1378b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
1379b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        return ((LayoutParams) drawer.getLayoutParams()).knownOpen;
1380b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
1381b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
1382b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
138379f95ce3e660d267831067e514ff455156c4381fAdam Powell     * Check if the given drawer view is currently in an open state.
138479f95ce3e660d267831067e514ff455156c4381fAdam Powell     * To be considered "open" the drawer must have settled into its fully
138579f95ce3e660d267831067e514ff455156c4381fAdam Powell     * visible state. If there is no drawer with the given gravity this method
138679f95ce3e660d267831067e514ff455156c4381fAdam Powell     * will return false.
138779f95ce3e660d267831067e514ff455156c4381fAdam Powell     *
138879f95ce3e660d267831067e514ff455156c4381fAdam Powell     * @param drawerGravity Gravity of the drawer to check
138979f95ce3e660d267831067e514ff455156c4381fAdam Powell     * @return true if the given drawer view is in an open state
139079f95ce3e660d267831067e514ff455156c4381fAdam Powell     */
1391a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public boolean isDrawerOpen(@EdgeGravity int drawerGravity) {
139279f95ce3e660d267831067e514ff455156c4381fAdam Powell        final View drawerView = findDrawerWithGravity(drawerGravity);
139379f95ce3e660d267831067e514ff455156c4381fAdam Powell        if (drawerView != null) {
139479f95ce3e660d267831067e514ff455156c4381fAdam Powell            return isDrawerOpen(drawerView);
139579f95ce3e660d267831067e514ff455156c4381fAdam Powell        }
139679f95ce3e660d267831067e514ff455156c4381fAdam Powell        return false;
139779f95ce3e660d267831067e514ff455156c4381fAdam Powell    }
139879f95ce3e660d267831067e514ff455156c4381fAdam Powell
139979f95ce3e660d267831067e514ff455156c4381fAdam Powell    /**
1400b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Check if a given drawer view is currently visible on-screen. The drawer
1401b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * may be only peeking onto the screen, fully extended, or anywhere inbetween.
1402b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
1403b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param drawer Drawer view to check
1404b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @return true if the given drawer is visible on-screen
1405b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @see #isDrawerOpen(android.view.View)
1406b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
1407b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public boolean isDrawerVisible(View drawer) {
1408b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (!isDrawerView(drawer)) {
1409b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            throw new IllegalArgumentException("View " + drawer + " is not a drawer");
1410b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
1411b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        return ((LayoutParams) drawer.getLayoutParams()).onScreen > 0;
1412b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
1413b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
141479f95ce3e660d267831067e514ff455156c4381fAdam Powell    /**
141579f95ce3e660d267831067e514ff455156c4381fAdam Powell     * Check if a given drawer view is currently visible on-screen. The drawer
1416a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye     * may be only peeking onto the screen, fully extended, or anywhere in between.
141779f95ce3e660d267831067e514ff455156c4381fAdam Powell     * If there is no drawer with the given gravity this method will return false.
141879f95ce3e660d267831067e514ff455156c4381fAdam Powell     *
141979f95ce3e660d267831067e514ff455156c4381fAdam Powell     * @param drawerGravity Gravity of the drawer to check
142079f95ce3e660d267831067e514ff455156c4381fAdam Powell     * @return true if the given drawer is visible on-screen
142179f95ce3e660d267831067e514ff455156c4381fAdam Powell     */
1422a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public boolean isDrawerVisible(@EdgeGravity int drawerGravity) {
142379f95ce3e660d267831067e514ff455156c4381fAdam Powell        final View drawerView = findDrawerWithGravity(drawerGravity);
142479f95ce3e660d267831067e514ff455156c4381fAdam Powell        if (drawerView != null) {
142579f95ce3e660d267831067e514ff455156c4381fAdam Powell            return isDrawerVisible(drawerView);
142679f95ce3e660d267831067e514ff455156c4381fAdam Powell        }
142779f95ce3e660d267831067e514ff455156c4381fAdam Powell        return false;
142879f95ce3e660d267831067e514ff455156c4381fAdam Powell    }
142979f95ce3e660d267831067e514ff455156c4381fAdam Powell
1430ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    private boolean hasPeekingDrawer() {
1431ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        final int childCount = getChildCount();
1432ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        for (int i = 0; i < childCount; i++) {
1433ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            final LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams();
1434ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            if (lp.isPeeking) {
1435ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                return true;
1436ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            }
1437ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        }
1438ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        return false;
1439ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    }
1440ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell
14411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
14421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
14431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
14441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
14451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
14471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
14481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return p instanceof LayoutParams
14491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                ? new LayoutParams((LayoutParams) p)
145000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                : p instanceof ViewGroup.MarginLayoutParams
145100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                ? new LayoutParams((MarginLayoutParams) p)
14521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                : new LayoutParams(p);
14531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
14541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
14561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
14571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return p instanceof LayoutParams && super.checkLayoutParams(p);
14581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
14591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
14611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
14621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return new LayoutParams(getContext(), attrs);
14631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
14641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1465791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    private boolean hasVisibleDrawer() {
14660492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        return findVisibleDrawer() != null;
14670492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
14680492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
14690492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    private View findVisibleDrawer() {
1470791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        final int childCount = getChildCount();
1471791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        for (int i = 0; i < childCount; i++) {
1472791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            final View child = getChildAt(i);
1473791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            if (isDrawerView(child) && isDrawerVisible(child)) {
14740492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                return child;
1475791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            }
1476791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        }
14770492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        return null;
1478791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    }
1479791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
1480cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell    void cancelChildViewTouch() {
1481cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell        // Cancel child touches
1482cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell        if (!mChildrenCanceledTouch) {
1483cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            final long now = SystemClock.uptimeMillis();
1484cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            final MotionEvent cancelEvent = MotionEvent.obtain(now, now,
1485cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                    MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
1486cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            final int childCount = getChildCount();
1487cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            for (int i = 0; i < childCount; i++) {
1488cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                getChildAt(i).dispatchTouchEvent(cancelEvent);
1489cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            }
1490cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            cancelEvent.recycle();
1491cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            mChildrenCanceledTouch = true;
1492cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell        }
1493cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell    }
1494cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell
1495791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    @Override
1496791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    public boolean onKeyDown(int keyCode, KeyEvent event) {
1497791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        if (keyCode == KeyEvent.KEYCODE_BACK && hasVisibleDrawer()) {
1498791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            KeyEventCompat.startTracking(event);
1499791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            return true;
1500791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        }
1501791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        return super.onKeyDown(keyCode, event);
1502791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    }
1503791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
1504791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    @Override
1505791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    public boolean onKeyUp(int keyCode, KeyEvent event) {
15060492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        if (keyCode == KeyEvent.KEYCODE_BACK) {
15070492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            final View visibleDrawer = findVisibleDrawer();
15080492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            if (visibleDrawer != null && getDrawerLockMode(visibleDrawer) == LOCK_MODE_UNLOCKED) {
15090492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                closeDrawers();
15100492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            }
15110492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            return visibleDrawer != null;
1512791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        }
1513791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        return super.onKeyUp(keyCode, event);
1514791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    }
1515791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
151657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
151757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected void onRestoreInstanceState(Parcelable state) {
151857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        final SavedState ss = (SavedState) state;
151957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        super.onRestoreInstanceState(ss.getSuperState());
152057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
152157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        if (ss.openDrawerGravity != Gravity.NO_GRAVITY) {
152257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            final View toOpen = findDrawerWithGravity(ss.openDrawerGravity);
152357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            if (toOpen != null) {
152457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                openDrawer(toOpen);
152557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
152657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
15278e01d24e718d603974182cd48f648369c07edec1Adam Powell
15288e01d24e718d603974182cd48f648369c07edec1Adam Powell        setDrawerLockMode(ss.lockModeLeft, Gravity.LEFT);
15298e01d24e718d603974182cd48f648369c07edec1Adam Powell        setDrawerLockMode(ss.lockModeRight, Gravity.RIGHT);
153057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
153157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
153257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
153357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected Parcelable onSaveInstanceState() {
153457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        final Parcelable superState = super.onSaveInstanceState();
153557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        final SavedState ss = new SavedState(superState);
153657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
15372bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        final View openDrawer = findOpenDrawer();
15382bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        if (openDrawer != null) {
15392bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            ss.openDrawerGravity = ((LayoutParams) openDrawer.getLayoutParams()).gravity;
154057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
154157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
15428e01d24e718d603974182cd48f648369c07edec1Adam Powell        ss.lockModeLeft = mLockModeLeft;
15438e01d24e718d603974182cd48f648369c07edec1Adam Powell        ss.lockModeRight = mLockModeRight;
15448e01d24e718d603974182cd48f648369c07edec1Adam Powell
154557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        return ss;
154657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
154757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
154812ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    @Override
154912ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    public void addView(View child, int index, ViewGroup.LayoutParams params) {
15502bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        super.addView(child, index, params);
15512bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette
15522bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        final View openDrawer = findOpenDrawer();
15532bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        if (openDrawer != null || isDrawerView(child)) {
15542bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            // A drawer is already open or the new view is a drawer, so the
15552bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            // new view should start out hidden.
155612ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            ViewCompat.setImportantForAccessibility(child,
155712ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                    ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
15582bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        } else {
15592bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            // Otherwise this is a content view and no drawer is open, so the
15602bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            // new view should start out visible.
156112ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            ViewCompat.setImportantForAccessibility(child,
156212ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                    ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
156312ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        }
15642bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette
15652bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        // We only need a delegate here if the framework doesn't understand
15662bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        // NO_HIDE_DESCENDANTS importance.
15672bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        if (!CAN_HIDE_DESCENDANTS) {
15682bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            ViewCompat.setAccessibilityDelegate(child, mChildAccessibilityDelegate);
15692bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        }
157012ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    }
157112ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
157249733ad715bcf68cc178f53e17a79380d332e5ccAlan Viverette    private static boolean includeChildForAccessibility(View child) {
157312ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        // If the child is not important for accessibility we make
157412ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        // sure this hides the entire subtree rooted at it as the
157512ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        // IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDATS is not
157612ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        // supported on older platforms but we want to hide the entire
157712ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        // content and not opened drawers if a drawer is opened.
157812ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        return ViewCompat.getImportantForAccessibility(child)
157912ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                != ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
158012ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                    && ViewCompat.getImportantForAccessibility(child)
158112ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                != ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO;
158212ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    }
158312ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
158457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    /**
158557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell     * State persisted across instances
158657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell     */
158757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected static class SavedState extends BaseSavedState {
158857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        int openDrawerGravity = Gravity.NO_GRAVITY;
15898e01d24e718d603974182cd48f648369c07edec1Adam Powell        int lockModeLeft = LOCK_MODE_UNLOCKED;
15908e01d24e718d603974182cd48f648369c07edec1Adam Powell        int lockModeRight = LOCK_MODE_UNLOCKED;
159157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
159257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        public SavedState(Parcel in) {
159357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            super(in);
159457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            openDrawerGravity = in.readInt();
159557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
159657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
159757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        public SavedState(Parcelable superState) {
159857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            super(superState);
159957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
160057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
160157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        @Override
160257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        public void writeToParcel(Parcel dest, int flags) {
160357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            super.writeToParcel(dest, flags);
160457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            dest.writeInt(openDrawerGravity);
160557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
160657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
160757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        public static final Parcelable.Creator<SavedState> CREATOR =
160857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                new Parcelable.Creator<SavedState>() {
160957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            @Override
161057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            public SavedState createFromParcel(Parcel source) {
161157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                return new SavedState(source);
161257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
161357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
161457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            @Override
161557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            public SavedState[] newArray(int size) {
161657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                return new SavedState[size];
161757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
161857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        };
161957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
162057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
16211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private class ViewDragCallback extends ViewDragHelper.Callback {
1622f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        private final int mAbsGravity;
16231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        private ViewDragHelper mDragger;
16241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16251732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        private final Runnable mPeekRunnable = new Runnable() {
16261732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            @Override public void run() {
16271732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                peekDrawer();
16281732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            }
16291732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        };
16301732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
16311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public ViewDragCallback(int gravity) {
1632f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            mAbsGravity = gravity;
16331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
16341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void setDragger(ViewDragHelper dragger) {
16361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mDragger = dragger;
16371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
16381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16391732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        public void removeCallbacks() {
16401732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            DrawerLayout.this.removeCallbacks(mPeekRunnable);
16411732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        }
16421732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
16431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
16441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public boolean tryCaptureView(View child, int pointerId) {
16451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // Only capture views where the gravity matches what we're looking for.
16461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // This lets us use two ViewDragHelpers, one for each side drawer.
1647f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            return isDrawerView(child) && checkDrawerViewAbsoluteGravity(child, mAbsGravity)
1648f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                    && getDrawerLockMode(child) == LOCK_MODE_UNLOCKED;
16491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
16501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
16521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewDragStateChanged(int state) {
1653f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            updateDrawerState(mAbsGravity, state, mDragger.getCapturedView());
16541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
16551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
16571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
16581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            float offset;
16591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childWidth = changedView.getWidth();
16601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // This reverses the positioning shown in onLayout.
1662f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if (checkDrawerViewAbsoluteGravity(changedView, Gravity.LEFT)) {
16631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                offset = (float) (childWidth + left) / childWidth;
16641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
16651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int width = getWidth();
16661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                offset = (float) (width - left) / childWidth;
16671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
16681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            setDrawerViewOffset(changedView, offset);
1669b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            changedView.setVisibility(offset == 0 ? INVISIBLE : VISIBLE);
16701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            invalidate();
16711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
16721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
16741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewCaptured(View capturedChild, int activePointerId) {
16751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final LayoutParams lp = (LayoutParams) capturedChild.getLayoutParams();
16761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            lp.isPeeking = false;
16771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            closeOtherDrawer();
16791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
16801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        private void closeOtherDrawer() {
1682f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            final int otherGrav = mAbsGravity == Gravity.LEFT ? Gravity.RIGHT : Gravity.LEFT;
16831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View toClose = findDrawerWithGravity(otherGrav);
16841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (toClose != null) {
16851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawer(toClose);
16861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
16871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
16881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
16901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewReleased(View releasedChild, float xvel, float yvel) {
16911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // Offset is how open the drawer is, therefore left/right values
16921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // are reversed from one another.
16931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final float offset = getDrawerViewOffset(releasedChild);
16941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childWidth = releasedChild.getWidth();
16951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            int left;
1697f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if (checkDrawerViewAbsoluteGravity(releasedChild, Gravity.LEFT)) {
16981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                left = xvel > 0 || xvel == 0 && offset > 0.5f ? 0 : -childWidth;
16991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
17001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int width = getWidth();
17017d690eb050d901c7a7b4ebc3896471124ef98f7cAdam Powell                left = xvel < 0 || xvel == 0 && offset > 0.5f ? width - childWidth : width;
17021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
17031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
17041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mDragger.settleCapturedViewAt(left, releasedChild.getTop());
17051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            invalidate();
17061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
17071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
17081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
17091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onEdgeTouched(int edgeFlags, int pointerId) {
17101732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            postDelayed(mPeekRunnable, PEEK_DELAY);
17111732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        }
17121732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
17131732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        private void peekDrawer() {
17141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View toCapture;
17151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childLeft;
1716ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            final int peekDistance = mDragger.getEdgeSize();
1717f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            final boolean leftEdge = mAbsGravity == Gravity.LEFT;
1718b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            if (leftEdge) {
17191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.LEFT);
1720ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                childLeft = (toCapture != null ? -toCapture.getWidth() : 0) + peekDistance;
17211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
17221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.RIGHT);
1723ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                childLeft = getWidth() - peekDistance;
17241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
17250492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            // Only peek if it would mean making the drawer more visible and the drawer isn't locked
1726b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            if (toCapture != null && ((leftEdge && toCapture.getLeft() < childLeft) ||
17270492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                    (!leftEdge && toCapture.getLeft() > childLeft)) &&
17280492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                    getDrawerLockMode(toCapture) == LOCK_MODE_UNLOCKED) {
1729b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                final LayoutParams lp = (LayoutParams) toCapture.getLayoutParams();
17301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mDragger.smoothSlideViewTo(toCapture, childLeft, toCapture.getTop());
1731b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                lp.isPeeking = true;
17321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                invalidate();
17331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
17341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeOtherDrawer();
1735cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell
1736cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                cancelChildViewTouch();
17371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
17381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
17391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
17401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
1741ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        public boolean onEdgeLock(int edgeFlags) {
1742ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            if (ALLOW_EDGE_LOCK) {
1743f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                final View drawer = findDrawerWithGravity(mAbsGravity);
1744ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                if (drawer != null && !isDrawerOpen(drawer)) {
1745ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                    closeDrawer(drawer);
1746ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                }
1747ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                return true;
1748acc82321ad119706485db342eaa12b225fa9b667Adam Powell            }
1749ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            return false;
1750acc82321ad119706485db342eaa12b225fa9b667Adam Powell        }
1751acc82321ad119706485db342eaa12b225fa9b667Adam Powell
1752acc82321ad119706485db342eaa12b225fa9b667Adam Powell        @Override
17531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onEdgeDragStarted(int edgeFlags, int pointerId) {
17541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View toCapture;
17551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if ((edgeFlags & ViewDragHelper.EDGE_LEFT) == ViewDragHelper.EDGE_LEFT) {
17561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.LEFT);
17571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
17581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.RIGHT);
17591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
17601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
17610492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            if (toCapture != null && getDrawerLockMode(toCapture) == LOCK_MODE_UNLOCKED) {
17621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mDragger.captureChildView(toCapture, pointerId);
17631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
17641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
17651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
17661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
17671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public int getViewHorizontalDragRange(View child) {
17688a28dd16be442db2ee6275baf72079777627f37eChet Haase            return isDrawerView(child) ? child.getWidth() : 0;
17691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
17701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
17711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
17721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public int clampViewPositionHorizontal(View child, int left, int dx) {
1773f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if (checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) {
17741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                return Math.max(-child.getWidth(), Math.min(left, 0));
17751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
17761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int width = getWidth();
17771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                return Math.max(width - child.getWidth(), Math.min(left, width));
17781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
17791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
178000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
178100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        @Override
178200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        public int clampViewPositionVertical(View child, int top, int dy) {
178300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell            return child.getTop();
178400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        }
17851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
17861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
178700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell    public static class LayoutParams extends ViewGroup.MarginLayoutParams {
17881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
17891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public int gravity = Gravity.NO_GRAVITY;
1790b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        float onScreen;
17911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean isPeeking;
17921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean knownOpen;
17931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
17941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(Context c, AttributeSet attrs) {
17951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(c, attrs);
17961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
17971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final TypedArray a = c.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
17981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this.gravity = a.getInt(0, Gravity.NO_GRAVITY);
17991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            a.recycle();
18001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
18011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
18021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(int width, int height) {
18031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(width, height);
18041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
18051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
18061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(int width, int height, int gravity) {
18071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this(width, height);
18081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this.gravity = gravity;
18091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
18101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
18111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(LayoutParams source) {
18121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(source);
18131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this.gravity = source.gravity;
18141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
18151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
18161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(ViewGroup.LayoutParams source) {
18171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(source);
18181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
181900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
182000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        public LayoutParams(ViewGroup.MarginLayoutParams source) {
182100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell            super(source);
182200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        }
18231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
18247d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell
18257d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell    class AccessibilityDelegate extends AccessibilityDelegateCompat {
18263cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell        private final Rect mTmpRect = new Rect();
18273cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
18287d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell        @Override
18297d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
18302bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            if (CAN_HIDE_DESCENDANTS) {
18312bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                super.onInitializeAccessibilityNodeInfo(host, info);
18322bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            } else {
18332bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                // Obtain a node for the host, then manually generate the list
18342bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                // of children to only include non-obscured views.
18352bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                final AccessibilityNodeInfoCompat superNode =
18362bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                        AccessibilityNodeInfoCompat.obtain(info);
18372bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                super.onInitializeAccessibilityNodeInfo(host, superNode);
18382bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette
18392bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                info.setSource(host);
18402bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                final ViewParent parent = ViewCompat.getParentForAccessibility(host);
18412bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                if (parent instanceof View) {
18422bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                    info.setParent((View) parent);
18432bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                }
18442bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                copyNodeInfoNoChildren(info, superNode);
18452bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                superNode.recycle();
18463cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
18472bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                addChildrenForAccessibility(info, (ViewGroup) host);
18483cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            }
18493cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
18502bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            info.setClassName(DrawerLayout.class.getName());
18514b1190de13d6408e24cbda5f77e6148f54206fd0Alan Viverette
18524b1190de13d6408e24cbda5f77e6148f54206fd0Alan Viverette            // This view reports itself as focusable so that it can intercept
18534b1190de13d6408e24cbda5f77e6148f54206fd0Alan Viverette            // the back button, but we should prevent this view from reporting
18544b1190de13d6408e24cbda5f77e6148f54206fd0Alan Viverette            // itself as focusable to accessibility services.
18554b1190de13d6408e24cbda5f77e6148f54206fd0Alan Viverette            info.setFocusable(false);
18564b1190de13d6408e24cbda5f77e6148f54206fd0Alan Viverette            info.setFocused(false);
1857d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette        }
1858d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette
1859526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        @Override
1860526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
1861526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            super.onInitializeAccessibilityEvent(host, event);
1862526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
1863526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            event.setClassName(DrawerLayout.class.getName());
1864aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette        }
1865526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
1866aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette        @Override
1867aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
1868526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            // Special case to handle window state change events. As far as
1869aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // accessibility services are concerned, state changes from
1870aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // DrawerLayout invalidate the entire contents of the screen (like
1871aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // an Activity or Dialog) and they should announce the title of the
1872aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // new content.
1873526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
1874526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                final List<CharSequence> eventText = event.getText();
1875526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                final View visibleDrawer = findVisibleDrawer();
1876526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                if (visibleDrawer != null) {
1877526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                    final int edgeGravity = getDrawerViewAbsoluteGravity(visibleDrawer);
1878526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                    final CharSequence title = getDrawerTitle(edgeGravity);
1879526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                    if (title != null) {
1880526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                        eventText.add(title);
1881526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                    }
1882526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                }
1883aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette
1884aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette                return true;
1885526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            }
1886aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette
1887aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            return super.dispatchPopulateAccessibilityEvent(host, event);
1888526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        }
1889526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
18902bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        @Override
18912bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
18922bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                AccessibilityEvent event) {
18932bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            if (CAN_HIDE_DESCENDANTS || includeChildForAccessibility(child)) {
18942bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                return super.onRequestSendAccessibilityEvent(host, child, event);
18952bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            }
18962bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            return false;
18972bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        }
18982bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette
1899d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette        private void addChildrenForAccessibility(AccessibilityNodeInfoCompat info, ViewGroup v) {
1900d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette            final int childCount = v.getChildCount();
19017d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell            for (int i = 0; i < childCount; i++) {
1902d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette                final View child = v.getChildAt(i);
190349733ad715bcf68cc178f53e17a79380d332e5ccAlan Viverette                if (includeChildForAccessibility(child)) {
190412ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                    info.addChild(child);
19057d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell                }
19067d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell            }
19077d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell        }
19087d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell
19093cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell        /**
19103cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell         * This should really be in AccessibilityNodeInfoCompat, but there unfortunately
19113cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell         * seem to be a few elements that are not easily cloneable using the underlying API.
19123cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell         * Leave it private here as it's not general-purpose useful.
19133cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell         */
19143cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell        private void copyNodeInfoNoChildren(AccessibilityNodeInfoCompat dest,
19153cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell                AccessibilityNodeInfoCompat src) {
19163cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            final Rect rect = mTmpRect;
19173cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
19183cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            src.getBoundsInParent(rect);
19193cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setBoundsInParent(rect);
19203cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
19213cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            src.getBoundsInScreen(rect);
19223cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setBoundsInScreen(rect);
19233cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
19243cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setVisibleToUser(src.isVisibleToUser());
19253cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setPackageName(src.getPackageName());
19263cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setClassName(src.getClassName());
19273cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setContentDescription(src.getContentDescription());
19283cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
19293cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setEnabled(src.isEnabled());
19303cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setClickable(src.isClickable());
19313cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setFocusable(src.isFocusable());
19323cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setFocused(src.isFocused());
19333cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setAccessibilityFocused(src.isAccessibilityFocused());
19343cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setSelected(src.isSelected());
19353cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setLongClickable(src.isLongClickable());
19363cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
19373cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.addAction(src.getActions());
19383cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell        }
19397d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell    }
194012ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
194112ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    final class ChildAccessibilityDelegate extends AccessibilityDelegateCompat {
194212ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        @Override
194312ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        public void onInitializeAccessibilityNodeInfo(View child,
194412ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                AccessibilityNodeInfoCompat info) {
194512ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            super.onInitializeAccessibilityNodeInfo(child, info);
19462bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette
194749733ad715bcf68cc178f53e17a79380d332e5ccAlan Viverette            if (!includeChildForAccessibility(child)) {
194812ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                // If we are ignoring the sub-tree rooted at the child,
194912ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                // break the connection to the rest of the node tree.
195049733ad715bcf68cc178f53e17a79380d332e5ccAlan Viverette                // For details refer to includeChildForAccessibility.
195112ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                info.setParent(null);
195212ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            }
195312ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        }
195412ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    }
19551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell}
1956