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;
3270acb0c19be3831a2080e4f902324de16bfbf62eTor Norbyeimport android.support.annotation.ColorInt;
33a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbyeimport android.support.annotation.DrawableRes;
34a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbyeimport android.support.annotation.IntDef;
353eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banesimport android.support.annotation.NonNull;
36a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbyeimport android.support.annotation.Nullable;
37f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powellimport android.support.v4.content.ContextCompat;
38621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liuimport android.support.v4.graphics.drawable.DrawableCompat;
3905f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banesimport android.support.v4.os.ParcelableCompat;
4005f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banesimport android.support.v4.os.ParcelableCompatCreatorCallbacks;
4105f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banesimport android.support.v4.view.AbsSavedState;
427d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powellimport android.support.v4.view.AccessibilityDelegateCompat;
431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.support.v4.view.GravityCompat;
441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.support.v4.view.MotionEventCompat;
451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.support.v4.view.ViewCompat;
461b8262b87426b2f766b40d6ab4eaeac296d5c2feAdam Powellimport android.support.v4.view.ViewGroupCompat;
477d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powellimport android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
480a13063f56de4a369ee20e62494dcdda9e37f966Alan Viveretteimport android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat;
491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.util.AttributeSet;
501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.Gravity;
51791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powellimport android.view.KeyEvent;
521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.MotionEvent;
531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.View;
541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.ViewGroup;
553cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powellimport android.view.ViewParent;
567d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powellimport android.view.accessibility.AccessibilityEvent;
571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
58a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbyeimport java.lang.annotation.Retention;
59a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbyeimport java.lang.annotation.RetentionPolicy;
60fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukaiimport java.util.ArrayList;
61526ba1382e61845ef23bf27d300883dea0966af5Alan Viveretteimport java.util.List;
62526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell/**
641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * DrawerLayout acts as a top-level container for window content that allows for
65ebe391af34e514420acab4d07fcd26b62a57e490Kirill Grouchnikov * interactive "drawer" views to be pulled out from one or both vertical edges of the window.
661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell *
671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * <p>Drawer positioning and layout is controlled using the <code>android:layout_gravity</code>
6809c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * attribute on child views corresponding to which side of the view you want the drawer
69ebe391af34e514420acab4d07fcd26b62a57e490Kirill Grouchnikov * to emerge from: left or right (or start/end on platform versions that support layout direction.)
70ebe391af34e514420acab4d07fcd26b62a57e490Kirill Grouchnikov * Note that you can only have one drawer view for each vertical edge of the window. If your
71ebe391af34e514420acab4d07fcd26b62a57e490Kirill Grouchnikov * layout configures more than one drawer view per vertical edge of the window, an exception will
72ebe391af34e514420acab4d07fcd26b62a57e490Kirill Grouchnikov * be thrown at runtime.
7309c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * </p>
7409c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell *
7509c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * <p>To use a DrawerLayout, position your primary content view as the first child with
76ebe391af34e514420acab4d07fcd26b62a57e490Kirill Grouchnikov * width and height of <code>match_parent</code> and no <code>layout_gravity></code>.
77ebe391af34e514420acab4d07fcd26b62a57e490Kirill Grouchnikov * Add drawers as child views after the main content view and set the <code>layout_gravity</code>
78ebe391af34e514420acab4d07fcd26b62a57e490Kirill Grouchnikov * appropriately. Drawers commonly use <code>match_parent</code> for height with a fixed width.</p>
7909c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell *
8009c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * <p>{@link DrawerListener} can be used to monitor the state and motion of drawer views.
8109c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * Avoid performing expensive operations such as layout during animation as it can cause
8209c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * stuttering; try to perform expensive operations during the {@link #STATE_IDLE} state.
8309c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * {@link SimpleDrawerListener} offers default/no-op implementations of each callback method.</p>
841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell *
8595572937e188a6f5724bfe1217efd04073e2c705Scott Main * <p>As per the <a href="{@docRoot}design/patterns/navigation-drawer.html">Android Design
8695572937e188a6f5724bfe1217efd04073e2c705Scott Main * guide</a>, any drawers positioned to the left/start should
871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * always contain content for navigating around the application, whereas any drawers
881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * positioned to the right/end should always contain actions to take on the current content.
891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * This preserves the same navigation left, actions right structure present in the Action Bar
901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * and elsewhere.</p>
9195572937e188a6f5724bfe1217efd04073e2c705Scott Main *
9295572937e188a6f5724bfe1217efd04073e2c705Scott Main * <p>For more information about how to use DrawerLayout, read <a
9395572937e188a6f5724bfe1217efd04073e2c705Scott Main * href="{@docRoot}training/implementing-navigation/nav-drawer.html">Creating a Navigation
9495572937e188a6f5724bfe1217efd04073e2c705Scott Main * Drawer</a>.</p>
951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */
96f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powellpublic class DrawerLayout extends ViewGroup implements DrawerLayoutImpl {
971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final String TAG = "DrawerLayout";
981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
99a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    @IntDef({STATE_IDLE, STATE_DRAGGING, STATE_SETTLING})
100a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    @Retention(RetentionPolicy.SOURCE)
101a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    private @interface State {}
102a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye
1031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
1041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Indicates that any drawers are in an idle, settled state. No animation is in progress.
1051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
1061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public static final int STATE_IDLE = ViewDragHelper.STATE_IDLE;
1071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
1091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Indicates that a drawer is currently being dragged by the user.
1101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
1111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public static final int STATE_DRAGGING = ViewDragHelper.STATE_DRAGGING;
1121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
1141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Indicates that a drawer is in the process of settling to a final position.
1151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
1161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public static final int STATE_SETTLING = ViewDragHelper.STATE_SETTLING;
1171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
118b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov    @IntDef({LOCK_MODE_UNLOCKED, LOCK_MODE_LOCKED_CLOSED, LOCK_MODE_LOCKED_OPEN,
119b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            LOCK_MODE_UNDEFINED})
120a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    @Retention(RetentionPolicy.SOURCE)
121a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    private @interface LockMode {}
122a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye
1230492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
1240492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * The drawer is unlocked.
1250492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
1260492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public static final int LOCK_MODE_UNLOCKED = 0;
1270492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
1280492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
1290492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * The drawer is locked closed. The user may not open it, though
1300492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * the app may open it programmatically.
1310492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
1320492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public static final int LOCK_MODE_LOCKED_CLOSED = 1;
1330492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
1340492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
1350492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * The drawer is locked open. The user may not close it, though the app
1360492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * may close it programmatically.
1370492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
1380492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public static final int LOCK_MODE_LOCKED_OPEN = 2;
1390492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
140b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov    /**
141b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov     * The drawer's lock state is reset to default.
142b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov     */
143b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov    public static final int LOCK_MODE_UNDEFINED = 3;
144b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov
145a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    @IntDef({Gravity.LEFT, Gravity.RIGHT, GravityCompat.START, GravityCompat.END})
146a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    @Retention(RetentionPolicy.SOURCE)
147a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    private @interface EdgeGravity {}
148a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye
149a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye
1501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final int MIN_DRAWER_MARGIN = 64; // dp
151621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    private static final int DRAWER_ELEVATION = 10; //dp
1521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final int DEFAULT_SCRIM_COLOR = 0x99000000;
1541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
155ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    /**
1561732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell     * Length of time to delay before peeking the drawer.
1571732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell     */
1581732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    private static final int PEEK_DELAY = 160; // ms
1591732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
1601732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    /**
16179f95ce3e660d267831067e514ff455156c4381fAdam Powell     * Minimum velocity that will be detected as a fling
16279f95ce3e660d267831067e514ff455156c4381fAdam Powell     */
16379f95ce3e660d267831067e514ff455156c4381fAdam Powell    private static final int MIN_FLING_VELOCITY = 400; // dips per second
16479f95ce3e660d267831067e514ff455156c4381fAdam Powell
16579f95ce3e660d267831067e514ff455156c4381fAdam Powell    /**
166ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell     * Experimental feature.
167ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell     */
168ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    private static final boolean ALLOW_EDGE_LOCK = false;
169ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell
17086559d86173efb890a8edf48d935cfebfaccf049Adam Powell    private static final boolean CHILDREN_DISALLOW_INTERCEPT = true;
17186559d86173efb890a8edf48d935cfebfaccf049Adam Powell
17286559d86173efb890a8edf48d935cfebfaccf049Adam Powell    private static final float TOUCH_SLOP_SENSITIVITY = 1.f;
17386559d86173efb890a8edf48d935cfebfaccf049Adam Powell
174540222c3675801eaa141ace1c164c4d3499b4721Aurimas Liutikas    static final int[] LAYOUT_ATTRS = new int[] {
1751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            android.R.attr.layout_gravity
1761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    };
1771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1782bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette    /** Whether we can use NO_HIDE_DESCENDANTS accessibility importance. */
179540222c3675801eaa141ace1c164c4d3499b4721Aurimas Liutikas    static final boolean CAN_HIDE_DESCENDANTS = Build.VERSION.SDK_INT >= 19;
1802bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette
181621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    /** Whether the drawer shadow comes from setting elevation on the drawer. */
182621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    private static final boolean SET_DRAWER_SHADOW_FROM_ELEVATION =
183621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            Build.VERSION.SDK_INT >= 21;
184621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu
18512ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    private final ChildAccessibilityDelegate mChildAccessibilityDelegate =
18612ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            new ChildAccessibilityDelegate();
187621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    private float mDrawerElevation;
18812ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
1891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private int mMinDrawerMargin;
1901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private int mScrimColor = DEFAULT_SCRIM_COLOR;
1921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private float mScrimOpacity;
1931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private Paint mScrimPaint = new Paint();
1941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private final ViewDragHelper mLeftDragger;
1961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private final ViewDragHelper mRightDragger;
1971732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    private final ViewDragCallback mLeftCallback;
1981732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    private final ViewDragCallback mRightCallback;
1991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private int mDrawerState;
200b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    private boolean mInLayout;
20157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    private boolean mFirstLayout = true;
202b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov
203b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov    private @LockMode int mLockModeLeft = LOCK_MODE_UNDEFINED;
204b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov    private @LockMode int mLockModeRight = LOCK_MODE_UNDEFINED;
205b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov    private @LockMode int mLockModeStart = LOCK_MODE_UNDEFINED;
206b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov    private @LockMode int mLockModeEnd = LOCK_MODE_UNDEFINED;
207b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov
2081732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell    private boolean mDisallowInterceptRequested;
209cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell    private boolean mChildrenCanceledTouch;
2101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
211d805095048f6be52cddbd572ee343c4639ba8187Alan Viverette    private @Nullable DrawerListener mListener;
2123eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes    private List<DrawerListener> mListeners;
2131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private float mInitialMotionX;
2151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private float mInitialMotionY;
2161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
217f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    private Drawable mStatusBarBackground;
218621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    private Drawable mShadowLeftResolved;
219621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    private Drawable mShadowRightResolved;
220b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
221526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    private CharSequence mTitleLeft;
222526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    private CharSequence mTitleRight;
223526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
224f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    private Object mLastInsets;
225f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    private boolean mDrawStatusBarBackground;
226f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
227621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    /** Shadow drawables for different gravity */
228621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    private Drawable mShadowStart = null;
229621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    private Drawable mShadowEnd = null;
230621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    private Drawable mShadowLeft = null;
231621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    private Drawable mShadowRight = null;
232621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu
233fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai    private final ArrayList<View> mNonDrawerViews;
234fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai
2351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
2361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Listener for monitoring events about drawers.
2371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
2381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public interface DrawerListener {
2391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
2401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when a drawer's position changes.
2411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param drawerView The child view that was moved
2421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param slideOffset The new offset of this drawer within its range, from 0-1
2431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
2444d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas        void onDrawerSlide(View drawerView, float slideOffset);
2451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
2471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when a drawer has settled in a completely open state.
2481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * The drawer is interactive at this point.
2491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         *
2501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param drawerView Drawer view that is now open
2511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
2524d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas        void onDrawerOpened(View drawerView);
2531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
2551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when a drawer has settled in a completely closed state.
2561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         *
2571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param drawerView Drawer view that is now closed
2581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
2594d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas        void onDrawerClosed(View drawerView);
2601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
2621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when the drawer motion state changes. The new state will
2631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * be one of {@link #STATE_IDLE}, {@link #STATE_DRAGGING} or {@link #STATE_SETTLING}.
2641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         *
2651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param newState The new drawer motion state
2661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
2674d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas        void onDrawerStateChanged(@State int newState);
2681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
2691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
270b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
271b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Stub/no-op implementations of all methods of {@link DrawerListener}.
272b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Override this if you only care about a few of the available callback methods.
273b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
2744d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas    public abstract static class SimpleDrawerListener implements DrawerListener {
275b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
276b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerSlide(View drawerView, float slideOffset) {
277b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
278b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
279b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
280b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerOpened(View drawerView) {
281b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
282b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
283b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
284b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerClosed(View drawerView) {
285b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
286b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
287b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
288b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerStateChanged(int newState) {
289b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
290b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
291b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
292f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    interface DrawerLayoutCompatImpl {
293f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        void configureApplyInsets(View drawerLayout);
294f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        void dispatchChildInsets(View child, Object insets, int drawerGravity);
295f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        void applyMarginInsets(MarginLayoutParams lp, Object insets, int drawerGravity);
296f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        int getTopInset(Object lastInsets);
29784cdd567de45ea632670d51da5fb4545248d073bChris Banes        Drawable getDefaultStatusBarBackground(Context context);
298f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    }
299f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
300f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    static class DrawerLayoutCompatImplBase implements DrawerLayoutCompatImpl {
30115375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas        @Override
302f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        public void configureApplyInsets(View drawerLayout) {
303f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            // This space for rent
304f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
305f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
30615375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas        @Override
307f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        public void dispatchChildInsets(View child, Object insets, int drawerGravity) {
308f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            // This space for rent
309f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
310f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
31115375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas        @Override
312f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        public void applyMarginInsets(MarginLayoutParams lp, Object insets, int drawerGravity) {
313f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            // This space for rent
314f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
315f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
31615375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas        @Override
317f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        public int getTopInset(Object insets) {
318f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            return 0;
319f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
32084cdd567de45ea632670d51da5fb4545248d073bChris Banes
32184cdd567de45ea632670d51da5fb4545248d073bChris Banes        @Override
32284cdd567de45ea632670d51da5fb4545248d073bChris Banes        public Drawable getDefaultStatusBarBackground(Context context) {
32384cdd567de45ea632670d51da5fb4545248d073bChris Banes            return null;
32484cdd567de45ea632670d51da5fb4545248d073bChris Banes        }
325f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    }
326f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
327f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    static class DrawerLayoutCompatImplApi21 implements DrawerLayoutCompatImpl {
32815375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas        @Override
329f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        public void configureApplyInsets(View drawerLayout) {
330f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            DrawerLayoutCompatApi21.configureApplyInsets(drawerLayout);
331f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
332f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
33315375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas        @Override
334f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        public void dispatchChildInsets(View child, Object insets, int drawerGravity) {
335f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            DrawerLayoutCompatApi21.dispatchChildInsets(child, insets, drawerGravity);
336f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
337f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
33815375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas        @Override
339f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        public void applyMarginInsets(MarginLayoutParams lp, Object insets, int drawerGravity) {
340f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            DrawerLayoutCompatApi21.applyMarginInsets(lp, insets, drawerGravity);
341f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
342f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
34315375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas        @Override
344f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        public int getTopInset(Object insets) {
345f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            return DrawerLayoutCompatApi21.getTopInset(insets);
346f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
34784cdd567de45ea632670d51da5fb4545248d073bChris Banes
34884cdd567de45ea632670d51da5fb4545248d073bChris Banes        @Override
34984cdd567de45ea632670d51da5fb4545248d073bChris Banes        public Drawable getDefaultStatusBarBackground(Context context) {
35084cdd567de45ea632670d51da5fb4545248d073bChris Banes            return DrawerLayoutCompatApi21.getDefaultStatusBarBackground(context);
35184cdd567de45ea632670d51da5fb4545248d073bChris Banes        }
352f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    }
353f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
354f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    static {
355f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        final int version = Build.VERSION.SDK_INT;
356f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        if (version >= 21) {
357f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            IMPL = new DrawerLayoutCompatImplApi21();
358f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        } else {
359f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            IMPL = new DrawerLayoutCompatImplBase();
360f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
361f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    }
362f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
363f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    static final DrawerLayoutCompatImpl IMPL;
364f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
3651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public DrawerLayout(Context context) {
3661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        this(context, null);
3671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
3681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public DrawerLayout(Context context, AttributeSet attrs) {
3701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        this(context, attrs, 0);
3711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
3721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public DrawerLayout(Context context, AttributeSet attrs, int defStyle) {
3741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        super(context, attrs, defStyle);
3754a069be655204ec079c03a09157e5d4ec223a0f7Yigit Boyar        setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
3761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final float density = getResources().getDisplayMetrics().density;
3771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mMinDrawerMargin = (int) (MIN_DRAWER_MARGIN * density + 0.5f);
37879f95ce3e660d267831067e514ff455156c4381fAdam Powell        final float minVel = MIN_FLING_VELOCITY * density;
3791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3801732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mLeftCallback = new ViewDragCallback(Gravity.LEFT);
3811732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mRightCallback = new ViewDragCallback(Gravity.RIGHT);
3821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
38386559d86173efb890a8edf48d935cfebfaccf049Adam Powell        mLeftDragger = ViewDragHelper.create(this, TOUCH_SLOP_SENSITIVITY, mLeftCallback);
3841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mLeftDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
38579f95ce3e660d267831067e514ff455156c4381fAdam Powell        mLeftDragger.setMinVelocity(minVel);
3861732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mLeftCallback.setDragger(mLeftDragger);
3871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
38886559d86173efb890a8edf48d935cfebfaccf049Adam Powell        mRightDragger = ViewDragHelper.create(this, TOUCH_SLOP_SENSITIVITY, mRightCallback);
3891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mRightDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_RIGHT);
39079f95ce3e660d267831067e514ff455156c4381fAdam Powell        mRightDragger.setMinVelocity(minVel);
3911732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mRightCallback.setDragger(mRightDragger);
392791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
393791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        // So that we can catch the back button
394791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        setFocusableInTouchMode(true);
3957d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell
39612ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        ViewCompat.setImportantForAccessibility(this,
39712ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
39812ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
3997d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell        ViewCompat.setAccessibilityDelegate(this, new AccessibilityDelegate());
4001b8262b87426b2f766b40d6ab4eaeac296d5c2feAdam Powell        ViewGroupCompat.setMotionEventSplittingEnabled(this, false);
40199cb2bbfcd84bdc2e89a5a2d11b6b69132169ea6Adam Powell        if (ViewCompat.getFitsSystemWindows(this)) {
40299cb2bbfcd84bdc2e89a5a2d11b6b69132169ea6Adam Powell            IMPL.configureApplyInsets(this);
40384cdd567de45ea632670d51da5fb4545248d073bChris Banes            mStatusBarBackground = IMPL.getDefaultStatusBarBackground(context);
40499cb2bbfcd84bdc2e89a5a2d11b6b69132169ea6Adam Powell        }
405621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu
406621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        mDrawerElevation = DRAWER_ELEVATION * density;
407fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai
408fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai        mNonDrawerViews = new ArrayList<View>();
409621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    }
410621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu
411621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    /**
412621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * Sets the base elevation of the drawer(s) relative to the parent, in pixels. Note that the
413621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * elevation change is only supported in API 21 and above.
414621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     *
415621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * @param elevation The base depth position of the view, in pixels.
416621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     */
417621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    public void setDrawerElevation(float elevation) {
418621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        mDrawerElevation = elevation;
419621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        for (int i = 0; i < getChildCount(); i++) {
420621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            View child = getChildAt(i);
421621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            if (isDrawerView(child)) {
422621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                ViewCompat.setElevation(child, mDrawerElevation);
423621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            }
424621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        }
425621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    }
426621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu
427621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    /**
428621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * The base elevation of the drawer(s) relative to the parent, in pixels. Note that the
429621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * elevation change is only supported in API 21 and above. For unsupported API levels, 0 will
430621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * be returned as the elevation.
431621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     *
432621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * @return The base depth position of the view, in pixels.
433621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     */
434621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    public float getDrawerElevation() {
435621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        if (SET_DRAWER_SHADOW_FROM_ELEVATION) {
436621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            return mDrawerElevation;
437621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        }
438621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        return 0f;
439f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    }
440f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
441f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    /**
442f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * @hide Internal use only; called to apply window insets when configured
443f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * with fitsSystemWindows="true"
444f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     */
445f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    @Override
446f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    public void setChildInsets(Object insets, boolean draw) {
447f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        mLastInsets = insets;
448f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        mDrawStatusBarBackground = draw;
449f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        setWillNotDraw(!draw && getBackground() == null);
450f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        requestLayout();
4511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
4521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
454621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * Set a simple drawable used for the left or right shadow. The drawable provided must have a
455621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * nonzero intrinsic width. For API 21 and above, an elevation will be set on the drawer
456621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * instead of the drawable provided.
457621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     *
458621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * <p>Note that for better support for both left-to-right and right-to-left layout
459621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * directions, a drawable for RTL layout (in additional to the one in LTR layout) can be
460621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * defined with a resource qualifier "ldrtl" for API 17 and above with the gravity
461621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * {@link GravityCompat#START}. Alternatively, for API 23 and above, the drawable can
462621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * auto-mirrored such that the drawable will be mirrored in RTL layout.</p>
463b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
464b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param shadowDrawable Shadow drawable to use at the edge of a drawer
465b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param gravity Which drawer the shadow should apply to
466b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
467a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public void setDrawerShadow(Drawable shadowDrawable, @EdgeGravity int gravity) {
468b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        /*
469b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         * TODO Someone someday might want to set more complex drawables here.
470b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         * They're probably nuts, but we might want to consider registering callbacks,
471b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         * setting states, etc. properly.
472b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         */
473621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        if (SET_DRAWER_SHADOW_FROM_ELEVATION) {
474621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            // No op. Drawer shadow will come from setting an elevation on the drawer.
475621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            return;
476b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
477621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        if ((gravity & GravityCompat.START) == GravityCompat.START) {
478621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            mShadowStart = shadowDrawable;
479621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        } else if ((gravity & GravityCompat.END) == GravityCompat.END) {
480621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            mShadowEnd = shadowDrawable;
481621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        } else if ((gravity & Gravity.LEFT) == Gravity.LEFT) {
482621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            mShadowLeft = shadowDrawable;
483621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        } else if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) {
484b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowRight = shadowDrawable;
485621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        } else {
486621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            return;
487b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
488621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        resolveShadowDrawables();
489621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        invalidate();
490b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
491b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
492b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
493621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * Set a simple drawable used for the left or right shadow. The drawable provided must have a
494621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * nonzero intrinsic width. For API 21 and above, an elevation will be set on the drawer
495621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * instead of the drawable provided.
496621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     *
497621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * <p>Note that for better support for both left-to-right and right-to-left layout
498621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * directions, a drawable for RTL layout (in additional to the one in LTR layout) can be
499621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * defined with a resource qualifier "ldrtl" for API 17 and above with the gravity
500621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * {@link GravityCompat#START}. Alternatively, for API 23 and above, the drawable can
501621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * auto-mirrored such that the drawable will be mirrored in RTL layout.</p>
502b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
503b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param resId Resource id of a shadow drawable to use at the edge of a drawer
504b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param gravity Which drawer the shadow should apply to
505b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
506a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public void setDrawerShadow(@DrawableRes int resId, @EdgeGravity int gravity) {
507e5faeaff97f60817cde21f0f92513845355a7d0dAurimas Liutikas        setDrawerShadow(ContextCompat.getDrawable(getContext(), resId), gravity);
508b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
509b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
510b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
511fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell     * Set a color to use for the scrim that obscures primary content while a drawer is open.
512fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell     *
513fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell     * @param color Color to use in 0xAARRGGBB format.
514fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell     */
51570acb0c19be3831a2080e4f902324de16bfbf62eTor Norbye    public void setScrimColor(@ColorInt int color) {
516fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell        mScrimColor = color;
517fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell        invalidate();
518fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell    }
519fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell
520fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell    /**
5213eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes     * Set a listener to be notified of drawer events. Note that this method is deprecated
5223eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes     * and you should use {@link #addDrawerListener(DrawerListener)} to add a listener and
5233eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes     * {@link #removeDrawerListener(DrawerListener)} to remove a registered listener.
5241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
5251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param listener Listener to notify when drawer events occur
526d805095048f6be52cddbd572ee343c4639ba8187Alan Viverette     * @deprecated Use {@link #addDrawerListener(DrawerListener)}
5271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @see DrawerListener
5283eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes     * @see #addDrawerListener(DrawerListener)
5293eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes     * @see #removeDrawerListener(DrawerListener)
5301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
5313eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes    @Deprecated
5321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void setDrawerListener(DrawerListener listener) {
5333eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes        // The logic in this method emulates what we had before support for multiple
5343eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes        // registered listeners.
5353eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes        if (mListener != null) {
5363eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes            removeDrawerListener(mListener);
5373eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes        }
5383eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes        if (listener != null) {
5393eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes            addDrawerListener(listener);
5403eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes        }
5413eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes        // Update the deprecated field so that we can remove the passed listener the next
5423eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes        // time we're called
5431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mListener = listener;
5441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
5451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
5473eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes     * Adds the specified listener to the list of listeners that will be notified of drawer events.
5483eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes     *
5493eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes     * @param listener Listener to notify when drawer events occur.
5503eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes     * @see #removeDrawerListener(DrawerListener)
5513eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes     */
5523eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes    public void addDrawerListener(@NonNull DrawerListener listener) {
5533eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes        if (listener == null) {
5543eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes            return;
5553eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes        }
5563eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes        if (mListeners == null) {
5573eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes            mListeners = new ArrayList<DrawerListener>();
5583eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes        }
5593eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes        mListeners.add(listener);
5603eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes    }
5613eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes
5623eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes    /**
5633eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes     * Removes the specified listener from the list of listeners that will be notified of drawer
5643eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes     * events.
5653eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes     *
5663eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes     * @param listener Listener to remove from being notified of drawer events
5673eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes     * @see #addDrawerListener(DrawerListener)
5683eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes     */
5693eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes    public void removeDrawerListener(@NonNull DrawerListener listener) {
5703eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes        if (listener == null) {
5713eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes            return;
5723eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes        }
573c19888d785a8ae316c580086c7a8c3fb30f41870Kirill Grouchnikov        if (mListeners == null) {
574c19888d785a8ae316c580086c7a8c3fb30f41870Kirill Grouchnikov            // This can happen if this method is called before the first call to addDrawerListener
575c19888d785a8ae316c580086c7a8c3fb30f41870Kirill Grouchnikov            return;
576c19888d785a8ae316c580086c7a8c3fb30f41870Kirill Grouchnikov        }
5773eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes        mListeners.remove(listener);
5783eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes    }
5793eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes
5803eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes    /**
5810492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Enable or disable interaction with all drawers.
5820492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
5830492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>This allows the application to restrict the user's ability to open or close
5840492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * any drawer within this layout. DrawerLayout will still respond to calls to
5850492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * {@link #openDrawer(int)}, {@link #closeDrawer(int)} and friends if a drawer is locked.</p>
5860492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
5870492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>Locking drawers open or closed will implicitly open or close
5880492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * any drawers as appropriate.</p>
5890492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
5900492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param lockMode The new lock mode for the given drawer. One of {@link #LOCK_MODE_UNLOCKED},
5910492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *                 {@link #LOCK_MODE_LOCKED_CLOSED} or {@link #LOCK_MODE_LOCKED_OPEN}.
5920492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
593a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public void setDrawerLockMode(@LockMode int lockMode) {
5940492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        setDrawerLockMode(lockMode, Gravity.LEFT);
5950492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        setDrawerLockMode(lockMode, Gravity.RIGHT);
5960492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
5970492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
5980492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
5990492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Enable or disable interaction with the given drawer.
6000492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
6010492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>This allows the application to restrict the user's ability to open or close
6020492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * the given drawer. DrawerLayout will still respond to calls to {@link #openDrawer(int)},
6030492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * {@link #closeDrawer(int)} and friends if a drawer is locked.</p>
6040492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
6050492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>Locking a drawer open or closed will implicitly open or close
6060492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * that drawer as appropriate.</p>
6070492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
6080492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param lockMode The new lock mode for the given drawer. One of {@link #LOCK_MODE_UNLOCKED},
6090492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *                 {@link #LOCK_MODE_LOCKED_CLOSED} or {@link #LOCK_MODE_LOCKED_OPEN}.
6100492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param edgeGravity Gravity.LEFT, RIGHT, START or END.
6110492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *                    Expresses which drawer to change the mode for.
6120492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
6130492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_UNLOCKED
6140492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_LOCKED_CLOSED
6150492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_LOCKED_OPEN
6160492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
617a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public void setDrawerLockMode(@LockMode int lockMode, @EdgeGravity int edgeGravity) {
618f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final int absGravity = GravityCompat.getAbsoluteGravity(edgeGravity,
6190492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                ViewCompat.getLayoutDirection(this));
620b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov
621b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov        switch (edgeGravity) {
622b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            case Gravity.LEFT:
623b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                mLockModeLeft = lockMode;
624b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                break;
625b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            case Gravity.RIGHT:
626b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                mLockModeRight = lockMode;
627b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                break;
628b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            case GravityCompat.START:
629b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                mLockModeStart = lockMode;
630b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                break;
631b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            case GravityCompat.END:
632b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                mLockModeEnd = lockMode;
633b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                break;
6340492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
635b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov
6360492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        if (lockMode != LOCK_MODE_UNLOCKED) {
6370492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            // Cancel interaction in progress
638f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            final ViewDragHelper helper = absGravity == Gravity.LEFT ? mLeftDragger : mRightDragger;
6390492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            helper.cancel();
6400492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
6410492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        switch (lockMode) {
6420492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            case LOCK_MODE_LOCKED_OPEN:
643f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                final View toOpen = findDrawerWithGravity(absGravity);
6440492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                if (toOpen != null) {
6450492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                    openDrawer(toOpen);
6460492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                }
6470492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                break;
6480492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            case LOCK_MODE_LOCKED_CLOSED:
649f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                final View toClose = findDrawerWithGravity(absGravity);
6500492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                if (toClose != null) {
6510492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                    closeDrawer(toClose);
6520492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                }
6534d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                break;
6544d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas            // default: do nothing
6550492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
6560492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
6570492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
6580492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
6590492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Enable or disable interaction with the given drawer.
6600492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
6610492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>This allows the application to restrict the user's ability to open or close
6620492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * the given drawer. DrawerLayout will still respond to calls to {@link #openDrawer(int)},
6630492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * {@link #closeDrawer(int)} and friends if a drawer is locked.</p>
6640492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
6650492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * <p>Locking a drawer open or closed will implicitly open or close
6660492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * that drawer as appropriate.</p>
6670492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
6680492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param lockMode The new lock mode for the given drawer. One of {@link #LOCK_MODE_UNLOCKED},
6690492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *                 {@link #LOCK_MODE_LOCKED_CLOSED} or {@link #LOCK_MODE_LOCKED_OPEN}.
6700492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param drawerView The drawer view to change the lock mode for
6710492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
6720492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_UNLOCKED
6730492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_LOCKED_CLOSED
6740492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @see #LOCK_MODE_LOCKED_OPEN
6750492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
676a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public void setDrawerLockMode(@LockMode int lockMode, View drawerView) {
6770492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        if (!isDrawerView(drawerView)) {
6784d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas            throw new IllegalArgumentException("View " + drawerView + " is not a "
6794d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                    + "drawer with appropriate layout_gravity");
6800492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
681f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final int gravity = ((LayoutParams) drawerView.getLayoutParams()).gravity;
682f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        setDrawerLockMode(lockMode, gravity);
6830492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
6840492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
6850492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
6860492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Check the lock mode of the drawer with the given gravity.
6870492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
6880492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param edgeGravity Gravity of the drawer to check
6890492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @return one of {@link #LOCK_MODE_UNLOCKED}, {@link #LOCK_MODE_LOCKED_CLOSED} or
6900492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *         {@link #LOCK_MODE_LOCKED_OPEN}.
6910492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
692a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    @LockMode
693a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public int getDrawerLockMode(@EdgeGravity int edgeGravity) {
694b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov        int layoutDirection = ViewCompat.getLayoutDirection(this);
695b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov
696b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov        switch (edgeGravity) {
697b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            case Gravity.LEFT:
698b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                if (mLockModeLeft != LOCK_MODE_UNDEFINED) {
699b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                    return mLockModeLeft;
700b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                }
7014d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                int leftLockMode = (layoutDirection == ViewCompat.LAYOUT_DIRECTION_LTR)
7024d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                        ? mLockModeStart : mLockModeEnd;
703b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                if (leftLockMode != LOCK_MODE_UNDEFINED) {
704b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                    return leftLockMode;
705b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                }
706b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                break;
707b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            case Gravity.RIGHT:
708b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                if (mLockModeRight != LOCK_MODE_UNDEFINED) {
709b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                    return mLockModeRight;
710b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                }
7114d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                int rightLockMode = (layoutDirection == ViewCompat.LAYOUT_DIRECTION_LTR)
7124d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                        ? mLockModeEnd : mLockModeStart;
713b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                if (rightLockMode != LOCK_MODE_UNDEFINED) {
714b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                    return rightLockMode;
715b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                }
716b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                break;
717b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            case GravityCompat.START:
718b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                if (mLockModeStart != LOCK_MODE_UNDEFINED) {
719b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                    return mLockModeStart;
720b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                }
7214d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                int startLockMode = (layoutDirection == ViewCompat.LAYOUT_DIRECTION_LTR)
7224d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                        ? mLockModeLeft : mLockModeRight;
723b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                if (startLockMode != LOCK_MODE_UNDEFINED) {
724b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                    return startLockMode;
725b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                }
726b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                break;
727b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            case GravityCompat.END:
728b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                if (mLockModeEnd != LOCK_MODE_UNDEFINED) {
729b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                    return mLockModeEnd;
730b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                }
7314d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                int endLockMode = (layoutDirection == ViewCompat.LAYOUT_DIRECTION_LTR)
7324d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                        ? mLockModeRight : mLockModeLeft;
733b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                if (endLockMode != LOCK_MODE_UNDEFINED) {
734b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                    return endLockMode;
735b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                }
736b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov                break;
7370492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
738b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov
7390492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        return LOCK_MODE_UNLOCKED;
7400492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
7410492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
7420492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
7430492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * Check the lock mode of the given drawer view.
7440492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *
7450492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @param drawerView Drawer view to check lock mode
7460492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     * @return one of {@link #LOCK_MODE_UNLOCKED}, {@link #LOCK_MODE_LOCKED_CLOSED} or
7470492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     *         {@link #LOCK_MODE_LOCKED_OPEN}.
7480492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell     */
749a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    @LockMode
7500492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    public int getDrawerLockMode(View drawerView) {
751431713be0958fd0f4d878f5f25755575191fb8baKirill Grouchnikov        if (!isDrawerView(drawerView)) {
752431713be0958fd0f4d878f5f25755575191fb8baKirill Grouchnikov            throw new IllegalArgumentException("View " + drawerView + " is not a drawer");
753431713be0958fd0f4d878f5f25755575191fb8baKirill Grouchnikov        }
754b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov        final int drawerGravity = ((LayoutParams) drawerView.getLayoutParams()).gravity;
755b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov        return getDrawerLockMode(drawerGravity);
7560492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
7570492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
7580492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    /**
759526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * Sets the title of the drawer with the given gravity.
760526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * <p>
761526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * When accessibility is turned on, this is the title that will be used to
762526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * identify the drawer to the active accessibility service.
763526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     *
764526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * @param edgeGravity Gravity.LEFT, RIGHT, START or END. Expresses which
765526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     *            drawer to set the title for.
766526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * @param title The title for the drawer.
767526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     */
768a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public void setDrawerTitle(@EdgeGravity int edgeGravity, CharSequence title) {
769526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        final int absGravity = GravityCompat.getAbsoluteGravity(
770526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                edgeGravity, ViewCompat.getLayoutDirection(this));
771526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        if (absGravity == Gravity.LEFT) {
772526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            mTitleLeft = title;
773526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        } else if (absGravity == Gravity.RIGHT) {
774526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            mTitleRight = title;
775526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        }
776526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    }
777526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
778526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    /**
779526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * Returns the title of the drawer with the given gravity.
780526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     *
781526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * @param edgeGravity Gravity.LEFT, RIGHT, START or END. Expresses which
782526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     *            drawer to return the title for.
783526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * @return The title of the drawer, or null if none set.
784526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     * @see #setDrawerTitle(int, CharSequence)
785526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette     */
786a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    @Nullable
787a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public CharSequence getDrawerTitle(@EdgeGravity int edgeGravity) {
788526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        final int absGravity = GravityCompat.getAbsoluteGravity(
789526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                edgeGravity, ViewCompat.getLayoutDirection(this));
790526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        if (absGravity == Gravity.LEFT) {
791526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            return mTitleLeft;
792526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        } else if (absGravity == Gravity.RIGHT) {
793526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            return mTitleRight;
794526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        }
795526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        return null;
796526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    }
797526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
798526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette    /**
7991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Resolve the shared state of all drawers from the component ViewDragHelpers.
8001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Should be called whenever a ViewDragHelper's state changes.
8011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
802a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    void updateDrawerState(int forGravity, @State int activeState, View activeDrawer) {
8031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int leftState = mLeftDragger.getViewDragState();
8041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int rightState = mRightDragger.getViewDragState();
8051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int state;
8071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (leftState == STATE_DRAGGING || rightState == STATE_DRAGGING) {
8081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            state = STATE_DRAGGING;
8091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        } else if (leftState == STATE_SETTLING || rightState == STATE_SETTLING) {
8101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            state = STATE_SETTLING;
8111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        } else {
8121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            state = STATE_IDLE;
8131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
8141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
815b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (activeDrawer != null && activeState == STATE_IDLE) {
816b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final LayoutParams lp = (LayoutParams) activeDrawer.getLayoutParams();
817b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            if (lp.onScreen == 0) {
818b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                dispatchOnDrawerClosed(activeDrawer);
819b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            } else if (lp.onScreen == 1) {
820b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                dispatchOnDrawerOpened(activeDrawer);
821b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            }
822b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
823b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
8241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (state != mDrawerState) {
8251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mDrawerState = state;
826b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
8273eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes            if (mListeners != null) {
8283eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes                // Notify the listeners. Do that from the end of the list so that if a listener
8293eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes                // removes itself as the result of being called, it won't mess up with our iteration
8303eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes                int listenerCount = mListeners.size();
8313eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes                for (int i = listenerCount - 1; i >= 0; i--) {
8323eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes                    mListeners.get(i).onDrawerStateChanged(state);
8333eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes                }
8341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
8351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
8361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
8371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void dispatchOnDrawerClosed(View drawerView) {
8391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
84067cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov        if ((lp.openState & LayoutParams.FLAG_IS_OPENED) == 1) {
84167cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov            lp.openState = 0;
8423eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes
8433eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes            if (mListeners != null) {
8443eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes                // Notify the listeners. Do that from the end of the list so that if a listener
8453eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes                // removes itself as the result of being called, it won't mess up with our iteration
8463eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes                int listenerCount = mListeners.size();
8473eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes                for (int i = listenerCount - 1; i >= 0; i--) {
8483eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes                    mListeners.get(i).onDrawerClosed(drawerView);
8493eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes                }
8501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
851aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette
8522bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            updateChildrenImportantForAccessibility(drawerView, false);
85312ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
854aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // Only send WINDOW_STATE_CHANGE if the host has window focus. This
855aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // may change if support for multiple foreground windows (e.g. IME)
856aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // improves.
857aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            if (hasWindowFocus()) {
858aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette                final View rootView = getRootView();
859aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette                if (rootView != null) {
860aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette                    rootView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
861aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette                }
862aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            }
8631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
8641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
8651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void dispatchOnDrawerOpened(View drawerView) {
8671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
86867cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov        if ((lp.openState & LayoutParams.FLAG_IS_OPENED) == 0) {
86967cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov            lp.openState = LayoutParams.FLAG_IS_OPENED;
8703eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes            if (mListeners != null) {
8713eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes                // Notify the listeners. Do that from the end of the list so that if a listener
8723eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes                // removes itself as the result of being called, it won't mess up with our iteration
8733eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes                int listenerCount = mListeners.size();
8743eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes                for (int i = listenerCount - 1; i >= 0; i--) {
8753eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes                    mListeners.get(i).onDrawerOpened(drawerView);
8763eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes                }
8771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
87812ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
8792bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            updateChildrenImportantForAccessibility(drawerView, true);
88012ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
881d2f68007428ed6785adcf572d47ed0f8c5c99556Alan Viverette            // Only send WINDOW_STATE_CHANGE if the host has window focus.
882d2f68007428ed6785adcf572d47ed0f8c5c99556Alan Viverette            if (hasWindowFocus()) {
883d2f68007428ed6785adcf572d47ed0f8c5c99556Alan Viverette                sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
884d2f68007428ed6785adcf572d47ed0f8c5c99556Alan Viverette            }
8851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
8861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
8871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8882bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette    private void updateChildrenImportantForAccessibility(View drawerView, boolean isDrawerOpen) {
8892bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        final int childCount = getChildCount();
8902bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        for (int i = 0; i < childCount; i++) {
8912bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            final View child = getChildAt(i);
8922bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            if (!isDrawerOpen && !isDrawerView(child)
8932bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                    || isDrawerOpen && child == drawerView) {
8942bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                // Drawer is closed and this is a content view or this is an
8952bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                // open drawer view, so it should be visible.
8962bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                ViewCompat.setImportantForAccessibility(child,
8972bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                        ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
8982bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            } else {
8992bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                ViewCompat.setImportantForAccessibility(child,
9002bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                        ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
9012bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            }
9022bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        }
9032bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette    }
9042bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette
9051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void dispatchOnDrawerSlide(View drawerView, float slideOffset) {
9063eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes        if (mListeners != null) {
9073eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes            // Notify the listeners. Do that from the end of the list so that if a listener
9083eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes            // removes itself as the result of being called, it won't mess up with our iteration
9093eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes            int listenerCount = mListeners.size();
9103eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes            for (int i = listenerCount - 1; i >= 0; i--) {
9113eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes                mListeners.get(i).onDrawerSlide(drawerView, slideOffset);
9123eb01e183e6eef7610881c8b9c0914afbe23b442Chris Banes            }
9131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
9151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void setDrawerViewOffset(View drawerView, float slideOffset) {
9171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
918b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (slideOffset == lp.onScreen) {
9191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return;
9201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
922b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        lp.onScreen = slideOffset;
9231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        dispatchOnDrawerSlide(drawerView, slideOffset);
9241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
9251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    float getDrawerViewOffset(View drawerView) {
927b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        return ((LayoutParams) drawerView.getLayoutParams()).onScreen;
9281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
9291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
930f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette    /**
931f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     * @return the absolute gravity of the child drawerView, resolved according
932f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     *         to the current layout direction
933f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     */
934f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette    int getDrawerViewAbsoluteGravity(View drawerView) {
9351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int gravity = ((LayoutParams) drawerView.getLayoutParams()).gravity;
936f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        return GravityCompat.getAbsoluteGravity(gravity, ViewCompat.getLayoutDirection(this));
9371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
9381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
939f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette    boolean checkDrawerViewAbsoluteGravity(View drawerView, int checkFor) {
940f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final int absGravity = getDrawerViewAbsoluteGravity(drawerView);
941f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        return (absGravity & checkFor) == checkFor;
9421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
9431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9440492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    View findOpenDrawer() {
9450492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        final int childCount = getChildCount();
9460492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        for (int i = 0; i < childCount; i++) {
9470492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            final View child = getChildAt(i);
94867cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov            final LayoutParams childLp = (LayoutParams) child.getLayoutParams();
94967cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov            if ((childLp.openState & LayoutParams.FLAG_IS_OPENED) == 1) {
9500492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                return child;
9510492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            }
9520492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        }
9530492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        return null;
9540492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
9550492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
9561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void moveDrawerToOffset(View drawerView, float slideOffset) {
9571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final float oldOffset = getDrawerViewOffset(drawerView);
9581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int width = drawerView.getWidth();
9591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int oldPos = (int) (width * oldOffset);
9601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int newPos = (int) (width * slideOffset);
9611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int dx = newPos - oldPos;
9621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
963f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        drawerView.offsetLeftAndRight(
964f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                checkDrawerViewAbsoluteGravity(drawerView, Gravity.LEFT) ? dx : -dx);
9651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        setDrawerViewOffset(drawerView, slideOffset);
9661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
9671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
968f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette    /**
969f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     * @param gravity the gravity of the child to return. If specified as a
970f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     *            relative value, it will be resolved according to the current
971f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     *            layout direction.
972f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     * @return the drawer with the specified gravity
973f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette     */
9741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    View findDrawerWithGravity(int gravity) {
975f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final int absHorizGravity = GravityCompat.getAbsoluteGravity(
976f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                gravity, ViewCompat.getLayoutDirection(this)) & Gravity.HORIZONTAL_GRAVITY_MASK;
9771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
9781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
9791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
980f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            final int childAbsGravity = getDrawerViewAbsoluteGravity(child);
981f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if ((childAbsGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == absHorizGravity) {
9821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                return child;
9831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
9841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return null;
9861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
9871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
9891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Simple gravity to string - only supports LEFT and RIGHT for debugging output.
9901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
9911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param gravity Absolute gravity value
9921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @return LEFT or RIGHT as appropriate, or a hex string
9931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
994a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    static String gravityToString(@EdgeGravity int gravity) {
9951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if ((gravity & Gravity.LEFT) == Gravity.LEFT) {
9961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return "LEFT";
9971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) {
9991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return "RIGHT";
10001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
10011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return Integer.toHexString(gravity);
10021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
10031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
100557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected void onDetachedFromWindow() {
100657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        super.onDetachedFromWindow();
100757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        mFirstLayout = true;
100857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
100957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
101057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
101157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected void onAttachedToWindow() {
101257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        super.onAttachedToWindow();
101357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        mFirstLayout = true;
101457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
101557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
101657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
10171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
1018c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
1019c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
1020c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
1021c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
10221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) {
1024c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell            if (isInEditMode()) {
1025c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                // Don't crash the layout editor. Consume all of the space if specified
1026c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                // or pick a magic number from thin air otherwise.
1027c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                // TODO Better communication with tools of this bogus state.
1028c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                // It will crash on a real device.
1029c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                if (widthMode == MeasureSpec.AT_MOST) {
1030c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                    widthMode = MeasureSpec.EXACTLY;
1031c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                } else if (widthMode == MeasureSpec.UNSPECIFIED) {
1032c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                    widthMode = MeasureSpec.EXACTLY;
1033c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                    widthSize = 300;
1034c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                }
1035c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                if (heightMode == MeasureSpec.AT_MOST) {
1036c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                    heightMode = MeasureSpec.EXACTLY;
10374d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                } else if (heightMode == MeasureSpec.UNSPECIFIED) {
1038c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                    heightMode = MeasureSpec.EXACTLY;
1039c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                    heightSize = 300;
1040c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                }
1041c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell            } else {
1042c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                throw new IllegalArgumentException(
1043c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell                        "DrawerLayout must be measured with MeasureSpec.EXACTLY.");
1044c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell            }
10451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
10461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        setMeasuredDimension(widthSize, heightSize);
10481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1049f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        final boolean applyInsets = mLastInsets != null && ViewCompat.getFitsSystemWindows(this);
1050f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        final int layoutDirection = ViewCompat.getLayoutDirection(this);
1051f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
1052e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov        // Only one drawer is permitted along each vertical edge (left / right). These two booleans
1053e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov        // are tracking the presence of the edge drawers.
1054e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov        boolean hasDrawerOnLeftEdge = false;
1055e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov        boolean hasDrawerOnRightEdge = false;
10561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
10571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
10581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
10591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (child.getVisibility() == GONE) {
10611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                continue;
10621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
10631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
106400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
106500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
1066f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            if (applyInsets) {
1067f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell                final int cgrav = GravityCompat.getAbsoluteGravity(lp.gravity, layoutDirection);
1068f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell                if (ViewCompat.getFitsSystemWindows(child)) {
1069f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell                    IMPL.dispatchChildInsets(child, mLastInsets, cgrav);
1070f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell                } else {
1071f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell                    IMPL.applyMarginInsets(lp, mLastInsets, cgrav);
1072f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell                }
1073f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            }
1074f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
10751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (isContentView(child)) {
10761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                // Content views get measured at exactly the layout's size.
107700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int contentWidthSpec = MeasureSpec.makeMeasureSpec(
107800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        widthSize - lp.leftMargin - lp.rightMargin, MeasureSpec.EXACTLY);
107900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int contentHeightSpec = MeasureSpec.makeMeasureSpec(
108000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        heightSize - lp.topMargin - lp.bottomMargin, MeasureSpec.EXACTLY);
108100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                child.measure(contentWidthSpec, contentHeightSpec);
10821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else if (isDrawerView(child)) {
1083621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                if (SET_DRAWER_SHADOW_FROM_ELEVATION) {
1084621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                    if (ViewCompat.getElevation(child) != mDrawerElevation) {
1085621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                        ViewCompat.setElevation(child, mDrawerElevation);
1086621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                    }
1087621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                }
1088e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov                final @EdgeGravity int childGravity =
1089f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                        getDrawerViewAbsoluteGravity(child) & Gravity.HORIZONTAL_GRAVITY_MASK;
1090e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov                // Note that the isDrawerView check guarantees that childGravity here is either
1091e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov                // LEFT or RIGHT
1092e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov                boolean isLeftEdgeDrawer = (childGravity == Gravity.LEFT);
10934d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                if ((isLeftEdgeDrawer && hasDrawerOnLeftEdge)
10944d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                        || (!isLeftEdgeDrawer && hasDrawerOnRightEdge)) {
10954d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                    throw new IllegalStateException("Child drawer has absolute gravity "
10964d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                            + gravityToString(childGravity) + " but this " + TAG + " already has a "
10974d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                            + "drawer view along that edge");
10981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
1099e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov                if (isLeftEdgeDrawer) {
1100e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov                    hasDrawerOnLeftEdge = true;
1101e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov                } else {
1102e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov                    hasDrawerOnRightEdge = true;
1103e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov                }
110400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int drawerWidthSpec = getChildMeasureSpec(widthMeasureSpec,
110500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        mMinDrawerMargin + lp.leftMargin + lp.rightMargin,
110600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.width);
110700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int drawerHeightSpec = getChildMeasureSpec(heightMeasureSpec,
110800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.topMargin + lp.bottomMargin,
110900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.height);
111000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                child.measure(drawerWidthSpec, drawerHeightSpec);
11111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
11124d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                throw new IllegalStateException("Child " + child + " at index " + i
11134d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                        + " does not have a valid layout_gravity - must be Gravity.LEFT, "
11144d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                        + "Gravity.RIGHT or Gravity.NO_GRAVITY");
11151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
11161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
11171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
11181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1119621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    private void resolveShadowDrawables() {
1120621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        if (SET_DRAWER_SHADOW_FROM_ELEVATION) {
1121621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            return;
1122621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        }
1123621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        mShadowLeftResolved = resolveLeftShadow();
1124621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        mShadowRightResolved = resolveRightShadow();
1125621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    }
1126621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu
1127621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    private Drawable resolveLeftShadow() {
1128621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        int layoutDirection = ViewCompat.getLayoutDirection(this);
1129621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        // Prefer shadows defined with start/end gravity over left and right.
1130621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_LTR) {
1131621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            if (mShadowStart != null) {
1132621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                // Correct drawable layout direction, if needed.
1133621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                mirror(mShadowStart, layoutDirection);
1134621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                return mShadowStart;
1135621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            }
1136621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        } else {
1137621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            if (mShadowEnd != null) {
1138621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                // Correct drawable layout direction, if needed.
1139621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                mirror(mShadowEnd, layoutDirection);
1140621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                return mShadowEnd;
1141621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            }
1142621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        }
1143621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        return mShadowLeft;
1144621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    }
1145621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu
1146621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    private Drawable resolveRightShadow() {
1147621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        int layoutDirection = ViewCompat.getLayoutDirection(this);
1148621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_LTR) {
1149621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            if (mShadowEnd != null) {
1150621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                // Correct drawable layout direction, if needed.
1151621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                mirror(mShadowEnd, layoutDirection);
1152621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                return mShadowEnd;
1153621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            }
1154621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        } else {
1155621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            if (mShadowStart != null) {
1156621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                // Correct drawable layout direction, if needed.
1157621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                mirror(mShadowStart, layoutDirection);
1158621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                return mShadowStart;
1159621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            }
1160621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        }
1161621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        return mShadowRight;
1162621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    }
1163621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu
1164621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    /**
1165621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * Change the layout direction of the given drawable.
1166621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * Return true if auto-mirror is supported and drawable's layout direction can be changed.
1167621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     * Otherwise, return false.
1168621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu     */
1169621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    private boolean mirror(Drawable drawable, int layoutDirection) {
1170621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        if (drawable == null || !DrawableCompat.isAutoMirrored(drawable)) {
1171621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            return false;
1172621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        }
1173621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu
1174621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        DrawableCompat.setLayoutDirection(drawable, layoutDirection);
1175621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        return true;
1176621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    }
1177621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu
11781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
11791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected void onLayout(boolean changed, int l, int t, int r, int b) {
1180b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        mInLayout = true;
1181c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell        final int width = r - l;
11821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
11831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
11841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
11851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
11861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (child.getVisibility() == GONE) {
11871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                continue;
11881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
11891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
119000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
119100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
11921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (isContentView(child)) {
119300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                child.layout(lp.leftMargin, lp.topMargin,
119400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.leftMargin + child.getMeasuredWidth(),
119500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        lp.topMargin + child.getMeasuredHeight());
11961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else { // Drawer, if it wasn't onMeasure would have thrown an exception.
11971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int childWidth = child.getMeasuredWidth();
119800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int childHeight = child.getMeasuredHeight();
11991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                int childLeft;
12001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1201c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                final float newOffset;
1202f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                if (checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) {
1203b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    childLeft = -childWidth + (int) (childWidth * lp.onScreen);
1204c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                    newOffset = (float) (childWidth + childLeft) / childWidth;
12051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                } else { // Right; onMeasure checked for us.
1206c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                    childLeft = width - (int) (childWidth * lp.onScreen);
1207c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                    newOffset = (float) (width - childLeft) / childWidth;
12081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
12091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1210c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                final boolean changeOffset = newOffset != lp.onScreen;
1211c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell
121200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK;
121300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
121400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                switch (vgrav) {
121500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    default:
121600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    case Gravity.TOP: {
12179b2fb1efe771e9927724b33242cbc3bc62b5b315Adam Powell                        child.layout(childLeft, lp.topMargin, childLeft + childWidth,
12189b2fb1efe771e9927724b33242cbc3bc62b5b315Adam Powell                                lp.topMargin + childHeight);
121900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        break;
122000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    }
122100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
122200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    case Gravity.BOTTOM: {
122300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        final int height = b - t;
122400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        child.layout(childLeft,
122500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                                height - lp.bottomMargin - child.getMeasuredHeight(),
122600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                                childLeft + childWidth,
122700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                                height - lp.bottomMargin);
122800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        break;
122900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    }
123000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
123100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    case Gravity.CENTER_VERTICAL: {
123200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        final int height = b - t;
123300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        int childTop = (height - childHeight) / 2;
123400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
123500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        // Offset for margins. If things don't fit right because of
123600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        // bad measurement before, oh well.
123700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        if (childTop < lp.topMargin) {
123800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                            childTop = lp.topMargin;
123900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        } else if (childTop + childHeight > height - lp.bottomMargin) {
124000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                            childTop = height - lp.bottomMargin - childHeight;
124100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        }
124200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        child.layout(childLeft, childTop, childLeft + childWidth,
124300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                                childTop + childHeight);
124400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                        break;
124500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                    }
124600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                }
1247b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
1248c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                if (changeOffset) {
1249c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                    setDrawerViewOffset(child, newOffset);
1250c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                }
1251c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell
1252c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                final int newVisibility = lp.onScreen > 0 ? VISIBLE : INVISIBLE;
1253c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                if (child.getVisibility() != newVisibility) {
1254c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell                    child.setVisibility(newVisibility);
1255b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                }
12561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
12571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
1258b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        mInLayout = false;
125957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        mFirstLayout = false;
1260b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
1261b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
1262b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    @Override
1263b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public void requestLayout() {
1264b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (!mInLayout) {
1265b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            super.requestLayout();
1266b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
12671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
12681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
12701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void computeScroll() {
12711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
12721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        float scrimOpacity = 0;
12731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
1274b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final float onscreen = ((LayoutParams) getChildAt(i).getLayoutParams()).onScreen;
12751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            scrimOpacity = Math.max(scrimOpacity, onscreen);
12761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
12771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mScrimOpacity = scrimOpacity;
12781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
12791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        // "|" used on purpose; both need to run.
12801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (mLeftDragger.continueSettling(true) | mRightDragger.continueSettling(true)) {
12811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            ViewCompat.postInvalidateOnAnimation(this);
12821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
12831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
12841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1285b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    private static boolean hasOpaqueBackground(View v) {
1286b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        final Drawable bg = v.getBackground();
1287b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (bg != null) {
1288b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            return bg.getOpacity() == PixelFormat.OPAQUE;
1289b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
1290b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        return false;
1291b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
1292b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
1293f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    /**
1294f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * Set a drawable to draw in the insets area for the status bar.
1295f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * Note that this will only be activated if this DrawerLayout fitsSystemWindows.
1296f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     *
1297f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * @param bg Background drawable to draw behind the status bar
1298f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     */
1299f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    public void setStatusBarBackground(Drawable bg) {
1300f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        mStatusBarBackground = bg;
1301cbfb6c6ffc411f1f9d302570341993bd9929ee1aScott Kennedy        invalidate();
1302f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    }
1303f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
1304f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    /**
1305753354ca64f8528ddc3b76d0ce69635de743e506Scott Kennedy     * Gets the drawable used to draw in the insets area for the status bar.
1306753354ca64f8528ddc3b76d0ce69635de743e506Scott Kennedy     *
1307753354ca64f8528ddc3b76d0ce69635de743e506Scott Kennedy     * @return The status bar background drawable, or null if none set
1308753354ca64f8528ddc3b76d0ce69635de743e506Scott Kennedy     */
1309753354ca64f8528ddc3b76d0ce69635de743e506Scott Kennedy    public Drawable getStatusBarBackgroundDrawable() {
1310753354ca64f8528ddc3b76d0ce69635de743e506Scott Kennedy        return mStatusBarBackground;
1311753354ca64f8528ddc3b76d0ce69635de743e506Scott Kennedy    }
1312753354ca64f8528ddc3b76d0ce69635de743e506Scott Kennedy
1313753354ca64f8528ddc3b76d0ce69635de743e506Scott Kennedy    /**
1314f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * Set a drawable to draw in the insets area for the status bar.
1315f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * Note that this will only be activated if this DrawerLayout fitsSystemWindows.
1316f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     *
1317f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * @param resId Resource id of a background drawable to draw behind the status bar
1318f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     */
1319f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    public void setStatusBarBackground(int resId) {
1320f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        mStatusBarBackground = resId != 0 ? ContextCompat.getDrawable(getContext(), resId) : null;
1321cbfb6c6ffc411f1f9d302570341993bd9929ee1aScott Kennedy        invalidate();
1322f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    }
1323f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
1324f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    /**
1325f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * Set a drawable to draw in the insets area for the status bar.
1326f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * Note that this will only be activated if this DrawerLayout fitsSystemWindows.
1327f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     *
1328f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     * @param color Color to use as a background drawable to draw behind the status bar
1329f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     *              in 0xAARRGGBB format.
1330f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell     */
133170acb0c19be3831a2080e4f902324de16bfbf62eTor Norbye    public void setStatusBarBackgroundColor(@ColorInt int color) {
1332f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        mStatusBarBackground = new ColorDrawable(color);
1333cbfb6c6ffc411f1f9d302570341993bd9929ee1aScott Kennedy        invalidate();
1334f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    }
1335f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
1336621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    public void onRtlPropertiesChanged(int layoutDirection) {
1337621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        resolveShadowDrawables();
1338621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu    }
1339621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu
1340f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    @Override
1341f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    public void onDraw(Canvas c) {
1342f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        super.onDraw(c);
1343f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        if (mDrawStatusBarBackground && mStatusBarBackground != null) {
1344f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            final int inset = IMPL.getTopInset(mLastInsets);
1345f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            if (inset > 0) {
1346f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell                mStatusBarBackground.setBounds(0, 0, getWidth(), inset);
1347f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell                mStatusBarBackground.draw(c);
1348f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell            }
1349f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell        }
1350f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell    }
1351f9c35128decbd812ff2497852ccacbd1ffbbd811Adam Powell
13521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
13531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
135400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        final int height = getHeight();
1355b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        final boolean drawingContent = isContentView(child);
1356b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        int clipLeft = 0, clipRight = getWidth();
1357b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
13581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int restoreCount = canvas.save();
1359b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (drawingContent) {
1360b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int childCount = getChildCount();
1361b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            for (int i = 0; i < childCount; i++) {
1362b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                final View v = getChildAt(i);
13634d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                if (v == child || v.getVisibility() != VISIBLE
13644d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                        || !hasOpaqueBackground(v) || !isDrawerView(v)
13654d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                        || v.getHeight() < height) {
1366b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    continue;
1367b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                }
1368b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
1369f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                if (checkDrawerViewAbsoluteGravity(v, Gravity.LEFT)) {
1370b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    final int vright = v.getRight();
1371b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    if (vright > clipLeft) clipLeft = vright;
1372b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                } else {
1373b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    final int vleft = v.getLeft();
1374b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    if (vleft < clipRight) clipRight = vleft;
1375b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                }
1376b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            }
1377b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            canvas.clipRect(clipLeft, 0, clipRight, getHeight());
1378b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
13791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final boolean result = super.drawChild(canvas, child, drawingTime);
13801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        canvas.restoreToCount(restoreCount);
1381b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
1382b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (mScrimOpacity > 0 && drawingContent) {
13831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int baseAlpha = (mScrimColor & 0xff000000) >>> 24;
13841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int imag = (int) (baseAlpha * mScrimOpacity);
13851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int color = imag << 24 | (mScrimColor & 0xffffff);
13861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mScrimPaint.setColor(color);
13871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1388b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            canvas.drawRect(clipLeft, 0, clipRight, getHeight(), mScrimPaint);
1389621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        } else if (mShadowLeftResolved != null
1390621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                &&  checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) {
1391621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            final int shadowWidth = mShadowLeftResolved.getIntrinsicWidth();
1392b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int childRight = child.getRight();
1393ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            final int drawerPeekDistance = mLeftDragger.getEdgeSize();
1394b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final float alpha =
1395ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                    Math.max(0, Math.min((float) childRight / drawerPeekDistance, 1.f));
1396621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            mShadowLeftResolved.setBounds(childRight, child.getTop(),
1397b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    childRight + shadowWidth, child.getBottom());
1398621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            mShadowLeftResolved.setAlpha((int) (0xff * alpha));
1399621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            mShadowLeftResolved.draw(canvas);
1400621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu        } else if (mShadowRightResolved != null
1401621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu                &&  checkDrawerViewAbsoluteGravity(child, Gravity.RIGHT)) {
1402621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            final int shadowWidth = mShadowRightResolved.getIntrinsicWidth();
1403b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int childLeft = child.getLeft();
1404b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int showing = getWidth() - childLeft;
1405ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            final int drawerPeekDistance = mRightDragger.getEdgeSize();
1406b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final float alpha =
1407ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                    Math.max(0, Math.min((float) showing / drawerPeekDistance, 1.f));
1408621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            mShadowRightResolved.setBounds(childLeft - shadowWidth, child.getTop(),
1409b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    childLeft, child.getBottom());
1410621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            mShadowRightResolved.setAlpha((int) (0xff * alpha));
1411621e41e02c0664afd4e358dfe166d6fb71e471c9Doris Liu            mShadowRightResolved.draw(canvas);
14121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
14131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return result;
14141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
14151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    boolean isContentView(View child) {
14171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return ((LayoutParams) child.getLayoutParams()).gravity == Gravity.NO_GRAVITY;
14181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
14191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    boolean isDrawerView(View child) {
14211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int gravity = ((LayoutParams) child.getLayoutParams()).gravity;
14221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int absGravity = GravityCompat.getAbsoluteGravity(gravity,
14231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                ViewCompat.getLayoutDirection(child));
14240fcbafc72ac95c44e2ff99a4e1b31475e4276052Kirill Grouchnikov        if ((absGravity & Gravity.LEFT) != 0) {
1425e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov            // This child is a left-edge drawer
1426e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov            return true;
1427e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov        }
14280fcbafc72ac95c44e2ff99a4e1b31475e4276052Kirill Grouchnikov        if ((absGravity & Gravity.RIGHT) != 0) {
1429e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov            // This child is a right-edge drawer
1430e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov            return true;
1431e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov        }
1432e6e27ab94303516b1e196568cee520832c38710cKirill Grouchnikov        return false;
14331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
14341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
14361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public boolean onInterceptTouchEvent(MotionEvent ev) {
14371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int action = MotionEventCompat.getActionMasked(ev);
14381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        // "|" used deliberately here; both methods should be invoked.
14404d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas        final boolean interceptForDrag = mLeftDragger.shouldInterceptTouchEvent(ev)
14414d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                | mRightDragger.shouldInterceptTouchEvent(ev);
14421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean interceptForTap = false;
14441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        switch (action) {
14461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_DOWN: {
14471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float x = ev.getX();
14481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float y = ev.getY();
14491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionX = x;
14501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionY = y;
14512bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                if (mScrimOpacity > 0) {
14522bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                    final View child = mLeftDragger.findTopChildUnder((int) x, (int) y);
14532bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                    if (child != null && isContentView(child)) {
14542bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                        interceptForTap = true;
14552bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                    }
14561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
14571732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
1458cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                mChildrenCanceledTouch = false;
14591732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                break;
14601732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            }
14611732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
14621732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            case MotionEvent.ACTION_MOVE: {
14631732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                // If we cross the touch slop, don't perform the delayed peek for an edge touch.
14641732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                if (mLeftDragger.checkTouchSlop(ViewDragHelper.DIRECTION_ALL)) {
14651732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                    mLeftCallback.removeCallbacks();
14661732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                    mRightCallback.removeCallbacks();
14671732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                }
14681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
14691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
14701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_CANCEL:
14721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_UP: {
14731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawers(true);
14741732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
1475cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                mChildrenCanceledTouch = false;
14761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
14771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
14781732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
1479cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell        return interceptForDrag || interceptForTap || hasPeekingDrawer() || mChildrenCanceledTouch;
14801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
14811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
14831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public boolean onTouchEvent(MotionEvent ev) {
14841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mLeftDragger.processTouchEvent(ev);
14851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mRightDragger.processTouchEvent(ev);
14861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int action = ev.getAction();
14881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean wantTouchEvents = true;
14891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
14901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        switch (action & MotionEventCompat.ACTION_MASK) {
14911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_DOWN: {
14921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float x = ev.getX();
14931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float y = ev.getY();
14941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionX = x;
14951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionY = y;
14961732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
1497cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                mChildrenCanceledTouch = false;
14981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
14991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
15001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
15011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_UP: {
15021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float x = ev.getX();
15031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float y = ev.getY();
15041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                boolean peekingOnly = true;
15058bc268e9c40e4ae375a0d65dc1293dccc541186fAdam Powell                final View touchedView = mLeftDragger.findTopChildUnder((int) x, (int) y);
15068bc268e9c40e4ae375a0d65dc1293dccc541186fAdam Powell                if (touchedView != null && isContentView(touchedView)) {
15071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    final float dx = x - mInitialMotionX;
15081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    final float dy = y - mInitialMotionY;
15091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    final int slop = mLeftDragger.getTouchSlop();
15101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    if (dx * dx + dy * dy < slop * slop) {
15110492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                        // Taps close a dimmed open drawer but only if it isn't locked open.
15120492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                        final View openDrawer = findOpenDrawer();
15130492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                        if (openDrawer != null) {
15140492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                            peekingOnly = getDrawerLockMode(openDrawer) == LOCK_MODE_LOCKED_OPEN;
15150492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                        }
15161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    }
15171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
15181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawers(peekingOnly);
15191732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
15201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
15211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
15221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
15231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_CANCEL: {
15241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawers(true);
15251732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                mDisallowInterceptRequested = false;
1526cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                mChildrenCanceledTouch = false;
15271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
15281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
15291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
15301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
15311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return wantTouchEvents;
15321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
15331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
153415375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
1535ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
15364d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas        if (CHILDREN_DISALLOW_INTERCEPT
15374d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                || (!mLeftDragger.isEdgeTouched(ViewDragHelper.EDGE_LEFT)
15384d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                        && !mRightDragger.isEdgeTouched(ViewDragHelper.EDGE_RIGHT))) {
15391732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            // If we have an edge touch we want to skip this and track it for later instead.
15401732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            super.requestDisallowInterceptTouchEvent(disallowIntercept);
15411732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        }
15421732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mDisallowInterceptRequested = disallowIntercept;
1543ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        if (disallowIntercept) {
1544ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            closeDrawers(true);
1545ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        }
1546ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    }
1547ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell
15481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
15491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Close all currently open drawer views by animating them out of view.
15501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
15511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void closeDrawers() {
15521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        closeDrawers(false);
15531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
15541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
15551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void closeDrawers(boolean peekingOnly) {
15561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean needsInvalidate = false;
15571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
15581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
15591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
15601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
15611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
15621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (!isDrawerView(child) || (peekingOnly && !lp.isPeeking)) {
15631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                continue;
15641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
15651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
15661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childWidth = child.getWidth();
15671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1568f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if (checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) {
15691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                needsInvalidate |= mLeftDragger.smoothSlideViewTo(child,
15701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        -childWidth, child.getTop());
15711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
15721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                needsInvalidate |= mRightDragger.smoothSlideViewTo(child,
15731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        getWidth(), child.getTop());
15741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
15751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
15761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            lp.isPeeking = false;
15771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
15781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
15791732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mLeftCallback.removeCallbacks();
15801732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        mRightCallback.removeCallbacks();
15811732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
15821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (needsInvalidate) {
15831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            invalidate();
15841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
15851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
15861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
15871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
15881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Open the specified drawer view by animating it into view.
15891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
15901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param drawerView Drawer view to open
15911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
15921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void openDrawer(View drawerView) {
1593ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas        openDrawer(drawerView, true);
1594ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas    }
1595ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas
1596ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas    /**
1597ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     * Open the specified drawer view.
1598ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     *
1599ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     * @param drawerView Drawer view to open
1600ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     * @param animate Whether opening of the drawer should be animated.
1601ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     */
1602ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas    public void openDrawer(View drawerView, boolean animate) {
16031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (!isDrawerView(drawerView)) {
16041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            throw new IllegalArgumentException("View " + drawerView + " is not a sliding drawer");
16051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
16061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
160767cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov        final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
160857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        if (mFirstLayout) {
160957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            lp.onScreen = 1.f;
161067cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov            lp.openState = LayoutParams.FLAG_IS_OPENED;
161149733ad715bcf68cc178f53e17a79380d332e5ccAlan Viverette
16122bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            updateChildrenImportantForAccessibility(drawerView, true);
1613ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas        } else if (animate) {
161467cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov            lp.openState |= LayoutParams.FLAG_IS_OPENING;
161567cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov
1616f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if (checkDrawerViewAbsoluteGravity(drawerView, Gravity.LEFT)) {
161757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mLeftDragger.smoothSlideViewTo(drawerView, 0, drawerView.getTop());
161857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            } else {
161957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mRightDragger.smoothSlideViewTo(drawerView, getWidth() - drawerView.getWidth(),
162057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                        drawerView.getTop());
162157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
1622ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas        } else {
1623ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas            moveDrawerToOffset(drawerView, 1.f);
1624ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas            updateDrawerState(lp.gravity, STATE_IDLE, drawerView);
1625ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas            drawerView.setVisibility(VISIBLE);
16261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
16271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        invalidate();
16281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
16291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
16311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Open the specified drawer by animating it out of view.
16321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
16331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param gravity Gravity.LEFT to move the left drawer or Gravity.RIGHT for the right.
16341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *                GravityCompat.START or GravityCompat.END may also be used.
16351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
1636a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public void openDrawer(@EdgeGravity int gravity) {
1637ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas        openDrawer(gravity, true);
1638ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas    }
1639ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas
1640ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas    /**
1641ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     * Open the specified drawer.
1642ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     *
1643ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     * @param gravity Gravity.LEFT to move the left drawer or Gravity.RIGHT for the right.
1644ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     *                GravityCompat.START or GravityCompat.END may also be used.
1645ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     * @param animate Whether opening of the drawer should be animated.
1646ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     */
1647ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas    public void openDrawer(@EdgeGravity int gravity, boolean animate) {
1648f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final View drawerView = findDrawerWithGravity(gravity);
16491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (drawerView == null) {
16504d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas            throw new IllegalArgumentException("No drawer view found with gravity "
16514d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                    + gravityToString(gravity));
16521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
1653ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas        openDrawer(drawerView, animate);
16541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
16551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
16571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Close the specified drawer view by animating it into view.
16581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
16591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param drawerView Drawer view to close
16601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
16611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void closeDrawer(View drawerView) {
1662ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas        closeDrawer(drawerView, true);
1663ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas    }
1664ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas
1665ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas    /**
1666ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     * Close the specified drawer view.
1667ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     *
1668ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     * @param drawerView Drawer view to close
1669ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     * @param animate Whether closing of the drawer should be animated.
1670ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     */
1671ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas    public void closeDrawer(View drawerView, boolean animate) {
16721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (!isDrawerView(drawerView)) {
16731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            throw new IllegalArgumentException("View " + drawerView + " is not a sliding drawer");
16741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
16751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
167667cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov        final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
167757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        if (mFirstLayout) {
167857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            lp.onScreen = 0.f;
167967cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov            lp.openState = 0;
1680ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas        } else if (animate) {
168167cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov            lp.openState |= LayoutParams.FLAG_IS_CLOSING;
168267cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov
1683f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if (checkDrawerViewAbsoluteGravity(drawerView, Gravity.LEFT)) {
168457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mLeftDragger.smoothSlideViewTo(drawerView, -drawerView.getWidth(),
168557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                        drawerView.getTop());
168657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            } else {
168757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mRightDragger.smoothSlideViewTo(drawerView, getWidth(), drawerView.getTop());
168857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
1689ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas        } else {
1690ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas            moveDrawerToOffset(drawerView, 0.f);
1691ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas            updateDrawerState(lp.gravity, STATE_IDLE, drawerView);
1692ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas            drawerView.setVisibility(INVISIBLE);
16931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
16941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        invalidate();
16951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
16961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
16971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
16981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Close the specified drawer by animating it out of view.
16991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
17001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param gravity Gravity.LEFT to move the left drawer or Gravity.RIGHT for the right.
17011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *                GravityCompat.START or GravityCompat.END may also be used.
17021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
1703a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public void closeDrawer(@EdgeGravity int gravity) {
1704ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas        closeDrawer(gravity, true);
1705ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas    }
1706ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas
1707ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas    /**
1708ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     * Close the specified drawer.
1709ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     *
1710ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     * @param gravity Gravity.LEFT to move the left drawer or Gravity.RIGHT for the right.
1711ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     *                GravityCompat.START or GravityCompat.END may also be used.
1712ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     * @param animate Whether closing of the drawer should be animated.
1713ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas     */
1714ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas    public void closeDrawer(@EdgeGravity int gravity, boolean animate) {
1715f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        final View drawerView = findDrawerWithGravity(gravity);
17161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (drawerView == null) {
17174d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas            throw new IllegalArgumentException("No drawer view found with gravity "
17184d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                    + gravityToString(gravity));
17191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
1720ee4afb511cf51d082e3226f442799a59725bdac2Aurimas Liutikas        closeDrawer(drawerView, animate);
17211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
17221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1723b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
1724b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Check if the given drawer view is currently in an open state.
1725b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * To be considered "open" the drawer must have settled into its fully
1726b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * visible state. To check for partial visibility use
1727b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * {@link #isDrawerVisible(android.view.View)}.
1728b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
1729b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param drawer Drawer view to check
1730b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @return true if the given drawer view is in an open state
1731b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @see #isDrawerVisible(android.view.View)
1732b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
1733b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public boolean isDrawerOpen(View drawer) {
1734b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (!isDrawerView(drawer)) {
1735b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            throw new IllegalArgumentException("View " + drawer + " is not a drawer");
1736b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
173767cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov        LayoutParams drawerLp = (LayoutParams) drawer.getLayoutParams();
173867cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov        return (drawerLp.openState & LayoutParams.FLAG_IS_OPENED) == 1;
1739b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
1740b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
1741b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
174279f95ce3e660d267831067e514ff455156c4381fAdam Powell     * Check if the given drawer view is currently in an open state.
174379f95ce3e660d267831067e514ff455156c4381fAdam Powell     * To be considered "open" the drawer must have settled into its fully
174479f95ce3e660d267831067e514ff455156c4381fAdam Powell     * visible state. If there is no drawer with the given gravity this method
174579f95ce3e660d267831067e514ff455156c4381fAdam Powell     * will return false.
174679f95ce3e660d267831067e514ff455156c4381fAdam Powell     *
174779f95ce3e660d267831067e514ff455156c4381fAdam Powell     * @param drawerGravity Gravity of the drawer to check
174879f95ce3e660d267831067e514ff455156c4381fAdam Powell     * @return true if the given drawer view is in an open state
174979f95ce3e660d267831067e514ff455156c4381fAdam Powell     */
1750a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public boolean isDrawerOpen(@EdgeGravity int drawerGravity) {
175179f95ce3e660d267831067e514ff455156c4381fAdam Powell        final View drawerView = findDrawerWithGravity(drawerGravity);
175279f95ce3e660d267831067e514ff455156c4381fAdam Powell        if (drawerView != null) {
175379f95ce3e660d267831067e514ff455156c4381fAdam Powell            return isDrawerOpen(drawerView);
175479f95ce3e660d267831067e514ff455156c4381fAdam Powell        }
175579f95ce3e660d267831067e514ff455156c4381fAdam Powell        return false;
175679f95ce3e660d267831067e514ff455156c4381fAdam Powell    }
175779f95ce3e660d267831067e514ff455156c4381fAdam Powell
175879f95ce3e660d267831067e514ff455156c4381fAdam Powell    /**
1759b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Check if a given drawer view is currently visible on-screen. The drawer
1760b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * may be only peeking onto the screen, fully extended, or anywhere inbetween.
1761b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
1762b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param drawer Drawer view to check
1763b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @return true if the given drawer is visible on-screen
1764b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @see #isDrawerOpen(android.view.View)
1765b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
1766b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public boolean isDrawerVisible(View drawer) {
1767b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (!isDrawerView(drawer)) {
1768b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            throw new IllegalArgumentException("View " + drawer + " is not a drawer");
1769b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
1770b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        return ((LayoutParams) drawer.getLayoutParams()).onScreen > 0;
1771b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
1772b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
177379f95ce3e660d267831067e514ff455156c4381fAdam Powell    /**
177479f95ce3e660d267831067e514ff455156c4381fAdam Powell     * Check if a given drawer view is currently visible on-screen. The drawer
1775a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye     * may be only peeking onto the screen, fully extended, or anywhere in between.
177679f95ce3e660d267831067e514ff455156c4381fAdam Powell     * If there is no drawer with the given gravity this method will return false.
177779f95ce3e660d267831067e514ff455156c4381fAdam Powell     *
177879f95ce3e660d267831067e514ff455156c4381fAdam Powell     * @param drawerGravity Gravity of the drawer to check
177979f95ce3e660d267831067e514ff455156c4381fAdam Powell     * @return true if the given drawer is visible on-screen
178079f95ce3e660d267831067e514ff455156c4381fAdam Powell     */
1781a3ff3273e976adf19770651dcf473fa67b38eb22Tor Norbye    public boolean isDrawerVisible(@EdgeGravity int drawerGravity) {
178279f95ce3e660d267831067e514ff455156c4381fAdam Powell        final View drawerView = findDrawerWithGravity(drawerGravity);
178379f95ce3e660d267831067e514ff455156c4381fAdam Powell        if (drawerView != null) {
178479f95ce3e660d267831067e514ff455156c4381fAdam Powell            return isDrawerVisible(drawerView);
178579f95ce3e660d267831067e514ff455156c4381fAdam Powell        }
178679f95ce3e660d267831067e514ff455156c4381fAdam Powell        return false;
178779f95ce3e660d267831067e514ff455156c4381fAdam Powell    }
178879f95ce3e660d267831067e514ff455156c4381fAdam Powell
1789ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    private boolean hasPeekingDrawer() {
1790ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        final int childCount = getChildCount();
1791ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        for (int i = 0; i < childCount; i++) {
1792ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            final LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams();
1793ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            if (lp.isPeeking) {
1794ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                return true;
1795ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            }
1796ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        }
1797ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        return false;
1798ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell    }
1799ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell
18001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
18011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
1802e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikas        return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
18031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
18041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
18051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
18061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
18071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return p instanceof LayoutParams
18081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                ? new LayoutParams((LayoutParams) p)
180900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                : p instanceof ViewGroup.MarginLayoutParams
181000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell                ? new LayoutParams((MarginLayoutParams) p)
18111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                : new LayoutParams(p);
18121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
18131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
18141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
18151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
18161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return p instanceof LayoutParams && super.checkLayoutParams(p);
18171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
18181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
18191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
18201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
18211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return new LayoutParams(getContext(), attrs);
18221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
18231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1824fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai    @Override
1825fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
1826fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai        if (getDescendantFocusability() == FOCUS_BLOCK_DESCENDANTS) {
1827fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai            return;
1828fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai        }
1829fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai
1830fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai        // Only the views in the open drawers are focusables. Add normal child views when
1831fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai        // no drawers are opened.
1832fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai        final int childCount = getChildCount();
1833fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai        boolean isDrawerOpen = false;
1834fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai        for (int i = 0; i < childCount; i++) {
1835fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai            final View child = getChildAt(i);
1836fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai            if (isDrawerView(child)) {
1837fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai                if (isDrawerOpen(child)) {
1838fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai                    isDrawerOpen = true;
1839fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai                    child.addFocusables(views, direction, focusableMode);
1840fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai                }
1841fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai            } else {
1842fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai                mNonDrawerViews.add(child);
1843fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai            }
1844fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai        }
1845fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai
1846fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai        if (!isDrawerOpen) {
1847fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai            final int nonDrawerViewsCount = mNonDrawerViews.size();
1848fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai            for (int i = 0; i < nonDrawerViewsCount; ++i) {
1849fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai                final View child = mNonDrawerViews.get(i);
1850fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai                if (child.getVisibility() == View.VISIBLE) {
1851fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai                    child.addFocusables(views, direction, focusableMode);
1852fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai                }
1853fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai            }
1854fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai        }
1855fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai
1856fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai        mNonDrawerViews.clear();
1857fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai    }
1858fedd8cbd0fd3f6a62dabffa3970db2d3373d8db8Jun Mukai
1859791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    private boolean hasVisibleDrawer() {
18600492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        return findVisibleDrawer() != null;
18610492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell    }
18620492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell
1863540222c3675801eaa141ace1c164c4d3499b4721Aurimas Liutikas    View findVisibleDrawer() {
1864791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        final int childCount = getChildCount();
1865791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        for (int i = 0; i < childCount; i++) {
1866791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            final View child = getChildAt(i);
1867791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            if (isDrawerView(child) && isDrawerVisible(child)) {
18680492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                return child;
1869791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            }
1870791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        }
18710492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        return null;
1872791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    }
1873791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
1874cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell    void cancelChildViewTouch() {
1875cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell        // Cancel child touches
1876cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell        if (!mChildrenCanceledTouch) {
1877cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            final long now = SystemClock.uptimeMillis();
1878cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            final MotionEvent cancelEvent = MotionEvent.obtain(now, now,
1879cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                    MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
1880cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            final int childCount = getChildCount();
1881cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            for (int i = 0; i < childCount; i++) {
1882cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                getChildAt(i).dispatchTouchEvent(cancelEvent);
1883cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            }
1884cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            cancelEvent.recycle();
1885cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell            mChildrenCanceledTouch = true;
1886cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell        }
1887cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell    }
1888cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell
1889791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    @Override
1890791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    public boolean onKeyDown(int keyCode, KeyEvent event) {
1891791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        if (keyCode == KeyEvent.KEYCODE_BACK && hasVisibleDrawer()) {
18921b3e9466b4c4d72f28bb4448672ef8bab19b6f3eKirill Grouchnikov            event.startTracking();
1893791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            return true;
1894791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        }
1895791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        return super.onKeyDown(keyCode, event);
1896791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    }
1897791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
1898791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    @Override
1899791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    public boolean onKeyUp(int keyCode, KeyEvent event) {
19000492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell        if (keyCode == KeyEvent.KEYCODE_BACK) {
19010492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            final View visibleDrawer = findVisibleDrawer();
19020492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            if (visibleDrawer != null && getDrawerLockMode(visibleDrawer) == LOCK_MODE_UNLOCKED) {
19030492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell                closeDrawers();
19040492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            }
19050492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            return visibleDrawer != null;
1906791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        }
1907791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        return super.onKeyUp(keyCode, event);
1908791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    }
1909791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
191057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
191157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected void onRestoreInstanceState(Parcelable state) {
1912bb58a82daf11bf3c056d1cd5887aa26435d37b69Aurimas Liutikas        if (!(state instanceof SavedState)) {
1913bb58a82daf11bf3c056d1cd5887aa26435d37b69Aurimas Liutikas            super.onRestoreInstanceState(state);
1914bb58a82daf11bf3c056d1cd5887aa26435d37b69Aurimas Liutikas            return;
1915bb58a82daf11bf3c056d1cd5887aa26435d37b69Aurimas Liutikas        }
1916bb58a82daf11bf3c056d1cd5887aa26435d37b69Aurimas Liutikas
191757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        final SavedState ss = (SavedState) state;
191857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        super.onRestoreInstanceState(ss.getSuperState());
191957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
192057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        if (ss.openDrawerGravity != Gravity.NO_GRAVITY) {
192157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            final View toOpen = findDrawerWithGravity(ss.openDrawerGravity);
192257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            if (toOpen != null) {
192357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                openDrawer(toOpen);
192457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
192557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
19268e01d24e718d603974182cd48f648369c07edec1Adam Powell
1927b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov        if (ss.lockModeLeft != LOCK_MODE_UNDEFINED) {
1928b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            setDrawerLockMode(ss.lockModeLeft, Gravity.LEFT);
1929b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov        }
1930b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov        if (ss.lockModeRight != LOCK_MODE_UNDEFINED) {
1931b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            setDrawerLockMode(ss.lockModeRight, Gravity.RIGHT);
1932b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov        }
1933b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov        if (ss.lockModeStart != LOCK_MODE_UNDEFINED) {
1934b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            setDrawerLockMode(ss.lockModeStart, GravityCompat.START);
1935b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov        }
1936b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov        if (ss.lockModeEnd != LOCK_MODE_UNDEFINED) {
1937b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            setDrawerLockMode(ss.lockModeEnd, GravityCompat.END);
1938b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov        }
193957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
194057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
194157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
194257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected Parcelable onSaveInstanceState() {
194357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        final Parcelable superState = super.onSaveInstanceState();
194457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        final SavedState ss = new SavedState(superState);
194557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
194667cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov        final int childCount = getChildCount();
194767cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov        for (int i = 0; i < childCount; i++) {
194867cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov            final View child = getChildAt(i);
194967cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov            LayoutParams lp = (LayoutParams) child.getLayoutParams();
195067cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov            // Is the current child fully opened (that is, not closing)?
195167cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov            boolean isOpenedAndNotClosing = (lp.openState == LayoutParams.FLAG_IS_OPENED);
195267cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov            // Is the current child opening?
195367cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov            boolean isClosedAndOpening = (lp.openState == LayoutParams.FLAG_IS_OPENING);
195467cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov            if (isOpenedAndNotClosing || isClosedAndOpening) {
195567cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov                // If one of the conditions above holds, save the child's gravity
195667cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov                // so that we open that child during state restore.
195767cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov                ss.openDrawerGravity = lp.gravity;
195867cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov                break;
195967cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov            }
196057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
196157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
19628e01d24e718d603974182cd48f648369c07edec1Adam Powell        ss.lockModeLeft = mLockModeLeft;
19638e01d24e718d603974182cd48f648369c07edec1Adam Powell        ss.lockModeRight = mLockModeRight;
1964b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov        ss.lockModeStart = mLockModeStart;
1965b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov        ss.lockModeEnd = mLockModeEnd;
19668e01d24e718d603974182cd48f648369c07edec1Adam Powell
196757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        return ss;
196857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
196957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
197012ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    @Override
197112ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    public void addView(View child, int index, ViewGroup.LayoutParams params) {
19722bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        super.addView(child, index, params);
19732bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette
19742bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        final View openDrawer = findOpenDrawer();
19752bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        if (openDrawer != null || isDrawerView(child)) {
19762bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            // A drawer is already open or the new view is a drawer, so the
19772bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            // new view should start out hidden.
197812ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            ViewCompat.setImportantForAccessibility(child,
197912ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                    ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
19802bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        } else {
19812bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            // Otherwise this is a content view and no drawer is open, so the
19822bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            // new view should start out visible.
198312ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            ViewCompat.setImportantForAccessibility(child,
198412ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                    ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
198512ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        }
19862bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette
19872bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        // We only need a delegate here if the framework doesn't understand
19882bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        // NO_HIDE_DESCENDANTS importance.
19892bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        if (!CAN_HIDE_DESCENDANTS) {
19902bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            ViewCompat.setAccessibilityDelegate(child, mChildAccessibilityDelegate);
19912bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        }
199212ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    }
199312ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
1994540222c3675801eaa141ace1c164c4d3499b4721Aurimas Liutikas    static boolean includeChildForAccessibility(View child) {
199512ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        // If the child is not important for accessibility we make
199612ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        // sure this hides the entire subtree rooted at it as the
199712ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        // IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDATS is not
199812ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        // supported on older platforms but we want to hide the entire
199912ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        // content and not opened drawers if a drawer is opened.
200012ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        return ViewCompat.getImportantForAccessibility(child)
200112ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                != ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
200212ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                    && ViewCompat.getImportantForAccessibility(child)
200312ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                != ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO;
200412ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    }
200512ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
200657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    /**
200757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell     * State persisted across instances
200857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell     */
200905f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banes    protected static class SavedState extends AbsSavedState {
201057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        int openDrawerGravity = Gravity.NO_GRAVITY;
2011b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov        @LockMode int lockModeLeft;
2012b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov        @LockMode int lockModeRight;
2013b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov        @LockMode int lockModeStart;
2014b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov        @LockMode int lockModeEnd;
201557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
201605f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banes        public SavedState(Parcel in, ClassLoader loader) {
201705f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banes            super(in, loader);
201857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            openDrawerGravity = in.readInt();
2019b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            lockModeLeft = in.readInt();
2020b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            lockModeRight = in.readInt();
2021b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            lockModeStart = in.readInt();
2022b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            lockModeEnd = in.readInt();
202357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
202457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
202557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        public SavedState(Parcelable superState) {
202657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            super(superState);
202757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
202857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
202957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        @Override
203057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        public void writeToParcel(Parcel dest, int flags) {
203157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            super.writeToParcel(dest, flags);
203257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            dest.writeInt(openDrawerGravity);
2033b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            dest.writeInt(lockModeLeft);
2034b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            dest.writeInt(lockModeRight);
2035b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            dest.writeInt(lockModeStart);
2036b518b3afec21cb8e843f00971bf6c176fe34c371Kirill Grouchnikov            dest.writeInt(lockModeEnd);
203757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
203857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
203905f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banes        public static final Creator<SavedState> CREATOR = ParcelableCompat.newCreator(
204005f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banes                new ParcelableCompatCreatorCallbacks<SavedState>() {
204105f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banes                    @Override
204205f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banes                    public SavedState createFromParcel(Parcel in, ClassLoader loader) {
204305f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banes                        return new SavedState(in, loader);
204405f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banes                    }
204557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
204605f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banes                    @Override
204705f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banes                    public SavedState[] newArray(int size) {
204805f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banes                        return new SavedState[size];
204905f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banes                    }
205005f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banes                });
205157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
205257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
20531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private class ViewDragCallback extends ViewDragHelper.Callback {
2054f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette        private final int mAbsGravity;
20551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        private ViewDragHelper mDragger;
20561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
20571732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        private final Runnable mPeekRunnable = new Runnable() {
20581732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            @Override public void run() {
20591732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell                peekDrawer();
20601732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            }
20611732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        };
20621732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
20634d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas        ViewDragCallback(int gravity) {
2064f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            mAbsGravity = gravity;
20651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
20661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
20671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void setDragger(ViewDragHelper dragger) {
20681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mDragger = dragger;
20691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
20701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
20711732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        public void removeCallbacks() {
20721732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            DrawerLayout.this.removeCallbacks(mPeekRunnable);
20731732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        }
20741732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
20751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
20761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public boolean tryCaptureView(View child, int pointerId) {
20771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // Only capture views where the gravity matches what we're looking for.
20781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // This lets us use two ViewDragHelpers, one for each side drawer.
2079f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            return isDrawerView(child) && checkDrawerViewAbsoluteGravity(child, mAbsGravity)
2080f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                    && getDrawerLockMode(child) == LOCK_MODE_UNLOCKED;
20811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
20821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
20831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
20841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewDragStateChanged(int state) {
2085f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            updateDrawerState(mAbsGravity, state, mDragger.getCapturedView());
20861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
20871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
20881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
20891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
20901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            float offset;
20911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childWidth = changedView.getWidth();
20921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
20931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // This reverses the positioning shown in onLayout.
2094f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if (checkDrawerViewAbsoluteGravity(changedView, Gravity.LEFT)) {
20951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                offset = (float) (childWidth + left) / childWidth;
20961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
20971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int width = getWidth();
20981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                offset = (float) (width - left) / childWidth;
20991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
21001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            setDrawerViewOffset(changedView, offset);
2101b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            changedView.setVisibility(offset == 0 ? INVISIBLE : VISIBLE);
21021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            invalidate();
21031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
21041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
21051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
21061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewCaptured(View capturedChild, int activePointerId) {
21071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final LayoutParams lp = (LayoutParams) capturedChild.getLayoutParams();
21081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            lp.isPeeking = false;
21091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
21101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            closeOtherDrawer();
21111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
21121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
21131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        private void closeOtherDrawer() {
2114f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            final int otherGrav = mAbsGravity == Gravity.LEFT ? Gravity.RIGHT : Gravity.LEFT;
21151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View toClose = findDrawerWithGravity(otherGrav);
21161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (toClose != null) {
21171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawer(toClose);
21181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
21191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
21201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
21211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
21221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewReleased(View releasedChild, float xvel, float yvel) {
21231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // Offset is how open the drawer is, therefore left/right values
21241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // are reversed from one another.
21251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final float offset = getDrawerViewOffset(releasedChild);
21261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childWidth = releasedChild.getWidth();
21271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
21281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            int left;
2129f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if (checkDrawerViewAbsoluteGravity(releasedChild, Gravity.LEFT)) {
21301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                left = xvel > 0 || xvel == 0 && offset > 0.5f ? 0 : -childWidth;
21311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
21321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int width = getWidth();
21337d690eb050d901c7a7b4ebc3896471124ef98f7cAdam Powell                left = xvel < 0 || xvel == 0 && offset > 0.5f ? width - childWidth : width;
21341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
21351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
21361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mDragger.settleCapturedViewAt(left, releasedChild.getTop());
21371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            invalidate();
21381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
21391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
21401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
21411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onEdgeTouched(int edgeFlags, int pointerId) {
21421732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell            postDelayed(mPeekRunnable, PEEK_DELAY);
21431732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell        }
21441732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell
2145540222c3675801eaa141ace1c164c4d3499b4721Aurimas Liutikas        void peekDrawer() {
21461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View toCapture;
21471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childLeft;
2148ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            final int peekDistance = mDragger.getEdgeSize();
2149f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            final boolean leftEdge = mAbsGravity == Gravity.LEFT;
2150b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            if (leftEdge) {
21511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.LEFT);
2152ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                childLeft = (toCapture != null ? -toCapture.getWidth() : 0) + peekDistance;
21531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
21541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.RIGHT);
2155ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                childLeft = getWidth() - peekDistance;
21561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
21570492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            // Only peek if it would mean making the drawer more visible and the drawer isn't locked
21584d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas            if (toCapture != null && ((leftEdge && toCapture.getLeft() < childLeft)
21594d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                    || (!leftEdge && toCapture.getLeft() > childLeft))
21604d2c7b7c4f194034c5f17c4bee7320d808aabe4cAurimas Liutikas                    && getDrawerLockMode(toCapture) == LOCK_MODE_UNLOCKED) {
2161b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                final LayoutParams lp = (LayoutParams) toCapture.getLayoutParams();
21621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mDragger.smoothSlideViewTo(toCapture, childLeft, toCapture.getTop());
2163b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                lp.isPeeking = true;
21641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                invalidate();
21651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
21661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeOtherDrawer();
2167cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell
2168cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell                cancelChildViewTouch();
21691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
21701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
21711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
21721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
2173ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell        public boolean onEdgeLock(int edgeFlags) {
2174ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            if (ALLOW_EDGE_LOCK) {
2175f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette                final View drawer = findDrawerWithGravity(mAbsGravity);
2176ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                if (drawer != null && !isDrawerOpen(drawer)) {
2177ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                    closeDrawer(drawer);
2178ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                }
2179ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell                return true;
2180acc82321ad119706485db342eaa12b225fa9b667Adam Powell            }
2181ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell            return false;
2182acc82321ad119706485db342eaa12b225fa9b667Adam Powell        }
2183acc82321ad119706485db342eaa12b225fa9b667Adam Powell
2184acc82321ad119706485db342eaa12b225fa9b667Adam Powell        @Override
21851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onEdgeDragStarted(int edgeFlags, int pointerId) {
21861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View toCapture;
21871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if ((edgeFlags & ViewDragHelper.EDGE_LEFT) == ViewDragHelper.EDGE_LEFT) {
21881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.LEFT);
21891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
21901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.RIGHT);
21911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
21921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
21930492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell            if (toCapture != null && getDrawerLockMode(toCapture) == LOCK_MODE_UNLOCKED) {
21941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mDragger.captureChildView(toCapture, pointerId);
21951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
21961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
21971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
21981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
21991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public int getViewHorizontalDragRange(View child) {
22008a28dd16be442db2ee6275baf72079777627f37eChet Haase            return isDrawerView(child) ? child.getWidth() : 0;
22011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
22021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
22031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
22041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public int clampViewPositionHorizontal(View child, int left, int dx) {
2205f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette            if (checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) {
22061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                return Math.max(-child.getWidth(), Math.min(left, 0));
22071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
22081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int width = getWidth();
22091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                return Math.max(width - child.getWidth(), Math.min(left, width));
22101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
22111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
221200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
221300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        @Override
221400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        public int clampViewPositionVertical(View child, int top, int dy) {
221500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell            return child.getTop();
221600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        }
22171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
22181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
221900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell    public static class LayoutParams extends ViewGroup.MarginLayoutParams {
222067cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov        private static final int FLAG_IS_OPENED = 0x1;
222167cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov        private static final int FLAG_IS_OPENING = 0x2;
222267cf3e301575e3d67e3b4c3d06f4624438590dd3Kirill Grouchnikov        private static final int FLAG_IS_CLOSING = 0x4;
22231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
22241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public int gravity = Gravity.NO_GRAVITY;
2225540222c3675801eaa141ace1c164c4d3499b4721Aurimas Liutikas        float onScreen;
2226540222c3675801eaa141ace1c164c4d3499b4721Aurimas Liutikas        boolean isPeeking;
2227540222c3675801eaa141ace1c164c4d3499b4721Aurimas Liutikas        int openState;
22281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
22291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(Context c, AttributeSet attrs) {
22301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(c, attrs);
22311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
22321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final TypedArray a = c.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
22331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this.gravity = a.getInt(0, Gravity.NO_GRAVITY);
22341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            a.recycle();
22351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
22361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
22371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(int width, int height) {
22381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(width, height);
22391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
22401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
22411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(int width, int height, int gravity) {
22421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this(width, height);
22431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this.gravity = gravity;
22441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
22451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
22461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(LayoutParams source) {
22471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(source);
22481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this.gravity = source.gravity;
22491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
22501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
22511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(ViewGroup.LayoutParams source) {
22521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(source);
22531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
225400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell
225500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        public LayoutParams(ViewGroup.MarginLayoutParams source) {
225600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell            super(source);
225700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell        }
22581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
22597d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell
22607d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell    class AccessibilityDelegate extends AccessibilityDelegateCompat {
22613cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell        private final Rect mTmpRect = new Rect();
22623cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
22637d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell        @Override
22647d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
22652bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            if (CAN_HIDE_DESCENDANTS) {
22662bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                super.onInitializeAccessibilityNodeInfo(host, info);
22672bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            } else {
22682bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                // Obtain a node for the host, then manually generate the list
22692bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                // of children to only include non-obscured views.
22702bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                final AccessibilityNodeInfoCompat superNode =
22712bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                        AccessibilityNodeInfoCompat.obtain(info);
22722bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                super.onInitializeAccessibilityNodeInfo(host, superNode);
22732bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette
22742bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                info.setSource(host);
22752bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                final ViewParent parent = ViewCompat.getParentForAccessibility(host);
22762bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                if (parent instanceof View) {
22772bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                    info.setParent((View) parent);
22782bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                }
22792bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                copyNodeInfoNoChildren(info, superNode);
22802bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                superNode.recycle();
22813cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
22822bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                addChildrenForAccessibility(info, (ViewGroup) host);
22833cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            }
22843cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
22852bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            info.setClassName(DrawerLayout.class.getName());
22864b1190de13d6408e24cbda5f77e6148f54206fd0Alan Viverette
22874b1190de13d6408e24cbda5f77e6148f54206fd0Alan Viverette            // This view reports itself as focusable so that it can intercept
22884b1190de13d6408e24cbda5f77e6148f54206fd0Alan Viverette            // the back button, but we should prevent this view from reporting
22894b1190de13d6408e24cbda5f77e6148f54206fd0Alan Viverette            // itself as focusable to accessibility services.
22904b1190de13d6408e24cbda5f77e6148f54206fd0Alan Viverette            info.setFocusable(false);
22914b1190de13d6408e24cbda5f77e6148f54206fd0Alan Viverette            info.setFocused(false);
22920a13063f56de4a369ee20e62494dcdda9e37f966Alan Viverette            info.removeAction(AccessibilityActionCompat.ACTION_FOCUS);
22930a13063f56de4a369ee20e62494dcdda9e37f966Alan Viverette            info.removeAction(AccessibilityActionCompat.ACTION_CLEAR_FOCUS);
2294d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette        }
2295d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette
2296526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        @Override
2297526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
2298526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            super.onInitializeAccessibilityEvent(host, event);
2299526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
2300526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            event.setClassName(DrawerLayout.class.getName());
2301aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette        }
2302526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
2303aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette        @Override
2304aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
2305526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            // Special case to handle window state change events. As far as
2306aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // accessibility services are concerned, state changes from
2307aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // DrawerLayout invalidate the entire contents of the screen (like
2308aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // an Activity or Dialog) and they should announce the title of the
2309aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            // new content.
2310526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
2311526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                final List<CharSequence> eventText = event.getText();
2312526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                final View visibleDrawer = findVisibleDrawer();
2313526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                if (visibleDrawer != null) {
2314526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                    final int edgeGravity = getDrawerViewAbsoluteGravity(visibleDrawer);
2315526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                    final CharSequence title = getDrawerTitle(edgeGravity);
2316526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                    if (title != null) {
2317526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                        eventText.add(title);
2318526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                    }
2319526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette                }
2320aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette
2321aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette                return true;
2322526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette            }
2323aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette
2324aeaa8ef97eb729fbee17e984d60e9ab27795f5d0Alan Viverette            return super.dispatchPopulateAccessibilityEvent(host, event);
2325526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette        }
2326526ba1382e61845ef23bf27d300883dea0966af5Alan Viverette
23272bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        @Override
23282bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
23292bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                AccessibilityEvent event) {
23302bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            if (CAN_HIDE_DESCENDANTS || includeChildForAccessibility(child)) {
23312bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette                return super.onRequestSendAccessibilityEvent(host, child, event);
23322bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            }
23332bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette            return false;
23342bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette        }
23352bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette
2336d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette        private void addChildrenForAccessibility(AccessibilityNodeInfoCompat info, ViewGroup v) {
2337d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette            final int childCount = v.getChildCount();
23387d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell            for (int i = 0; i < childCount; i++) {
2339d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette                final View child = v.getChildAt(i);
234049733ad715bcf68cc178f53e17a79380d332e5ccAlan Viverette                if (includeChildForAccessibility(child)) {
234112ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                    info.addChild(child);
23427d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell                }
23437d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell            }
23447d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell        }
23457d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell
23463cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell        /**
23473cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell         * This should really be in AccessibilityNodeInfoCompat, but there unfortunately
23483cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell         * seem to be a few elements that are not easily cloneable using the underlying API.
23493cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell         * Leave it private here as it's not general-purpose useful.
23503cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell         */
23513cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell        private void copyNodeInfoNoChildren(AccessibilityNodeInfoCompat dest,
23523cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell                AccessibilityNodeInfoCompat src) {
23533cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            final Rect rect = mTmpRect;
23543cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
23553cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            src.getBoundsInParent(rect);
23563cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setBoundsInParent(rect);
23573cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
23583cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            src.getBoundsInScreen(rect);
23593cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setBoundsInScreen(rect);
23603cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
23613cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setVisibleToUser(src.isVisibleToUser());
23623cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setPackageName(src.getPackageName());
23633cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setClassName(src.getClassName());
23643cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setContentDescription(src.getContentDescription());
23653cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
23663cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setEnabled(src.isEnabled());
23673cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setClickable(src.isClickable());
23683cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setFocusable(src.isFocusable());
23693cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setFocused(src.isFocused());
23703cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setAccessibilityFocused(src.isAccessibilityFocused());
23713cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setSelected(src.isSelected());
23723cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.setLongClickable(src.isLongClickable());
23733cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell
23743cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell            dest.addAction(src.getActions());
23753cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell        }
23767d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell    }
237712ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette
237812ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    final class ChildAccessibilityDelegate extends AccessibilityDelegateCompat {
237912ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        @Override
238012ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        public void onInitializeAccessibilityNodeInfo(View child,
238112ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                AccessibilityNodeInfoCompat info) {
238212ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            super.onInitializeAccessibilityNodeInfo(child, info);
23832bb8d4e8831b2d0f1de7f15493bb79f48c91db2aAlan Viverette
238449733ad715bcf68cc178f53e17a79380d332e5ccAlan Viverette            if (!includeChildForAccessibility(child)) {
238512ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                // If we are ignoring the sub-tree rooted at the child,
238612ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                // break the connection to the rest of the node tree.
238749733ad715bcf68cc178f53e17a79380d332e5ccAlan Viverette                // For details refer to includeChildForAccessibility.
238812ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette                info.setParent(null);
238912ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette            }
239012ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette        }
239112ba769d9e9b121829c69daf0f6350e808028a6aAlan Viverette    }
23921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell}
2393