11d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell/* 21d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Copyright (C) 2013 The Android Open Source Project 31d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * 41d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Licensed under the Apache License, Version 2.0 (the "License"); 51d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * you may not use this file except in compliance with the License. 61d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * You may obtain a copy of the License at 71d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * 81d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * http://www.apache.org/licenses/LICENSE-2.0 91d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * 101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Unless required by applicable law or agreed to in writing, software 111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * distributed under the License is distributed on an "AS IS" BASIS, 121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * See the License for the specific language governing permissions and 141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * limitations under the License. 151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */ 161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellpackage android.support.v4.widget; 191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.content.Context; 211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.content.res.TypedArray; 221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.graphics.Canvas; 231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.graphics.Paint; 24b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powellimport android.graphics.PixelFormat; 253cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powellimport android.graphics.Rect; 26b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powellimport android.graphics.drawable.Drawable; 2757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powellimport android.os.Parcel; 2857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powellimport android.os.Parcelable; 29cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powellimport android.os.SystemClock; 307d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powellimport android.support.v4.view.AccessibilityDelegateCompat; 311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.support.v4.view.GravityCompat; 32791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powellimport android.support.v4.view.KeyEventCompat; 331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.support.v4.view.MotionEventCompat; 341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.support.v4.view.ViewCompat; 351b8262b87426b2f766b40d6ab4eaeac296d5c2feAdam Powellimport android.support.v4.view.ViewGroupCompat; 367d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powellimport android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; 371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.util.AttributeSet; 381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.Gravity; 39791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powellimport android.view.KeyEvent; 401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.MotionEvent; 411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.View; 421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.ViewGroup; 433cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powellimport android.view.ViewParent; 447d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powellimport android.view.accessibility.AccessibilityEvent; 451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell/** 471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * DrawerLayout acts as a top-level container for window content that allows for 481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * interactive "drawer" views to be pulled out from the edge of the window. 491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * 501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * <p>Drawer positioning and layout is controlled using the <code>android:layout_gravity</code> 5109c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * attribute on child views corresponding to which side of the view you want the drawer 5209c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * to emerge from: left or right. (Or start/end on platform versions that support layout direction.) 5309c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * </p> 5409c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * 5509c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * <p>To use a DrawerLayout, position your primary content view as the first child with 5609c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * a width and height of <code>match_parent</code>. Add drawers as child views after the main 5709c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * content view and set the <code>layout_gravity</code> appropriately. Drawers commonly use 5809c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * <code>match_parent</code> for height with a fixed width.</p> 5909c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * 6009c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * <p>{@link DrawerListener} can be used to monitor the state and motion of drawer views. 6109c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * Avoid performing expensive operations such as layout during animation as it can cause 6209c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * stuttering; try to perform expensive operations during the {@link #STATE_IDLE} state. 6309c38625b5400dcda3d872dbe865c867cc02e5ebAdam Powell * {@link SimpleDrawerListener} offers default/no-op implementations of each callback method.</p> 641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * 651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * <p>As per the Android Design guide, any drawers positioned to the left/start should 661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * always contain content for navigating around the application, whereas any drawers 671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * positioned to the right/end should always contain actions to take on the current content. 681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * This preserves the same navigation left, actions right structure present in the Action Bar 691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * and elsewhere.</p> 701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */ 711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellpublic class DrawerLayout extends ViewGroup { 721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell private static final String TAG = "DrawerLayout"; 731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell /** 751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Indicates that any drawers are in an idle, settled state. No animation is in progress. 761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */ 771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public static final int STATE_IDLE = ViewDragHelper.STATE_IDLE; 781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell /** 801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Indicates that a drawer is currently being dragged by the user. 811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */ 821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public static final int STATE_DRAGGING = ViewDragHelper.STATE_DRAGGING; 831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell /** 851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Indicates that a drawer is in the process of settling to a final position. 861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */ 871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public static final int STATE_SETTLING = ViewDragHelper.STATE_SETTLING; 881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 890492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell /** 900492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * The drawer is unlocked. 910492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell */ 920492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell public static final int LOCK_MODE_UNLOCKED = 0; 930492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell 940492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell /** 950492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * The drawer is locked closed. The user may not open it, though 960492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * the app may open it programmatically. 970492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell */ 980492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell public static final int LOCK_MODE_LOCKED_CLOSED = 1; 990492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell 1000492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell /** 1010492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * The drawer is locked open. The user may not close it, though the app 1020492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * may close it programmatically. 1030492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell */ 1040492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell public static final int LOCK_MODE_LOCKED_OPEN = 2; 1050492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell 1061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell private static final int MIN_DRAWER_MARGIN = 64; // dp 1071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 1081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell private static final int DEFAULT_SCRIM_COLOR = 0x99000000; 1091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 110ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell /** 1111732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell * Length of time to delay before peeking the drawer. 1121732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell */ 1131732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell private static final int PEEK_DELAY = 160; // ms 1141732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell 1151732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell /** 11679f95ce3e660d267831067e514ff455156c4381fAdam Powell * Minimum velocity that will be detected as a fling 11779f95ce3e660d267831067e514ff455156c4381fAdam Powell */ 11879f95ce3e660d267831067e514ff455156c4381fAdam Powell private static final int MIN_FLING_VELOCITY = 400; // dips per second 11979f95ce3e660d267831067e514ff455156c4381fAdam Powell 12079f95ce3e660d267831067e514ff455156c4381fAdam Powell /** 121ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell * Experimental feature. 122ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell */ 123ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell private static final boolean ALLOW_EDGE_LOCK = false; 124ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell 12586559d86173efb890a8edf48d935cfebfaccf049Adam Powell private static final boolean CHILDREN_DISALLOW_INTERCEPT = true; 12686559d86173efb890a8edf48d935cfebfaccf049Adam Powell 12786559d86173efb890a8edf48d935cfebfaccf049Adam Powell private static final float TOUCH_SLOP_SENSITIVITY = 1.f; 12886559d86173efb890a8edf48d935cfebfaccf049Adam Powell 1291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell private static final int[] LAYOUT_ATTRS = new int[] { 1301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell android.R.attr.layout_gravity 1311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell }; 1321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 1331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell private int mMinDrawerMargin; 1341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 1351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell private int mScrimColor = DEFAULT_SCRIM_COLOR; 1361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell private float mScrimOpacity; 1371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell private Paint mScrimPaint = new Paint(); 1381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 1391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell private final ViewDragHelper mLeftDragger; 1401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell private final ViewDragHelper mRightDragger; 1411732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell private final ViewDragCallback mLeftCallback; 1421732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell private final ViewDragCallback mRightCallback; 1431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell private int mDrawerState; 144b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell private boolean mInLayout; 14557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell private boolean mFirstLayout = true; 1460492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell private int mLockModeLeft; 1470492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell private int mLockModeRight; 1481732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell private boolean mDisallowInterceptRequested; 149cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell private boolean mChildrenCanceledTouch; 1501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 1511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell private DrawerListener mListener; 1521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 1531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell private float mInitialMotionX; 1541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell private float mInitialMotionY; 1551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 156b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell private Drawable mShadowLeft; 157b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell private Drawable mShadowRight; 158b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell 1591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell /** 1601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Listener for monitoring events about drawers. 1611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */ 1621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public interface DrawerListener { 1631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell /** 1641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Called when a drawer's position changes. 1651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * @param drawerView The child view that was moved 1661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * @param slideOffset The new offset of this drawer within its range, from 0-1 1671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */ 1681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public void onDrawerSlide(View drawerView, float slideOffset); 1691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 1701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell /** 1711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Called when a drawer has settled in a completely open state. 1721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * The drawer is interactive at this point. 1731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * 1741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * @param drawerView Drawer view that is now open 1751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */ 1761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public void onDrawerOpened(View drawerView); 1771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 1781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell /** 1791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Called when a drawer has settled in a completely closed state. 1801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * 1811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * @param drawerView Drawer view that is now closed 1821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */ 1831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public void onDrawerClosed(View drawerView); 1841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 1851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell /** 1861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Called when the drawer motion state changes. The new state will 1871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * be one of {@link #STATE_IDLE}, {@link #STATE_DRAGGING} or {@link #STATE_SETTLING}. 1881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * 1891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * @param newState The new drawer motion state 1901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */ 1911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public void onDrawerStateChanged(int newState); 1921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 1931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 194b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell /** 195b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * Stub/no-op implementations of all methods of {@link DrawerListener}. 196b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * Override this if you only care about a few of the available callback methods. 197b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell */ 198b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell public static abstract class SimpleDrawerListener implements DrawerListener { 199b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell @Override 200b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell public void onDrawerSlide(View drawerView, float slideOffset) { 201b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 202b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell 203b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell @Override 204b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell public void onDrawerOpened(View drawerView) { 205b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 206b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell 207b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell @Override 208b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell public void onDrawerClosed(View drawerView) { 209b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 210b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell 211b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell @Override 212b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell public void onDrawerStateChanged(int newState) { 213b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 214b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 215b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell 2161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public DrawerLayout(Context context) { 2171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell this(context, null); 2181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 2191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 2201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public DrawerLayout(Context context, AttributeSet attrs) { 2211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell this(context, attrs, 0); 2221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 2231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 2241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public DrawerLayout(Context context, AttributeSet attrs, int defStyle) { 2251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell super(context, attrs, defStyle); 2261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 2271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final float density = getResources().getDisplayMetrics().density; 2281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mMinDrawerMargin = (int) (MIN_DRAWER_MARGIN * density + 0.5f); 22979f95ce3e660d267831067e514ff455156c4381fAdam Powell final float minVel = MIN_FLING_VELOCITY * density; 2301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 2311732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell mLeftCallback = new ViewDragCallback(Gravity.LEFT); 2321732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell mRightCallback = new ViewDragCallback(Gravity.RIGHT); 2331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 23486559d86173efb890a8edf48d935cfebfaccf049Adam Powell mLeftDragger = ViewDragHelper.create(this, TOUCH_SLOP_SENSITIVITY, mLeftCallback); 2351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mLeftDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT); 23679f95ce3e660d267831067e514ff455156c4381fAdam Powell mLeftDragger.setMinVelocity(minVel); 2371732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell mLeftCallback.setDragger(mLeftDragger); 2381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 23986559d86173efb890a8edf48d935cfebfaccf049Adam Powell mRightDragger = ViewDragHelper.create(this, TOUCH_SLOP_SENSITIVITY, mRightCallback); 2401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mRightDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_RIGHT); 24179f95ce3e660d267831067e514ff455156c4381fAdam Powell mRightDragger.setMinVelocity(minVel); 2421732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell mRightCallback.setDragger(mRightDragger); 243791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell 244791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell // So that we can catch the back button 245791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell setFocusableInTouchMode(true); 2467d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell 2477d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell ViewCompat.setAccessibilityDelegate(this, new AccessibilityDelegate()); 2481b8262b87426b2f766b40d6ab4eaeac296d5c2feAdam Powell ViewGroupCompat.setMotionEventSplittingEnabled(this, false); 2491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 2501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 2511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell /** 252b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * Set a simple drawable used for the left or right shadow. 253b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * The drawable provided must have a nonzero intrinsic width. 254b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * 255b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * @param shadowDrawable Shadow drawable to use at the edge of a drawer 256b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * @param gravity Which drawer the shadow should apply to 257b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell */ 258b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell public void setDrawerShadow(Drawable shadowDrawable, int gravity) { 259b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell /* 260b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * TODO Someone someday might want to set more complex drawables here. 261b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * They're probably nuts, but we might want to consider registering callbacks, 262b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * setting states, etc. properly. 263b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell */ 264b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell 265b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell final int absGravity = GravityCompat.getAbsoluteGravity(gravity, 266b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell ViewCompat.getLayoutDirection(this)); 267b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell if ((absGravity & Gravity.LEFT) == Gravity.LEFT) { 268b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell mShadowLeft = shadowDrawable; 269b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell invalidate(); 270b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 271b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell if ((absGravity & Gravity.RIGHT) == Gravity.RIGHT) { 272b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell mShadowRight = shadowDrawable; 273b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell invalidate(); 274b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 275b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 276b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell 277b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell /** 278b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * Set a simple drawable used for the left or right shadow. 279b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * The drawable provided must have a nonzero intrinsic width. 280b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * 281b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * @param resId Resource id of a shadow drawable to use at the edge of a drawer 282b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * @param gravity Which drawer the shadow should apply to 283b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell */ 284b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell public void setDrawerShadow(int resId, int gravity) { 285b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell setDrawerShadow(getResources().getDrawable(resId), gravity); 286b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 287b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell 288b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell /** 289fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell * Set a color to use for the scrim that obscures primary content while a drawer is open. 290fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell * 291fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell * @param color Color to use in 0xAARRGGBB format. 292fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell */ 293fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell public void setScrimColor(int color) { 294fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell mScrimColor = color; 295fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell invalidate(); 296fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell } 297fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell 298fe130779be95af79e875bdbeac7182a424b8b9a6Adam Powell /** 2991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Set a listener to be notified of drawer events. 3001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * 3011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * @param listener Listener to notify when drawer events occur 3021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * @see DrawerListener 3031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */ 3041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public void setDrawerListener(DrawerListener listener) { 3051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mListener = listener; 3061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 3071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 3081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell /** 3090492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * Enable or disable interaction with all drawers. 3100492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * 3110492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * <p>This allows the application to restrict the user's ability to open or close 3120492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * any drawer within this layout. DrawerLayout will still respond to calls to 3130492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * {@link #openDrawer(int)}, {@link #closeDrawer(int)} and friends if a drawer is locked.</p> 3140492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * 3150492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * <p>Locking drawers open or closed will implicitly open or close 3160492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * any drawers as appropriate.</p> 3170492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * 3180492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * @param lockMode The new lock mode for the given drawer. One of {@link #LOCK_MODE_UNLOCKED}, 3190492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * {@link #LOCK_MODE_LOCKED_CLOSED} or {@link #LOCK_MODE_LOCKED_OPEN}. 3200492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell */ 3210492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell public void setDrawerLockMode(int lockMode) { 3220492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell setDrawerLockMode(lockMode, Gravity.LEFT); 3230492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell setDrawerLockMode(lockMode, Gravity.RIGHT); 3240492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell } 3250492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell 3260492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell /** 3270492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * Enable or disable interaction with the given drawer. 3280492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * 3290492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * <p>This allows the application to restrict the user's ability to open or close 3300492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * the given drawer. DrawerLayout will still respond to calls to {@link #openDrawer(int)}, 3310492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * {@link #closeDrawer(int)} and friends if a drawer is locked.</p> 3320492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * 3330492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * <p>Locking a drawer open or closed will implicitly open or close 3340492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * that drawer as appropriate.</p> 3350492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * 3360492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * @param lockMode The new lock mode for the given drawer. One of {@link #LOCK_MODE_UNLOCKED}, 3370492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * {@link #LOCK_MODE_LOCKED_CLOSED} or {@link #LOCK_MODE_LOCKED_OPEN}. 3380492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * @param edgeGravity Gravity.LEFT, RIGHT, START or END. 3390492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * Expresses which drawer to change the mode for. 3400492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * 3410492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * @see #LOCK_MODE_UNLOCKED 3420492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * @see #LOCK_MODE_LOCKED_CLOSED 3430492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * @see #LOCK_MODE_LOCKED_OPEN 3440492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell */ 3450492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell public void setDrawerLockMode(int lockMode, int edgeGravity) { 346f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette final int absGravity = GravityCompat.getAbsoluteGravity(edgeGravity, 3470492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell ViewCompat.getLayoutDirection(this)); 348f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette if (absGravity == Gravity.LEFT) { 3490492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell mLockModeLeft = lockMode; 350f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette } else if (absGravity == Gravity.RIGHT) { 3510492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell mLockModeRight = lockMode; 3520492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell } 3530492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell if (lockMode != LOCK_MODE_UNLOCKED) { 3540492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell // Cancel interaction in progress 355f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette final ViewDragHelper helper = absGravity == Gravity.LEFT ? mLeftDragger : mRightDragger; 3560492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell helper.cancel(); 3570492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell } 3580492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell switch (lockMode) { 3590492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell case LOCK_MODE_LOCKED_OPEN: 360f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette final View toOpen = findDrawerWithGravity(absGravity); 3610492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell if (toOpen != null) { 3620492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell openDrawer(toOpen); 3630492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell } 3640492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell break; 3650492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell case LOCK_MODE_LOCKED_CLOSED: 366f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette final View toClose = findDrawerWithGravity(absGravity); 3670492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell if (toClose != null) { 3680492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell closeDrawer(toClose); 3690492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell } 3700492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell break; 3710492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell // default: do nothing 3720492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell } 3730492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell } 3740492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell 3750492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell /** 3760492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * Enable or disable interaction with the given drawer. 3770492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * 3780492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * <p>This allows the application to restrict the user's ability to open or close 3790492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * the given drawer. DrawerLayout will still respond to calls to {@link #openDrawer(int)}, 3800492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * {@link #closeDrawer(int)} and friends if a drawer is locked.</p> 3810492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * 3820492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * <p>Locking a drawer open or closed will implicitly open or close 3830492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * that drawer as appropriate.</p> 3840492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * 3850492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * @param lockMode The new lock mode for the given drawer. One of {@link #LOCK_MODE_UNLOCKED}, 3860492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * {@link #LOCK_MODE_LOCKED_CLOSED} or {@link #LOCK_MODE_LOCKED_OPEN}. 3870492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * @param drawerView The drawer view to change the lock mode for 3880492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * 3890492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * @see #LOCK_MODE_UNLOCKED 3900492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * @see #LOCK_MODE_LOCKED_CLOSED 3910492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * @see #LOCK_MODE_LOCKED_OPEN 3920492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell */ 3930492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell public void setDrawerLockMode(int lockMode, View drawerView) { 3940492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell if (!isDrawerView(drawerView)) { 3950492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell throw new IllegalArgumentException("View " + drawerView + " is not a " + 3960492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell "drawer with appropriate layout_gravity"); 3970492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell } 398f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette final int gravity = ((LayoutParams) drawerView.getLayoutParams()).gravity; 399f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette setDrawerLockMode(lockMode, gravity); 4000492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell } 4010492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell 4020492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell /** 4030492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * Check the lock mode of the drawer with the given gravity. 4040492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * 4050492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * @param edgeGravity Gravity of the drawer to check 4060492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * @return one of {@link #LOCK_MODE_UNLOCKED}, {@link #LOCK_MODE_LOCKED_CLOSED} or 4070492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * {@link #LOCK_MODE_LOCKED_OPEN}. 4080492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell */ 4090492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell public int getDrawerLockMode(int edgeGravity) { 410f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette final int absGravity = GravityCompat.getAbsoluteGravity( 411f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette edgeGravity, ViewCompat.getLayoutDirection(this)); 412f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette if (absGravity == Gravity.LEFT) { 4130492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell return mLockModeLeft; 414f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette } else if (absGravity == Gravity.RIGHT) { 4150492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell return mLockModeRight; 4160492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell } 4170492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell return LOCK_MODE_UNLOCKED; 4180492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell } 4190492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell 4200492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell /** 4210492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * Check the lock mode of the given drawer view. 4220492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * 4230492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * @param drawerView Drawer view to check lock mode 4240492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * @return one of {@link #LOCK_MODE_UNLOCKED}, {@link #LOCK_MODE_LOCKED_CLOSED} or 4250492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell * {@link #LOCK_MODE_LOCKED_OPEN}. 4260492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell */ 4270492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell public int getDrawerLockMode(View drawerView) { 428f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette final int absGravity = getDrawerViewAbsoluteGravity(drawerView); 429f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette if (absGravity == Gravity.LEFT) { 4300492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell return mLockModeLeft; 431f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette } else if (absGravity == Gravity.RIGHT) { 4320492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell return mLockModeRight; 4330492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell } 4340492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell return LOCK_MODE_UNLOCKED; 4350492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell } 4360492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell 4370492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell /** 4381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Resolve the shared state of all drawers from the component ViewDragHelpers. 4391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Should be called whenever a ViewDragHelper's state changes. 4401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */ 441b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell void updateDrawerState(int forGravity, int activeState, View activeDrawer) { 4421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int leftState = mLeftDragger.getViewDragState(); 4431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int rightState = mRightDragger.getViewDragState(); 4441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 4451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int state; 4461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (leftState == STATE_DRAGGING || rightState == STATE_DRAGGING) { 4471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell state = STATE_DRAGGING; 4481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } else if (leftState == STATE_SETTLING || rightState == STATE_SETTLING) { 4491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell state = STATE_SETTLING; 4501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } else { 4511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell state = STATE_IDLE; 4521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 4531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 454b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell if (activeDrawer != null && activeState == STATE_IDLE) { 455b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell final LayoutParams lp = (LayoutParams) activeDrawer.getLayoutParams(); 456b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell if (lp.onScreen == 0) { 457b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell dispatchOnDrawerClosed(activeDrawer); 458b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } else if (lp.onScreen == 1) { 459b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell dispatchOnDrawerOpened(activeDrawer); 460b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 461b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 462b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell 4631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (state != mDrawerState) { 4641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mDrawerState = state; 465b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell 4661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (mListener != null) { 4671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mListener.onDrawerStateChanged(state); 4681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 4691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 4701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 4711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 4721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell void dispatchOnDrawerClosed(View drawerView) { 4731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams(); 4741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (lp.knownOpen) { 4751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell lp.knownOpen = false; 4761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (mListener != null) { 4771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mListener.onDrawerClosed(drawerView); 4781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 4797d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); 4801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 4811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 4821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 4831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell void dispatchOnDrawerOpened(View drawerView) { 4841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams(); 4851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (!lp.knownOpen) { 4861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell lp.knownOpen = true; 4871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (mListener != null) { 4881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mListener.onDrawerOpened(drawerView); 4891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 4907d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell drawerView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); 4911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 4921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 4931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 4941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell void dispatchOnDrawerSlide(View drawerView, float slideOffset) { 4951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (mListener != null) { 4961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mListener.onDrawerSlide(drawerView, slideOffset); 4971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 4981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 4991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 5001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell void setDrawerViewOffset(View drawerView, float slideOffset) { 5011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams(); 502b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell if (slideOffset == lp.onScreen) { 5031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell return; 5041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 5051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 506b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell lp.onScreen = slideOffset; 5071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell dispatchOnDrawerSlide(drawerView, slideOffset); 5081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 5091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 5101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell float getDrawerViewOffset(View drawerView) { 511b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell return ((LayoutParams) drawerView.getLayoutParams()).onScreen; 5121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 5131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 514f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette /** 515f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette * @return the absolute gravity of the child drawerView, resolved according 516f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette * to the current layout direction 517f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette */ 518f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette int getDrawerViewAbsoluteGravity(View drawerView) { 5191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int gravity = ((LayoutParams) drawerView.getLayoutParams()).gravity; 520f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette return GravityCompat.getAbsoluteGravity(gravity, ViewCompat.getLayoutDirection(this)); 5211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 5221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 523f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette boolean checkDrawerViewAbsoluteGravity(View drawerView, int checkFor) { 524f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette final int absGravity = getDrawerViewAbsoluteGravity(drawerView); 525f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette return (absGravity & checkFor) == checkFor; 5261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 5271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 5280492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell View findOpenDrawer() { 5290492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell final int childCount = getChildCount(); 5300492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell for (int i = 0; i < childCount; i++) { 5310492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell final View child = getChildAt(i); 5320492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell if (((LayoutParams) child.getLayoutParams()).knownOpen) { 5330492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell return child; 5340492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell } 5350492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell } 5360492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell return null; 5370492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell } 5380492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell 5391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell void moveDrawerToOffset(View drawerView, float slideOffset) { 5401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final float oldOffset = getDrawerViewOffset(drawerView); 5411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int width = drawerView.getWidth(); 5421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int oldPos = (int) (width * oldOffset); 5431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int newPos = (int) (width * slideOffset); 5441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int dx = newPos - oldPos; 5451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 546f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette drawerView.offsetLeftAndRight( 547f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette checkDrawerViewAbsoluteGravity(drawerView, Gravity.LEFT) ? dx : -dx); 5481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell setDrawerViewOffset(drawerView, slideOffset); 5491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 5501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 551f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette /** 552f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette * @param gravity the gravity of the child to return. If specified as a 553f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette * relative value, it will be resolved according to the current 554f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette * layout direction. 555f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette * @return the drawer with the specified gravity 556f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette */ 5571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell View findDrawerWithGravity(int gravity) { 558f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette final int absHorizGravity = GravityCompat.getAbsoluteGravity( 559f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette gravity, ViewCompat.getLayoutDirection(this)) & Gravity.HORIZONTAL_GRAVITY_MASK; 5601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int childCount = getChildCount(); 5611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell for (int i = 0; i < childCount; i++) { 5621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final View child = getChildAt(i); 563f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette final int childAbsGravity = getDrawerViewAbsoluteGravity(child); 564f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette if ((childAbsGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == absHorizGravity) { 5651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell return child; 5661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 5671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 5681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell return null; 5691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 5701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 5711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell /** 5721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Simple gravity to string - only supports LEFT and RIGHT for debugging output. 5731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * 5741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * @param gravity Absolute gravity value 5751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * @return LEFT or RIGHT as appropriate, or a hex string 5761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */ 5771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell static String gravityToString(int gravity) { 5781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if ((gravity & Gravity.LEFT) == Gravity.LEFT) { 5791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell return "LEFT"; 5801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 5811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) { 5821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell return "RIGHT"; 5831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 5841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell return Integer.toHexString(gravity); 5851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 5861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 5871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell @Override 58857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell protected void onDetachedFromWindow() { 58957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell super.onDetachedFromWindow(); 59057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell mFirstLayout = true; 59157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell } 59257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell 59357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell @Override 59457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell protected void onAttachedToWindow() { 59557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell super.onAttachedToWindow(); 59657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell mFirstLayout = true; 59757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell } 59857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell 59957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell @Override 6001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 601c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell int widthMode = MeasureSpec.getMode(widthMeasureSpec); 602c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell int heightMode = MeasureSpec.getMode(heightMeasureSpec); 603c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell int widthSize = MeasureSpec.getSize(widthMeasureSpec); 604c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell int heightSize = MeasureSpec.getSize(heightMeasureSpec); 6051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 6061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) { 607c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell if (isInEditMode()) { 608c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell // Don't crash the layout editor. Consume all of the space if specified 609c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell // or pick a magic number from thin air otherwise. 610c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell // TODO Better communication with tools of this bogus state. 611c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell // It will crash on a real device. 612c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell if (widthMode == MeasureSpec.AT_MOST) { 613c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell widthMode = MeasureSpec.EXACTLY; 614c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell } else if (widthMode == MeasureSpec.UNSPECIFIED) { 615c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell widthMode = MeasureSpec.EXACTLY; 616c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell widthSize = 300; 617c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell } 618c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell if (heightMode == MeasureSpec.AT_MOST) { 619c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell heightMode = MeasureSpec.EXACTLY; 620c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell } 621c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell else if (heightMode == MeasureSpec.UNSPECIFIED) { 622c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell heightMode = MeasureSpec.EXACTLY; 623c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell heightSize = 300; 624c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell } 625c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell } else { 626c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell throw new IllegalArgumentException( 627c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell "DrawerLayout must be measured with MeasureSpec.EXACTLY."); 628c6f6c4511593aa49688d5425e2f6e36459076c25Adam Powell } 6291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 6301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 6311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell setMeasuredDimension(widthSize, heightSize); 6321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 6331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell // Gravity value for each drawer we've seen. Only one of each permitted. 6341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell int foundDrawers = 0; 6351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int childCount = getChildCount(); 6361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell for (int i = 0; i < childCount; i++) { 6371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final View child = getChildAt(i); 6381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 6391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (child.getVisibility() == GONE) { 6401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell continue; 6411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 6421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 64300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 64400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell 6451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (isContentView(child)) { 6461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell // Content views get measured at exactly the layout's size. 64700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell final int contentWidthSpec = MeasureSpec.makeMeasureSpec( 64800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell widthSize - lp.leftMargin - lp.rightMargin, MeasureSpec.EXACTLY); 64900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell final int contentHeightSpec = MeasureSpec.makeMeasureSpec( 65000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell heightSize - lp.topMargin - lp.bottomMargin, MeasureSpec.EXACTLY); 65100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell child.measure(contentWidthSpec, contentHeightSpec); 6521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } else if (isDrawerView(child)) { 6531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int childGravity = 654f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette getDrawerViewAbsoluteGravity(child) & Gravity.HORIZONTAL_GRAVITY_MASK; 6551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if ((foundDrawers & childGravity) != 0) { 6561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell throw new IllegalStateException("Child drawer has absolute gravity " + 6571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell gravityToString(childGravity) + " but this " + TAG + " already has a " + 6581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell "drawer view along that edge"); 6591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 66000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell final int drawerWidthSpec = getChildMeasureSpec(widthMeasureSpec, 66100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell mMinDrawerMargin + lp.leftMargin + lp.rightMargin, 66200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell lp.width); 66300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell final int drawerHeightSpec = getChildMeasureSpec(heightMeasureSpec, 66400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell lp.topMargin + lp.bottomMargin, 66500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell lp.height); 66600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell child.measure(drawerWidthSpec, drawerHeightSpec); 6671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } else { 6681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell throw new IllegalStateException("Child " + child + " at index " + i + 6691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell " does not have a valid layout_gravity - must be Gravity.LEFT, " + 6701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell "Gravity.RIGHT or Gravity.NO_GRAVITY"); 6711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 6721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 6731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 6741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 6751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell @Override 6761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell protected void onLayout(boolean changed, int l, int t, int r, int b) { 677b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell mInLayout = true; 678c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell final int width = r - l; 6791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int childCount = getChildCount(); 6801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell for (int i = 0; i < childCount; i++) { 6811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final View child = getChildAt(i); 6821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 6831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (child.getVisibility() == GONE) { 6841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell continue; 6851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 6861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 68700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 68800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell 6891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (isContentView(child)) { 69000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell child.layout(lp.leftMargin, lp.topMargin, 69100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell lp.leftMargin + child.getMeasuredWidth(), 69200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell lp.topMargin + child.getMeasuredHeight()); 6931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } else { // Drawer, if it wasn't onMeasure would have thrown an exception. 6941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int childWidth = child.getMeasuredWidth(); 69500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell final int childHeight = child.getMeasuredHeight(); 6961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell int childLeft; 6971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 698c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell final float newOffset; 699f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette if (checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) { 700b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell childLeft = -childWidth + (int) (childWidth * lp.onScreen); 701c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell newOffset = (float) (childWidth + childLeft) / childWidth; 7021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } else { // Right; onMeasure checked for us. 703c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell childLeft = width - (int) (childWidth * lp.onScreen); 704c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell newOffset = (float) (width - childLeft) / childWidth; 7051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 7061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 707c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell final boolean changeOffset = newOffset != lp.onScreen; 708c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell 70900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK; 71000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell 71100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell switch (vgrav) { 71200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell default: 71300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell case Gravity.TOP: { 7149b2fb1efe771e9927724b33242cbc3bc62b5b315Adam Powell child.layout(childLeft, lp.topMargin, childLeft + childWidth, 7159b2fb1efe771e9927724b33242cbc3bc62b5b315Adam Powell lp.topMargin + childHeight); 71600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell break; 71700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell } 71800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell 71900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell case Gravity.BOTTOM: { 72000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell final int height = b - t; 72100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell child.layout(childLeft, 72200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell height - lp.bottomMargin - child.getMeasuredHeight(), 72300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell childLeft + childWidth, 72400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell height - lp.bottomMargin); 72500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell break; 72600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell } 72700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell 72800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell case Gravity.CENTER_VERTICAL: { 72900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell final int height = b - t; 73000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell int childTop = (height - childHeight) / 2; 73100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell 73200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell // Offset for margins. If things don't fit right because of 73300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell // bad measurement before, oh well. 73400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell if (childTop < lp.topMargin) { 73500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell childTop = lp.topMargin; 73600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell } else if (childTop + childHeight > height - lp.bottomMargin) { 73700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell childTop = height - lp.bottomMargin - childHeight; 73800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell } 73900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell child.layout(childLeft, childTop, childLeft + childWidth, 74000ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell childTop + childHeight); 74100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell break; 74200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell } 74300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell } 744b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell 745c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell if (changeOffset) { 746c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell setDrawerViewOffset(child, newOffset); 747c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell } 748c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell 749c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell final int newVisibility = lp.onScreen > 0 ? VISIBLE : INVISIBLE; 750c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell if (child.getVisibility() != newVisibility) { 751c27e9ab4a09e40911d180fa0e25a0011a3adcd71Adam Powell child.setVisibility(newVisibility); 752b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 7531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 7541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 755b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell mInLayout = false; 75657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell mFirstLayout = false; 757b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 758b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell 759b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell @Override 760b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell public void requestLayout() { 761b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell if (!mInLayout) { 762b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell super.requestLayout(); 763b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 7641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 7651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 7661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell @Override 7671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public void computeScroll() { 7681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int childCount = getChildCount(); 7691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell float scrimOpacity = 0; 7701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell for (int i = 0; i < childCount; i++) { 771b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell final float onscreen = ((LayoutParams) getChildAt(i).getLayoutParams()).onScreen; 7721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell scrimOpacity = Math.max(scrimOpacity, onscreen); 7731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 7741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mScrimOpacity = scrimOpacity; 7751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 7761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell // "|" used on purpose; both need to run. 7771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (mLeftDragger.continueSettling(true) | mRightDragger.continueSettling(true)) { 7781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell ViewCompat.postInvalidateOnAnimation(this); 7791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 7801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 7811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 782b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell private static boolean hasOpaqueBackground(View v) { 783b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell final Drawable bg = v.getBackground(); 784b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell if (bg != null) { 785b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell return bg.getOpacity() == PixelFormat.OPAQUE; 786b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 787b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell return false; 788b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 789b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell 7901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell @Override 7911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell protected boolean drawChild(Canvas canvas, View child, long drawingTime) { 79200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell final int height = getHeight(); 793b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell final boolean drawingContent = isContentView(child); 794b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell int clipLeft = 0, clipRight = getWidth(); 795b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell 7961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int restoreCount = canvas.save(); 797b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell if (drawingContent) { 798b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell final int childCount = getChildCount(); 799b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell for (int i = 0; i < childCount; i++) { 800b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell final View v = getChildAt(i); 801b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell if (v == child || v.getVisibility() != VISIBLE || 80200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell !hasOpaqueBackground(v) || !isDrawerView(v) || 80300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell v.getHeight() < height) { 804b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell continue; 805b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 806b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell 807f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette if (checkDrawerViewAbsoluteGravity(v, Gravity.LEFT)) { 808b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell final int vright = v.getRight(); 809b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell if (vright > clipLeft) clipLeft = vright; 810b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } else { 811b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell final int vleft = v.getLeft(); 812b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell if (vleft < clipRight) clipRight = vleft; 813b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 814b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 815b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell canvas.clipRect(clipLeft, 0, clipRight, getHeight()); 816b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 8171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final boolean result = super.drawChild(canvas, child, drawingTime); 8181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell canvas.restoreToCount(restoreCount); 819b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell 820b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell if (mScrimOpacity > 0 && drawingContent) { 8211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int baseAlpha = (mScrimColor & 0xff000000) >>> 24; 8221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int imag = (int) (baseAlpha * mScrimOpacity); 8231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int color = imag << 24 | (mScrimColor & 0xffffff); 8241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mScrimPaint.setColor(color); 8251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 826b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell canvas.drawRect(clipLeft, 0, clipRight, getHeight(), mScrimPaint); 827f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette } else if (mShadowLeft != null && checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) { 828b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell final int shadowWidth = mShadowLeft.getIntrinsicWidth(); 829b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell final int childRight = child.getRight(); 830ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell final int drawerPeekDistance = mLeftDragger.getEdgeSize(); 831b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell final float alpha = 832ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell Math.max(0, Math.min((float) childRight / drawerPeekDistance, 1.f)); 833b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell mShadowLeft.setBounds(childRight, child.getTop(), 834b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell childRight + shadowWidth, child.getBottom()); 835b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell mShadowLeft.setAlpha((int) (0xff * alpha)); 836b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell mShadowLeft.draw(canvas); 837f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette } else if (mShadowRight != null && checkDrawerViewAbsoluteGravity(child, Gravity.RIGHT)) { 838b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell final int shadowWidth = mShadowRight.getIntrinsicWidth(); 839b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell final int childLeft = child.getLeft(); 840b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell final int showing = getWidth() - childLeft; 841ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell final int drawerPeekDistance = mRightDragger.getEdgeSize(); 842b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell final float alpha = 843ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell Math.max(0, Math.min((float) showing / drawerPeekDistance, 1.f)); 844b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell mShadowRight.setBounds(childLeft - shadowWidth, child.getTop(), 845b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell childLeft, child.getBottom()); 846b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell mShadowRight.setAlpha((int) (0xff * alpha)); 847b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell mShadowRight.draw(canvas); 8481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 8491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell return result; 8501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 8511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 8521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell boolean isContentView(View child) { 8531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell return ((LayoutParams) child.getLayoutParams()).gravity == Gravity.NO_GRAVITY; 8541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 8551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 8561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell boolean isDrawerView(View child) { 8571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int gravity = ((LayoutParams) child.getLayoutParams()).gravity; 8581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int absGravity = GravityCompat.getAbsoluteGravity(gravity, 8591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell ViewCompat.getLayoutDirection(child)); 8601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell return (absGravity & (Gravity.LEFT | Gravity.RIGHT)) != 0; 8611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 8621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 8631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell @Override 8641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public boolean onInterceptTouchEvent(MotionEvent ev) { 8651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int action = MotionEventCompat.getActionMasked(ev); 8661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 8671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell // "|" used deliberately here; both methods should be invoked. 8681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final boolean interceptForDrag = mLeftDragger.shouldInterceptTouchEvent(ev) | 8691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mRightDragger.shouldInterceptTouchEvent(ev); 8701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 8711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell boolean interceptForTap = false; 8721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 8731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell switch (action) { 8741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell case MotionEvent.ACTION_DOWN: { 8751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final float x = ev.getX(); 8761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final float y = ev.getY(); 8771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mInitialMotionX = x; 8781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mInitialMotionY = y; 8791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (mScrimOpacity > 0 && 8801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell isContentView(mLeftDragger.findTopChildUnder((int) x, (int) y))) { 8811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell interceptForTap = true; 8821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 8831732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell mDisallowInterceptRequested = false; 884cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell mChildrenCanceledTouch = false; 8851732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell break; 8861732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell } 8871732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell 8881732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell case MotionEvent.ACTION_MOVE: { 8891732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell // If we cross the touch slop, don't perform the delayed peek for an edge touch. 8901732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell if (mLeftDragger.checkTouchSlop(ViewDragHelper.DIRECTION_ALL)) { 8911732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell mLeftCallback.removeCallbacks(); 8921732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell mRightCallback.removeCallbacks(); 8931732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell } 8941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell break; 8951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 8961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 8971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell case MotionEvent.ACTION_CANCEL: 8981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell case MotionEvent.ACTION_UP: { 8991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell closeDrawers(true); 9001732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell mDisallowInterceptRequested = false; 901cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell mChildrenCanceledTouch = false; 9021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 9031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 9041732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell 905cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell return interceptForDrag || interceptForTap || hasPeekingDrawer() || mChildrenCanceledTouch; 9061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 9071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 9081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell @Override 9091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public boolean onTouchEvent(MotionEvent ev) { 9101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mLeftDragger.processTouchEvent(ev); 9111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mRightDragger.processTouchEvent(ev); 9121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 9131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int action = ev.getAction(); 9141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell boolean wantTouchEvents = true; 9151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 9161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell switch (action & MotionEventCompat.ACTION_MASK) { 9171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell case MotionEvent.ACTION_DOWN: { 9181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final float x = ev.getX(); 9191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final float y = ev.getY(); 9201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mInitialMotionX = x; 9211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mInitialMotionY = y; 9221732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell mDisallowInterceptRequested = false; 923cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell mChildrenCanceledTouch = false; 9241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell break; 9251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 9261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 9271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell case MotionEvent.ACTION_UP: { 9281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final float x = ev.getX(); 9291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final float y = ev.getY(); 9301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell boolean peekingOnly = true; 9318bc268e9c40e4ae375a0d65dc1293dccc541186fAdam Powell final View touchedView = mLeftDragger.findTopChildUnder((int) x, (int) y); 9328bc268e9c40e4ae375a0d65dc1293dccc541186fAdam Powell if (touchedView != null && isContentView(touchedView)) { 9331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final float dx = x - mInitialMotionX; 9341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final float dy = y - mInitialMotionY; 9351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int slop = mLeftDragger.getTouchSlop(); 9361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (dx * dx + dy * dy < slop * slop) { 9370492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell // Taps close a dimmed open drawer but only if it isn't locked open. 9380492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell final View openDrawer = findOpenDrawer(); 9390492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell if (openDrawer != null) { 9400492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell peekingOnly = getDrawerLockMode(openDrawer) == LOCK_MODE_LOCKED_OPEN; 9410492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell } 9421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 9431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 9441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell closeDrawers(peekingOnly); 9451732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell mDisallowInterceptRequested = false; 9461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell break; 9471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 9481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 9491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell case MotionEvent.ACTION_CANCEL: { 9501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell closeDrawers(true); 9511732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell mDisallowInterceptRequested = false; 952cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell mChildrenCanceledTouch = false; 9531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell break; 9541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 9551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 9561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 9571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell return wantTouchEvents; 9581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 9591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 960ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { 96186559d86173efb890a8edf48d935cfebfaccf049Adam Powell if (CHILDREN_DISALLOW_INTERCEPT || 96286559d86173efb890a8edf48d935cfebfaccf049Adam Powell (!mLeftDragger.isEdgeTouched(ViewDragHelper.EDGE_LEFT) && 96386559d86173efb890a8edf48d935cfebfaccf049Adam Powell !mRightDragger.isEdgeTouched(ViewDragHelper.EDGE_RIGHT))) { 9641732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell // If we have an edge touch we want to skip this and track it for later instead. 9651732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell super.requestDisallowInterceptTouchEvent(disallowIntercept); 9661732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell } 9671732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell mDisallowInterceptRequested = disallowIntercept; 968ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell if (disallowIntercept) { 969ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell closeDrawers(true); 970ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell } 971ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell } 972ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell 9731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell /** 9741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Close all currently open drawer views by animating them out of view. 9751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */ 9761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public void closeDrawers() { 9771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell closeDrawers(false); 9781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 9791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 9801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell void closeDrawers(boolean peekingOnly) { 9811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell boolean needsInvalidate = false; 9821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int childCount = getChildCount(); 9831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell for (int i = 0; i < childCount; i++) { 9841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final View child = getChildAt(i); 9851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 9861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 9871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (!isDrawerView(child) || (peekingOnly && !lp.isPeeking)) { 9881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell continue; 9891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 9901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 9911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int childWidth = child.getWidth(); 9921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 993f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette if (checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) { 9941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell needsInvalidate |= mLeftDragger.smoothSlideViewTo(child, 9951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell -childWidth, child.getTop()); 9961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } else { 9971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell needsInvalidate |= mRightDragger.smoothSlideViewTo(child, 9981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell getWidth(), child.getTop()); 9991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 10001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 10011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell lp.isPeeking = false; 10021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 10031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 10041732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell mLeftCallback.removeCallbacks(); 10051732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell mRightCallback.removeCallbacks(); 10061732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell 10071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (needsInvalidate) { 10081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell invalidate(); 10091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 10101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 10111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 10121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell /** 10131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Open the specified drawer view by animating it into view. 10141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * 10151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * @param drawerView Drawer view to open 10161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */ 10171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public void openDrawer(View drawerView) { 10181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (!isDrawerView(drawerView)) { 10191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell throw new IllegalArgumentException("View " + drawerView + " is not a sliding drawer"); 10201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 10211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 102257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell if (mFirstLayout) { 102357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams(); 102457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell lp.onScreen = 1.f; 102557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell lp.knownOpen = true; 10261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } else { 1027f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette if (checkDrawerViewAbsoluteGravity(drawerView, Gravity.LEFT)) { 102857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell mLeftDragger.smoothSlideViewTo(drawerView, 0, drawerView.getTop()); 102957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell } else { 103057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell mRightDragger.smoothSlideViewTo(drawerView, getWidth() - drawerView.getWidth(), 103157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell drawerView.getTop()); 103257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell } 10331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 10341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell invalidate(); 10351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 10361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 10371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell /** 10381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Open the specified drawer by animating it out of view. 10391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * 10401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * @param gravity Gravity.LEFT to move the left drawer or Gravity.RIGHT for the right. 10411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * GravityCompat.START or GravityCompat.END may also be used. 10421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */ 10431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public void openDrawer(int gravity) { 1044f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette final View drawerView = findDrawerWithGravity(gravity); 10451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (drawerView == null) { 1046f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette throw new IllegalArgumentException("No drawer view found with gravity " + 1047f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette gravityToString(gravity)); 10481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 10491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell openDrawer(drawerView); 10501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 10511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 10521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell /** 10531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Close the specified drawer view by animating it into view. 10541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * 10551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * @param drawerView Drawer view to close 10561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */ 10571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public void closeDrawer(View drawerView) { 10581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (!isDrawerView(drawerView)) { 10591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell throw new IllegalArgumentException("View " + drawerView + " is not a sliding drawer"); 10601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 10611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 106257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell if (mFirstLayout) { 106357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams(); 106457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell lp.onScreen = 0.f; 106557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell lp.knownOpen = false; 10661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } else { 1067f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette if (checkDrawerViewAbsoluteGravity(drawerView, Gravity.LEFT)) { 106857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell mLeftDragger.smoothSlideViewTo(drawerView, -drawerView.getWidth(), 106957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell drawerView.getTop()); 107057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell } else { 107157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell mRightDragger.smoothSlideViewTo(drawerView, getWidth(), drawerView.getTop()); 107257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell } 10731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 10741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell invalidate(); 10751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 10761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 10771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell /** 10781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Close the specified drawer by animating it out of view. 10791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * 10801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * @param gravity Gravity.LEFT to move the left drawer or Gravity.RIGHT for the right. 10811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * GravityCompat.START or GravityCompat.END may also be used. 10821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */ 10831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public void closeDrawer(int gravity) { 1084f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette final View drawerView = findDrawerWithGravity(gravity); 10851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (drawerView == null) { 1086f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette throw new IllegalArgumentException("No drawer view found with gravity " + 1087f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette gravityToString(gravity)); 10881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 10891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell closeDrawer(drawerView); 10901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 10911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 1092b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell /** 1093b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * Check if the given drawer view is currently in an open state. 1094b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * To be considered "open" the drawer must have settled into its fully 1095b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * visible state. To check for partial visibility use 1096b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * {@link #isDrawerVisible(android.view.View)}. 1097b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * 1098b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * @param drawer Drawer view to check 1099b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * @return true if the given drawer view is in an open state 1100b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * @see #isDrawerVisible(android.view.View) 1101b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell */ 1102b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell public boolean isDrawerOpen(View drawer) { 1103b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell if (!isDrawerView(drawer)) { 1104b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell throw new IllegalArgumentException("View " + drawer + " is not a drawer"); 1105b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 1106b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell return ((LayoutParams) drawer.getLayoutParams()).knownOpen; 1107b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 1108b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell 1109b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell /** 111079f95ce3e660d267831067e514ff455156c4381fAdam Powell * Check if the given drawer view is currently in an open state. 111179f95ce3e660d267831067e514ff455156c4381fAdam Powell * To be considered "open" the drawer must have settled into its fully 111279f95ce3e660d267831067e514ff455156c4381fAdam Powell * visible state. If there is no drawer with the given gravity this method 111379f95ce3e660d267831067e514ff455156c4381fAdam Powell * will return false. 111479f95ce3e660d267831067e514ff455156c4381fAdam Powell * 111579f95ce3e660d267831067e514ff455156c4381fAdam Powell * @param drawerGravity Gravity of the drawer to check 111679f95ce3e660d267831067e514ff455156c4381fAdam Powell * @return true if the given drawer view is in an open state 111779f95ce3e660d267831067e514ff455156c4381fAdam Powell */ 111879f95ce3e660d267831067e514ff455156c4381fAdam Powell public boolean isDrawerOpen(int drawerGravity) { 111979f95ce3e660d267831067e514ff455156c4381fAdam Powell final View drawerView = findDrawerWithGravity(drawerGravity); 112079f95ce3e660d267831067e514ff455156c4381fAdam Powell if (drawerView != null) { 112179f95ce3e660d267831067e514ff455156c4381fAdam Powell return isDrawerOpen(drawerView); 112279f95ce3e660d267831067e514ff455156c4381fAdam Powell } 112379f95ce3e660d267831067e514ff455156c4381fAdam Powell return false; 112479f95ce3e660d267831067e514ff455156c4381fAdam Powell } 112579f95ce3e660d267831067e514ff455156c4381fAdam Powell 112679f95ce3e660d267831067e514ff455156c4381fAdam Powell /** 1127b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * Check if a given drawer view is currently visible on-screen. The drawer 1128b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * may be only peeking onto the screen, fully extended, or anywhere inbetween. 1129b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * 1130b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * @param drawer Drawer view to check 1131b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * @return true if the given drawer is visible on-screen 1132b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell * @see #isDrawerOpen(android.view.View) 1133b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell */ 1134b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell public boolean isDrawerVisible(View drawer) { 1135b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell if (!isDrawerView(drawer)) { 1136b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell throw new IllegalArgumentException("View " + drawer + " is not a drawer"); 1137b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 1138b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell return ((LayoutParams) drawer.getLayoutParams()).onScreen > 0; 1139b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell } 1140b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell 114179f95ce3e660d267831067e514ff455156c4381fAdam Powell /** 114279f95ce3e660d267831067e514ff455156c4381fAdam Powell * Check if a given drawer view is currently visible on-screen. The drawer 114379f95ce3e660d267831067e514ff455156c4381fAdam Powell * may be only peeking onto the screen, fully extended, or anywhere inbetween. 114479f95ce3e660d267831067e514ff455156c4381fAdam Powell * If there is no drawer with the given gravity this method will return false. 114579f95ce3e660d267831067e514ff455156c4381fAdam Powell * 114679f95ce3e660d267831067e514ff455156c4381fAdam Powell * @param drawerGravity Gravity of the drawer to check 114779f95ce3e660d267831067e514ff455156c4381fAdam Powell * @return true if the given drawer is visible on-screen 114879f95ce3e660d267831067e514ff455156c4381fAdam Powell */ 114979f95ce3e660d267831067e514ff455156c4381fAdam Powell public boolean isDrawerVisible(int drawerGravity) { 115079f95ce3e660d267831067e514ff455156c4381fAdam Powell final View drawerView = findDrawerWithGravity(drawerGravity); 115179f95ce3e660d267831067e514ff455156c4381fAdam Powell if (drawerView != null) { 115279f95ce3e660d267831067e514ff455156c4381fAdam Powell return isDrawerVisible(drawerView); 115379f95ce3e660d267831067e514ff455156c4381fAdam Powell } 115479f95ce3e660d267831067e514ff455156c4381fAdam Powell return false; 115579f95ce3e660d267831067e514ff455156c4381fAdam Powell } 115679f95ce3e660d267831067e514ff455156c4381fAdam Powell 1157ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell private boolean hasPeekingDrawer() { 1158ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell final int childCount = getChildCount(); 1159ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell for (int i = 0; i < childCount; i++) { 1160ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell final LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams(); 1161ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell if (lp.isPeeking) { 1162ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell return true; 1163ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell } 1164ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell } 1165ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell return false; 1166ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell } 1167ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell 11681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell @Override 11691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell protected ViewGroup.LayoutParams generateDefaultLayoutParams() { 11701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell return new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); 11711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 11721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 11731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell @Override 11741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 11751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell return p instanceof LayoutParams 11761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell ? new LayoutParams((LayoutParams) p) 117700ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell : p instanceof ViewGroup.MarginLayoutParams 117800ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell ? new LayoutParams((MarginLayoutParams) p) 11791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell : new LayoutParams(p); 11801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 11811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 11821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell @Override 11831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 11841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell return p instanceof LayoutParams && super.checkLayoutParams(p); 11851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 11861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 11871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell @Override 11881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { 11891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell return new LayoutParams(getContext(), attrs); 11901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 11911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 1192791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell private boolean hasVisibleDrawer() { 11930492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell return findVisibleDrawer() != null; 11940492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell } 11950492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell 11960492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell private View findVisibleDrawer() { 1197791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell final int childCount = getChildCount(); 1198791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell for (int i = 0; i < childCount; i++) { 1199791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell final View child = getChildAt(i); 1200791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell if (isDrawerView(child) && isDrawerVisible(child)) { 12010492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell return child; 1202791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell } 1203791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell } 12040492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell return null; 1205791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell } 1206791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell 1207cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell void cancelChildViewTouch() { 1208cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell // Cancel child touches 1209cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell if (!mChildrenCanceledTouch) { 1210cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell final long now = SystemClock.uptimeMillis(); 1211cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell final MotionEvent cancelEvent = MotionEvent.obtain(now, now, 1212cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0); 1213cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell final int childCount = getChildCount(); 1214cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell for (int i = 0; i < childCount; i++) { 1215cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell getChildAt(i).dispatchTouchEvent(cancelEvent); 1216cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell } 1217cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell cancelEvent.recycle(); 1218cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell mChildrenCanceledTouch = true; 1219cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell } 1220cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell } 1221cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell 1222791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell @Override 1223791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell public boolean onKeyDown(int keyCode, KeyEvent event) { 1224791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell if (keyCode == KeyEvent.KEYCODE_BACK && hasVisibleDrawer()) { 1225791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell KeyEventCompat.startTracking(event); 1226791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell return true; 1227791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell } 1228791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell return super.onKeyDown(keyCode, event); 1229791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell } 1230791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell 1231791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell @Override 1232791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell public boolean onKeyUp(int keyCode, KeyEvent event) { 12330492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell if (keyCode == KeyEvent.KEYCODE_BACK) { 12340492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell final View visibleDrawer = findVisibleDrawer(); 12350492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell if (visibleDrawer != null && getDrawerLockMode(visibleDrawer) == LOCK_MODE_UNLOCKED) { 12360492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell closeDrawers(); 12370492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell } 12380492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell return visibleDrawer != null; 1239791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell } 1240791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell return super.onKeyUp(keyCode, event); 1241791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell } 1242791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell 124357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell @Override 124457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell protected void onRestoreInstanceState(Parcelable state) { 124557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell final SavedState ss = (SavedState) state; 124657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell super.onRestoreInstanceState(ss.getSuperState()); 124757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell 124857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell if (ss.openDrawerGravity != Gravity.NO_GRAVITY) { 124957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell final View toOpen = findDrawerWithGravity(ss.openDrawerGravity); 125057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell if (toOpen != null) { 125157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell openDrawer(toOpen); 125257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell } 125357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell } 12548e01d24e718d603974182cd48f648369c07edec1Adam Powell 12558e01d24e718d603974182cd48f648369c07edec1Adam Powell setDrawerLockMode(ss.lockModeLeft, Gravity.LEFT); 12568e01d24e718d603974182cd48f648369c07edec1Adam Powell setDrawerLockMode(ss.lockModeRight, Gravity.RIGHT); 125757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell } 125857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell 125957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell @Override 126057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell protected Parcelable onSaveInstanceState() { 126157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell final Parcelable superState = super.onSaveInstanceState(); 126257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell 126357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell final SavedState ss = new SavedState(superState); 126457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell 126557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell final int childCount = getChildCount(); 126657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell for (int i = 0; i < childCount; i++) { 126757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell final View child = getChildAt(i); 126857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell if (!isDrawerView(child)) { 126957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell continue; 127057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell } 127157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell 127257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 127357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell if (lp.knownOpen) { 127457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell ss.openDrawerGravity = lp.gravity; 127557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell // Only one drawer can be open at a time. 127657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell break; 127757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell } 127857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell } 127957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell 12808e01d24e718d603974182cd48f648369c07edec1Adam Powell ss.lockModeLeft = mLockModeLeft; 12818e01d24e718d603974182cd48f648369c07edec1Adam Powell ss.lockModeRight = mLockModeRight; 12828e01d24e718d603974182cd48f648369c07edec1Adam Powell 128357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell return ss; 128457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell } 128557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell 128657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell /** 128757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell * State persisted across instances 128857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell */ 128957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell protected static class SavedState extends BaseSavedState { 129057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell int openDrawerGravity = Gravity.NO_GRAVITY; 12918e01d24e718d603974182cd48f648369c07edec1Adam Powell int lockModeLeft = LOCK_MODE_UNLOCKED; 12928e01d24e718d603974182cd48f648369c07edec1Adam Powell int lockModeRight = LOCK_MODE_UNLOCKED; 129357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell 129457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell public SavedState(Parcel in) { 129557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell super(in); 129657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell openDrawerGravity = in.readInt(); 129757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell } 129857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell 129957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell public SavedState(Parcelable superState) { 130057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell super(superState); 130157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell } 130257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell 130357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell @Override 130457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell public void writeToParcel(Parcel dest, int flags) { 130557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell super.writeToParcel(dest, flags); 130657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell dest.writeInt(openDrawerGravity); 130757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell } 130857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell 130957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell public static final Parcelable.Creator<SavedState> CREATOR = 131057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell new Parcelable.Creator<SavedState>() { 131157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell @Override 131257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell public SavedState createFromParcel(Parcel source) { 131357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell return new SavedState(source); 131457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell } 131557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell 131657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell @Override 131757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell public SavedState[] newArray(int size) { 131857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell return new SavedState[size]; 131957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell } 132057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell }; 132157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell } 132257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell 13231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell private class ViewDragCallback extends ViewDragHelper.Callback { 1324f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette private final int mAbsGravity; 13251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell private ViewDragHelper mDragger; 13261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 13271732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell private final Runnable mPeekRunnable = new Runnable() { 13281732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell @Override public void run() { 13291732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell peekDrawer(); 13301732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell } 13311732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell }; 13321732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell 13331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public ViewDragCallback(int gravity) { 1334f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette mAbsGravity = gravity; 13351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 13361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 13371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public void setDragger(ViewDragHelper dragger) { 13381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mDragger = dragger; 13391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 13401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 13411732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell public void removeCallbacks() { 13421732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell DrawerLayout.this.removeCallbacks(mPeekRunnable); 13431732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell } 13441732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell 13451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell @Override 13461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public boolean tryCaptureView(View child, int pointerId) { 13471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell // Only capture views where the gravity matches what we're looking for. 13481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell // This lets us use two ViewDragHelpers, one for each side drawer. 1349f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette return isDrawerView(child) && checkDrawerViewAbsoluteGravity(child, mAbsGravity) 1350f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette && getDrawerLockMode(child) == LOCK_MODE_UNLOCKED; 13511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 13521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 13531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell @Override 13541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public void onViewDragStateChanged(int state) { 1355f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette updateDrawerState(mAbsGravity, state, mDragger.getCapturedView()); 13561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 13571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 13581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell @Override 13591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { 13601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell float offset; 13611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int childWidth = changedView.getWidth(); 13621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 13631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell // This reverses the positioning shown in onLayout. 1364f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette if (checkDrawerViewAbsoluteGravity(changedView, Gravity.LEFT)) { 13651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell offset = (float) (childWidth + left) / childWidth; 13661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } else { 13671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int width = getWidth(); 13681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell offset = (float) (width - left) / childWidth; 13691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 13701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell setDrawerViewOffset(changedView, offset); 1371b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell changedView.setVisibility(offset == 0 ? INVISIBLE : VISIBLE); 13721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell invalidate(); 13731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 13741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 13751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell @Override 13761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public void onViewCaptured(View capturedChild, int activePointerId) { 13771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final LayoutParams lp = (LayoutParams) capturedChild.getLayoutParams(); 13781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell lp.isPeeking = false; 13791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 13801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell closeOtherDrawer(); 13811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 13821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 13831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell private void closeOtherDrawer() { 1384f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette final int otherGrav = mAbsGravity == Gravity.LEFT ? Gravity.RIGHT : Gravity.LEFT; 13851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final View toClose = findDrawerWithGravity(otherGrav); 13861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if (toClose != null) { 13871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell closeDrawer(toClose); 13881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 13891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 13901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 13911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell @Override 13921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public void onViewReleased(View releasedChild, float xvel, float yvel) { 13931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell // Offset is how open the drawer is, therefore left/right values 13941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell // are reversed from one another. 13951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final float offset = getDrawerViewOffset(releasedChild); 13961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int childWidth = releasedChild.getWidth(); 13971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 13981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell int left; 1399f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette if (checkDrawerViewAbsoluteGravity(releasedChild, Gravity.LEFT)) { 14001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell left = xvel > 0 || xvel == 0 && offset > 0.5f ? 0 : -childWidth; 14011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } else { 14021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int width = getWidth(); 14037d690eb050d901c7a7b4ebc3896471124ef98f7cAdam Powell left = xvel < 0 || xvel == 0 && offset > 0.5f ? width - childWidth : width; 14041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 14051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 14061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mDragger.settleCapturedViewAt(left, releasedChild.getTop()); 14071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell invalidate(); 14081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 14091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 14101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell @Override 14111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public void onEdgeTouched(int edgeFlags, int pointerId) { 14121732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell postDelayed(mPeekRunnable, PEEK_DELAY); 14131732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell } 14141732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell 14151732720ad57fe6d01392cd06551f1a25cff0333cAdam Powell private void peekDrawer() { 14161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final View toCapture; 14171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int childLeft; 1418ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell final int peekDistance = mDragger.getEdgeSize(); 1419f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette final boolean leftEdge = mAbsGravity == Gravity.LEFT; 1420b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell if (leftEdge) { 14211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell toCapture = findDrawerWithGravity(Gravity.LEFT); 1422ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell childLeft = (toCapture != null ? -toCapture.getWidth() : 0) + peekDistance; 14231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } else { 14241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell toCapture = findDrawerWithGravity(Gravity.RIGHT); 1425ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell childLeft = getWidth() - peekDistance; 14261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 14270492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell // Only peek if it would mean making the drawer more visible and the drawer isn't locked 1428b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell if (toCapture != null && ((leftEdge && toCapture.getLeft() < childLeft) || 14290492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell (!leftEdge && toCapture.getLeft() > childLeft)) && 14300492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell getDrawerLockMode(toCapture) == LOCK_MODE_UNLOCKED) { 1431b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell final LayoutParams lp = (LayoutParams) toCapture.getLayoutParams(); 14321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mDragger.smoothSlideViewTo(toCapture, childLeft, toCapture.getTop()); 1433b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell lp.isPeeking = true; 14341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell invalidate(); 14351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 14361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell closeOtherDrawer(); 1437cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell 1438cde2707260e8241ffb816a03cbf5d52c28004b8aAdam Powell cancelChildViewTouch(); 14391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 14401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 14411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 14421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell @Override 1443ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell public boolean onEdgeLock(int edgeFlags) { 1444ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell if (ALLOW_EDGE_LOCK) { 1445f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette final View drawer = findDrawerWithGravity(mAbsGravity); 1446ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell if (drawer != null && !isDrawerOpen(drawer)) { 1447ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell closeDrawer(drawer); 1448ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell } 1449ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell return true; 1450acc82321ad119706485db342eaa12b225fa9b667Adam Powell } 1451ea7b10f4d5531713506e98c8093e7aab811f21f3Adam Powell return false; 1452acc82321ad119706485db342eaa12b225fa9b667Adam Powell } 1453acc82321ad119706485db342eaa12b225fa9b667Adam Powell 1454acc82321ad119706485db342eaa12b225fa9b667Adam Powell @Override 14551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public void onEdgeDragStarted(int edgeFlags, int pointerId) { 14561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final View toCapture; 14571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell if ((edgeFlags & ViewDragHelper.EDGE_LEFT) == ViewDragHelper.EDGE_LEFT) { 14581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell toCapture = findDrawerWithGravity(Gravity.LEFT); 14591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } else { 14601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell toCapture = findDrawerWithGravity(Gravity.RIGHT); 14611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 14621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 14630492ea23e32dbf509a7613d29e5791fdd44b2135Adam Powell if (toCapture != null && getDrawerLockMode(toCapture) == LOCK_MODE_UNLOCKED) { 14641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell mDragger.captureChildView(toCapture, pointerId); 14651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 14661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 14671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 14681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell @Override 14691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public int getViewHorizontalDragRange(View child) { 14701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell return child.getWidth(); 14711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 14721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 14731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell @Override 14741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public int clampViewPositionHorizontal(View child, int left, int dx) { 1475f55dfacb0db5da12ad3b9e5615c3feaea372f37dAlan Viverette if (checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) { 14761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell return Math.max(-child.getWidth(), Math.min(left, 0)); 14771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } else { 14781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final int width = getWidth(); 14791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell return Math.max(width - child.getWidth(), Math.min(left, width)); 14801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 14811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 148200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell 148300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell @Override 148400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell public int clampViewPositionVertical(View child, int top, int dy) { 148500ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell return child.getTop(); 148600ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell } 14871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 14881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 148900ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell public static class LayoutParams extends ViewGroup.MarginLayoutParams { 14901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 14911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public int gravity = Gravity.NO_GRAVITY; 1492b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell float onScreen; 14931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell boolean isPeeking; 14941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell boolean knownOpen; 14951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 14961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public LayoutParams(Context c, AttributeSet attrs) { 14971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell super(c, attrs); 14981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 14991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell final TypedArray a = c.obtainStyledAttributes(attrs, LAYOUT_ATTRS); 15001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell this.gravity = a.getInt(0, Gravity.NO_GRAVITY); 15011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell a.recycle(); 15021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 15031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 15041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public LayoutParams(int width, int height) { 15051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell super(width, height); 15061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 15071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 15081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public LayoutParams(int width, int height, int gravity) { 15091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell this(width, height); 15101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell this.gravity = gravity; 15111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 15121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 15131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public LayoutParams(LayoutParams source) { 15141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell super(source); 15151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell this.gravity = source.gravity; 15161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 15171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell 15181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell public LayoutParams(ViewGroup.LayoutParams source) { 15191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell super(source); 15201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 152100ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell 152200ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell public LayoutParams(ViewGroup.MarginLayoutParams source) { 152300ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell super(source); 152400ca2532981fbd705f947a637ffd967a8d6f733bAdam Powell } 15251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell } 15267d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell 15277d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell class AccessibilityDelegate extends AccessibilityDelegateCompat { 15283cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell private final Rect mTmpRect = new Rect(); 15293cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell 15307d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell @Override 15317d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { 15323cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell final AccessibilityNodeInfoCompat superNode = AccessibilityNodeInfoCompat.obtain(info); 15333cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell super.onInitializeAccessibilityNodeInfo(host, superNode); 15343cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell 15353cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell info.setSource(host); 15363cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell final ViewParent parent = ViewCompat.getParentForAccessibility(host); 15373cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell if (parent instanceof View) { 15383cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell info.setParent((View) parent); 15393cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell } 15403cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell copyNodeInfoNoChildren(info, superNode); 15413cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell 15423cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell superNode.recycle(); 15433cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell 1544d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette addChildrenForAccessibility(info, (ViewGroup) host); 1545d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette } 1546d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette 1547d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette private void addChildrenForAccessibility(AccessibilityNodeInfoCompat info, ViewGroup v) { 1548d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette final int childCount = v.getChildCount(); 15497d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell for (int i = 0; i < childCount; i++) { 1550d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette final View child = v.getChildAt(i); 1551d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette if (filter(child)) { 1552d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette continue; 1553d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette } 1554d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette 1555d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette // Adding children that are marked as not important for 1556d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette // accessibility will break the hierarchy, so we need to check 1557d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette // that value and re-parent views if necessary. 1558d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette final int importance = ViewCompat.getImportantForAccessibility(child); 1559d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette switch (importance) { 1560d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette case ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS: 1561d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette // Always skip NO_HIDE views and their descendants. 1562d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette break; 1563d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette case ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO: 1564d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette // Re-parent children of NO view groups, skip NO views. 1565d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette if (child instanceof ViewGroup) { 1566d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette addChildrenForAccessibility(info, (ViewGroup) child); 1567d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette } 1568d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette break; 1569d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette case ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO: 1570d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette // Force AUTO views to YES and add them. 1571d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette ViewCompat.setImportantForAccessibility( 1572d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette child, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES); 1573d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette case ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES: 1574d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette info.addChild(child); 1575d6edbe712f21ea4924ab9fb49ebd8c94d1e03884Alan Viverette break; 15767d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell } 15777d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell } 15787d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell } 15797d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell 15807d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell @Override 15817d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, 15827d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell AccessibilityEvent event) { 15837d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell if (!filter(child)) { 15847d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell return super.onRequestSendAccessibilityEvent(host, child, event); 15857d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell } 15867d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell return false; 15877d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell } 15887d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell 15897d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell public boolean filter(View child) { 15907d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell final View openDrawer = findOpenDrawer(); 15917d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell return openDrawer != null && openDrawer != child; 15927d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell } 15933cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell 15943cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell /** 15953cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell * This should really be in AccessibilityNodeInfoCompat, but there unfortunately 15963cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell * seem to be a few elements that are not easily cloneable using the underlying API. 15973cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell * Leave it private here as it's not general-purpose useful. 15983cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell */ 15993cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell private void copyNodeInfoNoChildren(AccessibilityNodeInfoCompat dest, 16003cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell AccessibilityNodeInfoCompat src) { 16013cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell final Rect rect = mTmpRect; 16023cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell 16033cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell src.getBoundsInParent(rect); 16043cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell dest.setBoundsInParent(rect); 16053cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell 16063cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell src.getBoundsInScreen(rect); 16073cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell dest.setBoundsInScreen(rect); 16083cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell 16093cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell dest.setVisibleToUser(src.isVisibleToUser()); 16103cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell dest.setPackageName(src.getPackageName()); 16113cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell dest.setClassName(src.getClassName()); 16123cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell dest.setContentDescription(src.getContentDescription()); 16133cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell 16143cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell dest.setEnabled(src.isEnabled()); 16153cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell dest.setClickable(src.isClickable()); 16163cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell dest.setFocusable(src.isFocusable()); 16173cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell dest.setFocused(src.isFocused()); 16183cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell dest.setAccessibilityFocused(src.isAccessibilityFocused()); 16193cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell dest.setSelected(src.isSelected()); 16203cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell dest.setLongClickable(src.isLongClickable()); 16213cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell 16223cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell dest.addAction(src.getActions()); 16233cf6141d516a0a6170823b1bda5c0b6d7500e76cAdam Powell } 16247d0061d5605a1ac298837bee21c0d4eb4a34bd4eAdam Powell } 16251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell} 1626