DrawerLayout.java revision 8bc268e9c40e4ae375a0d65dc1293dccc541186f
11d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell/*
21d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Copyright (C) 2013 The Android Open Source Project
31d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell *
41d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Licensed under the Apache License, Version 2.0 (the "License");
51d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * you may not use this file except in compliance with the License.
61d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * You may obtain a copy of the License at
71d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell *
81d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell *      http://www.apache.org/licenses/LICENSE-2.0
91d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell *
101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * Unless required by applicable law or agreed to in writing, software
111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * distributed under the License is distributed on an "AS IS" BASIS,
121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * See the License for the specific language governing permissions and
141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * limitations under the License.
151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */
161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellpackage android.support.v4.widget;
191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.content.Context;
211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.content.res.TypedArray;
221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.graphics.Canvas;
231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.graphics.Paint;
24b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powellimport android.graphics.PixelFormat;
25b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powellimport android.graphics.drawable.Drawable;
2657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powellimport android.os.Parcel;
2757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powellimport android.os.Parcelable;
281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.support.v4.view.GravityCompat;
29791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powellimport android.support.v4.view.KeyEventCompat;
301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.support.v4.view.MotionEventCompat;
311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.support.v4.view.ViewCompat;
321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.util.AttributeSet;
331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.Gravity;
34791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powellimport android.view.KeyEvent;
351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.MotionEvent;
361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.View;
371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellimport android.view.ViewGroup;
381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell/**
401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * DrawerLayout acts as a top-level container for window content that allows for
411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * interactive "drawer" views to be pulled out from the edge of the window.
421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell *
431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * <p>Drawer positioning and layout is controlled using the <code>android:layout_gravity</code>
441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * attribute on child views corresponding to </p>
451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell *
461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * <p>As per the Android Design guide, any drawers positioned to the left/start should
471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * always contain content for navigating around the application, whereas any drawers
481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * positioned to the right/end should always contain actions to take on the current content.
491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * This preserves the same navigation left, actions right structure present in the Action Bar
501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * and elsewhere.</p>
511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell */
521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powellpublic class DrawerLayout extends ViewGroup {
531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final String TAG = "DrawerLayout";
541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final int INVALID_POINTER = -1;
561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Indicates that any drawers are in an idle, settled state. No animation is in progress.
591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public static final int STATE_IDLE = ViewDragHelper.STATE_IDLE;
611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Indicates that a drawer is currently being dragged by the user.
641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public static final int STATE_DRAGGING = ViewDragHelper.STATE_DRAGGING;
661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Indicates that a drawer is in the process of settling to a final position.
691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public static final int STATE_SETTLING = ViewDragHelper.STATE_SETTLING;
711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final int MIN_DRAWER_MARGIN = 64; // dp
731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final int DRAWER_PEEK_DISTANCE = 16; // dp
751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final int DEFAULT_SCRIM_COLOR = 0x99000000;
771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private static final int[] LAYOUT_ATTRS = new int[] {
791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            android.R.attr.layout_gravity
801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    };
811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private int mMinDrawerMargin;
831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private int mDrawerPeekDistance;
841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private int mScrimColor = DEFAULT_SCRIM_COLOR;
861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private float mScrimOpacity;
871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private Paint mScrimPaint = new Paint();
881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private final ViewDragHelper mLeftDragger;
901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private final ViewDragHelper mRightDragger;
911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private int mDrawerState;
92b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    private boolean mInLayout;
9357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    private boolean mFirstLayout = true;
941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private DrawerListener mListener;
961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private float mInitialMotionX;
981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private float mInitialMotionY;
991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
100b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    private Drawable mShadowLeft;
101b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    private Drawable mShadowRight;
102b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
1031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
1041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Listener for monitoring events about drawers.
1051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
1061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public interface DrawerListener {
1071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
1081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when a drawer's position changes.
1091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param drawerView The child view that was moved
1101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param slideOffset The new offset of this drawer within its range, from 0-1
1111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
1121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onDrawerSlide(View drawerView, float slideOffset);
1131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
1151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when a drawer has settled in a completely open state.
1161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * The drawer is interactive at this point.
1171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         *
1181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param drawerView Drawer view that is now open
1191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
1201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onDrawerOpened(View drawerView);
1211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
1231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when a drawer has settled in a completely closed state.
1241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         *
1251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param drawerView Drawer view that is now closed
1261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
1271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onDrawerClosed(View drawerView);
1281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        /**
1301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * Called when the drawer motion state changes. The new state will
1311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * be one of {@link #STATE_IDLE}, {@link #STATE_DRAGGING} or {@link #STATE_SETTLING}.
1321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         *
1331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         * @param newState The new drawer motion state
1341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell         */
1351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onDrawerStateChanged(int newState);
1361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
1371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
138b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
139b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Stub/no-op implementations of all methods of {@link DrawerListener}.
140b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Override this if you only care about a few of the available callback methods.
141b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
142b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public static abstract class SimpleDrawerListener implements DrawerListener {
143b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
144b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerSlide(View drawerView, float slideOffset) {
145b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
146b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
147b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
148b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerOpened(View drawerView) {
149b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
150b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
151b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
152b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerClosed(View drawerView) {
153b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
154b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
155b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        @Override
156b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        public void onDrawerStateChanged(int newState) {
157b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
158b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
159b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
1601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public DrawerLayout(Context context) {
1611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        this(context, null);
1621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
1631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public DrawerLayout(Context context, AttributeSet attrs) {
1651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        this(context, attrs, 0);
1661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
1671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public DrawerLayout(Context context, AttributeSet attrs, int defStyle) {
1691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        super(context, attrs, defStyle);
1701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final float density = getResources().getDisplayMetrics().density;
1721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mMinDrawerMargin = (int) (MIN_DRAWER_MARGIN * density + 0.5f);
1731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mDrawerPeekDistance = (int) (DRAWER_PEEK_DISTANCE * density + 0.5f);
1741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final ViewDragCallback leftCallback = new ViewDragCallback(Gravity.LEFT);
1761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final ViewDragCallback rightCallback = new ViewDragCallback(Gravity.RIGHT);
1771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mLeftDragger = ViewDragHelper.create(this, 0.5f, leftCallback);
1791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mLeftDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
1801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        leftCallback.setDragger(mLeftDragger);
1811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mRightDragger = ViewDragHelper.create(this, 0.5f, rightCallback);
1831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mRightDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_RIGHT);
1841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        rightCallback.setDragger(mRightDragger);
185791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
186791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        // So that we can catch the back button
187791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        setFocusableInTouchMode(true);
1881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
1891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
191b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Set a simple drawable used for the left or right shadow.
192b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * The drawable provided must have a nonzero intrinsic width.
193b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
194b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param shadowDrawable Shadow drawable to use at the edge of a drawer
195b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param gravity Which drawer the shadow should apply to
196b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
197b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public void setDrawerShadow(Drawable shadowDrawable, int gravity) {
198b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        /*
199b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         * TODO Someone someday might want to set more complex drawables here.
200b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         * They're probably nuts, but we might want to consider registering callbacks,
201b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         * setting states, etc. properly.
202b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell         */
203b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
204b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        final int absGravity = GravityCompat.getAbsoluteGravity(gravity,
205b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                ViewCompat.getLayoutDirection(this));
206b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if ((absGravity & Gravity.LEFT) == Gravity.LEFT) {
207b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowLeft = shadowDrawable;
208b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            invalidate();
209b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
210b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if ((absGravity & Gravity.RIGHT) == Gravity.RIGHT) {
211b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowRight = shadowDrawable;
212b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            invalidate();
213b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
214b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
215b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
216b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
217b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Set a simple drawable used for the left or right shadow.
218b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * The drawable provided must have a nonzero intrinsic width.
219b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
220b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param resId Resource id of a shadow drawable to use at the edge of a drawer
221b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param gravity Which drawer the shadow should apply to
222b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
223b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public void setDrawerShadow(int resId, int gravity) {
224b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        setDrawerShadow(getResources().getDrawable(resId), gravity);
225b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
226b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
227b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
2281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Set a listener to be notified of drawer events.
2291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
2301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param listener Listener to notify when drawer events occur
2311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @see DrawerListener
2321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
2331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void setDrawerListener(DrawerListener listener) {
2341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mListener = listener;
2351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
2361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
2381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Resolve the shared state of all drawers from the component ViewDragHelpers.
2391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Should be called whenever a ViewDragHelper's state changes.
2401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
241b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    void updateDrawerState(int forGravity, int activeState, View activeDrawer) {
2421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int leftState = mLeftDragger.getViewDragState();
2431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int rightState = mRightDragger.getViewDragState();
2441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int state;
2461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (leftState == STATE_DRAGGING || rightState == STATE_DRAGGING) {
2471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            state = STATE_DRAGGING;
2481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        } else if (leftState == STATE_SETTLING || rightState == STATE_SETTLING) {
2491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            state = STATE_SETTLING;
2501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        } else {
2511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            state = STATE_IDLE;
2521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
2531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
254b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (activeDrawer != null && activeState == STATE_IDLE) {
255b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final LayoutParams lp = (LayoutParams) activeDrawer.getLayoutParams();
256b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            if (lp.onScreen == 0) {
257b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                dispatchOnDrawerClosed(activeDrawer);
258b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            } else if (lp.onScreen == 1) {
259b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                dispatchOnDrawerOpened(activeDrawer);
260b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            }
261b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
262b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
2631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (state != mDrawerState) {
2641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mDrawerState = state;
265b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
2661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (mListener != null) {
2671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mListener.onDrawerStateChanged(state);
2681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
2691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
2701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
2711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void dispatchOnDrawerClosed(View drawerView) {
2731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
2741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (lp.knownOpen) {
2751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            lp.knownOpen = false;
2761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (mListener != null) {
2771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mListener.onDrawerClosed(drawerView);
2781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
2791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
2801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
2811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void dispatchOnDrawerOpened(View drawerView) {
2831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
2841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (!lp.knownOpen) {
2851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            lp.knownOpen = true;
2861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (mListener != null) {
2871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mListener.onDrawerOpened(drawerView);
2881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
2891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
2901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
2911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void dispatchOnDrawerSlide(View drawerView, float slideOffset) {
2931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (mListener != null) {
2941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mListener.onDrawerSlide(drawerView, slideOffset);
2951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
2961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
2971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
2981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void setDrawerViewOffset(View drawerView, float slideOffset) {
2991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
300b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (slideOffset == lp.onScreen) {
3011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return;
3021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
3031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
304b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        lp.onScreen = slideOffset;
3051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        dispatchOnDrawerSlide(drawerView, slideOffset);
3061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
3071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    float getDrawerViewOffset(View drawerView) {
309b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        return ((LayoutParams) drawerView.getLayoutParams()).onScreen;
3101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
3111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    int getDrawerViewGravity(View drawerView) {
3131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int gravity = ((LayoutParams) drawerView.getLayoutParams()).gravity;
3141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return GravityCompat.getAbsoluteGravity(gravity, ViewCompat.getLayoutDirection(drawerView));
3151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
3161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    boolean checkDrawerViewGravity(View drawerView, int checkFor) {
3181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int absGrav = getDrawerViewGravity(drawerView);
3191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return (absGrav & checkFor) == checkFor;
3201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
3211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void moveDrawerToOffset(View drawerView, float slideOffset) {
3231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final float oldOffset = getDrawerViewOffset(drawerView);
3241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int width = drawerView.getWidth();
3251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int oldPos = (int) (width * oldOffset);
3261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int newPos = (int) (width * slideOffset);
3271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int dx = newPos - oldPos;
3281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        drawerView.offsetLeftAndRight(checkDrawerViewGravity(drawerView, Gravity.LEFT) ? dx : -dx);
3301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        setDrawerViewOffset(drawerView, slideOffset);
3311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
3321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    View findDrawerWithGravity(int gravity) {
3341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
3351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
3361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
3371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childGravity = getDrawerViewGravity(child);
3381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if ((childGravity & Gravity.HORIZONTAL_GRAVITY_MASK) ==
3391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    (gravity & Gravity.HORIZONTAL_GRAVITY_MASK)) {
3401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                return child;
3411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
3421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
3431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return null;
3441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
3451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
3471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Simple gravity to string - only supports LEFT and RIGHT for debugging output.
3481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
3491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param gravity Absolute gravity value
3501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @return LEFT or RIGHT as appropriate, or a hex string
3511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
3521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    static String gravityToString(int gravity) {
3531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if ((gravity & Gravity.LEFT) == Gravity.LEFT) {
3541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return "LEFT";
3551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
3561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) {
3571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return "RIGHT";
3581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
3591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return Integer.toHexString(gravity);
3601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
3611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
36357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected void onDetachedFromWindow() {
36457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        super.onDetachedFromWindow();
36557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        mFirstLayout = true;
36657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
36757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
36857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
36957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected void onAttachedToWindow() {
37057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        super.onAttachedToWindow();
37157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        mFirstLayout = true;
37257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
37357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
37457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
3751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
3761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
3771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
3781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
3791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
3801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) {
3821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            throw new IllegalArgumentException(
3831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    "DrawerLayout must be measured with MeasureSpec.EXACTLY.");
3841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
3851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        setMeasuredDimension(widthSize, heightSize);
3871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        // Gravity value for each drawer we've seen. Only one of each permitted.
3891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        int foundDrawers = 0;
3901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
3911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
3921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
3931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (child.getVisibility() == GONE) {
3951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                continue;
3961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
3971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
3981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (isContentView(child)) {
3991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                // Content views get measured at exactly the layout's size.
4001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                child.measure(widthMeasureSpec, heightMeasureSpec);
4011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else if (isDrawerView(child)) {
4021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int childGravity =
4031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        getDrawerViewGravity(child) & Gravity.HORIZONTAL_GRAVITY_MASK;
4041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                if ((foundDrawers & childGravity) != 0) {
4051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    throw new IllegalStateException("Child drawer has absolute gravity " +
4061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                            gravityToString(childGravity) + " but this " + TAG + " already has a " +
4071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                            "drawer view along that edge");
4081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
4091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int drawerWidthSpec = getChildMeasureSpec(widthMeasureSpec, mMinDrawerMargin,
4101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        child.getLayoutParams().width);
4111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                child.measure(drawerWidthSpec, heightMeasureSpec);
4121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
4131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                throw new IllegalStateException("Child " + child + " at index " + i +
4141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        " does not have a valid layout_gravity - must be Gravity.LEFT, " +
4151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        "Gravity.RIGHT or Gravity.NO_GRAVITY");
4161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
4171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
4181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
4191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
4211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected void onLayout(boolean changed, int l, int t, int r, int b) {
422b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        mInLayout = true;
4231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
4241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
4251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
4261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (child.getVisibility() == GONE) {
4281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                continue;
4291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
4301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (isContentView(child)) {
4321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
4331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else { // Drawer, if it wasn't onMeasure would have thrown an exception.
4341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
4351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int childWidth = child.getMeasuredWidth();
4371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                int childLeft;
4381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                if (checkDrawerViewGravity(child, Gravity.LEFT)) {
440b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    childLeft = -childWidth + (int) (childWidth * lp.onScreen);
4411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                } else { // Right; onMeasure checked for us.
442b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    childLeft = r - l - (int) (childWidth * lp.onScreen);
4431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
4441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight());
446b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
447b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                if (lp.onScreen == 0) {
448b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    child.setVisibility(INVISIBLE);
449b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                }
4501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
4511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
452b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        mInLayout = false;
45357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        mFirstLayout = false;
454b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
455b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
456b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    @Override
457b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public void requestLayout() {
458b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (!mInLayout) {
459b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            super.requestLayout();
460b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
4611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
4621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
4641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void computeScroll() {
4651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
4661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        float scrimOpacity = 0;
4671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
468b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final float onscreen = ((LayoutParams) getChildAt(i).getLayoutParams()).onScreen;
4691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            scrimOpacity = Math.max(scrimOpacity, onscreen);
4701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
4711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mScrimOpacity = scrimOpacity;
4721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
4731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        // "|" used on purpose; both need to run.
4741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (mLeftDragger.continueSettling(true) | mRightDragger.continueSettling(true)) {
4751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            ViewCompat.postInvalidateOnAnimation(this);
4761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
4771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
4781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
479b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    private static boolean hasOpaqueBackground(View v) {
480b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        final Drawable bg = v.getBackground();
481b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (bg != null) {
482b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            return bg.getOpacity() == PixelFormat.OPAQUE;
483b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
484b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        return false;
485b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
486b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
4871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
4881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
489b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        final boolean drawingContent = isContentView(child);
490b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        int clipLeft = 0, clipRight = getWidth();
491b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
4921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int restoreCount = canvas.save();
493b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (drawingContent) {
494b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int childCount = getChildCount();
495b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            for (int i = 0; i < childCount; i++) {
496b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                final View v = getChildAt(i);
497b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                if (v == child || v.getVisibility() != VISIBLE ||
498b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                        !hasOpaqueBackground(v) || !isDrawerView(v)) {
499b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    continue;
500b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                }
501b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
502b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                if (checkDrawerViewGravity(v, Gravity.LEFT)) {
503b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    final int vright = v.getRight();
504b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    if (vright > clipLeft) clipLeft = vright;
505b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                } else {
506b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    final int vleft = v.getLeft();
507b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    if (vleft < clipRight) clipRight = vleft;
508b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                }
509b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            }
510b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            canvas.clipRect(clipLeft, 0, clipRight, getHeight());
511b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
5121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final boolean result = super.drawChild(canvas, child, drawingTime);
5131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        canvas.restoreToCount(restoreCount);
514b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
515b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (mScrimOpacity > 0 && drawingContent) {
5161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int baseAlpha = (mScrimColor & 0xff000000) >>> 24;
5171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int imag = (int) (baseAlpha * mScrimOpacity);
5181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int color = imag << 24 | (mScrimColor & 0xffffff);
5191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mScrimPaint.setColor(color);
5201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
521b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            canvas.drawRect(clipLeft, 0, clipRight, getHeight(), mScrimPaint);
522b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        } else if (mShadowLeft != null && checkDrawerViewGravity(child, Gravity.LEFT)) {
523b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int shadowWidth = mShadowLeft.getIntrinsicWidth();
524b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int childRight = child.getRight();
525b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final float alpha =
526b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    Math.max(0, Math.min((float) childRight / mDrawerPeekDistance, 1.f));
527b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowLeft.setBounds(childRight, child.getTop(),
528b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    childRight + shadowWidth, child.getBottom());
529b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowLeft.setAlpha((int) (0xff * alpha));
530b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowLeft.draw(canvas);
531b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        } else if (mShadowRight != null && checkDrawerViewGravity(child, Gravity.RIGHT)) {
532b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int shadowWidth = mShadowRight.getIntrinsicWidth();
533b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int childLeft = child.getLeft();
534b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final int showing = getWidth() - childLeft;
535b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final float alpha =
536b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    Math.max(0, Math.min((float) showing / mDrawerPeekDistance, 1.f));
537b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowRight.setBounds(childLeft - shadowWidth, child.getTop(),
538b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    childLeft, child.getBottom());
539b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowRight.setAlpha((int) (0xff * alpha));
540b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            mShadowRight.draw(canvas);
5411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
5421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return result;
5431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
5441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    boolean isContentView(View child) {
5461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return ((LayoutParams) child.getLayoutParams()).gravity == Gravity.NO_GRAVITY;
5471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
5481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    boolean isDrawerView(View child) {
5501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int gravity = ((LayoutParams) child.getLayoutParams()).gravity;
5511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int absGravity = GravityCompat.getAbsoluteGravity(gravity,
5521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                ViewCompat.getLayoutDirection(child));
5531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return (absGravity & (Gravity.LEFT | Gravity.RIGHT)) != 0;
5541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
5551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
5571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public boolean onInterceptTouchEvent(MotionEvent ev) {
5581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int action = MotionEventCompat.getActionMasked(ev);
5591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        // "|" used deliberately here; both methods should be invoked.
5611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final boolean interceptForDrag = mLeftDragger.shouldInterceptTouchEvent(ev) |
5621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mRightDragger.shouldInterceptTouchEvent(ev);
5631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean interceptForTap = false;
5651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        switch (action) {
5671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_DOWN: {
5681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float x = ev.getX();
5691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float y = ev.getY();
5701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionX = x;
5711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionY = y;
5721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                if (mScrimOpacity > 0 &&
5731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        isContentView(mLeftDragger.findTopChildUnder((int) x, (int) y))) {
5741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    interceptForTap = true;
5751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
5761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
5771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
5781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_CANCEL:
5801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_UP: {
5811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawers(true);
5821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
5831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
5841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return interceptForDrag || interceptForTap;
5851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
5861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
5871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
5881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
58932a53a670d1f6ff07454135a22e970f2154260dcAdam Powell        final int childCount = getChildCount();
59032a53a670d1f6ff07454135a22e970f2154260dcAdam Powell        for (int i = 0; i < childCount; i++) {
59132a53a670d1f6ff07454135a22e970f2154260dcAdam Powell            final LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams();
59232a53a670d1f6ff07454135a22e970f2154260dcAdam Powell
59332a53a670d1f6ff07454135a22e970f2154260dcAdam Powell            if (lp.isPeeking) {
59432a53a670d1f6ff07454135a22e970f2154260dcAdam Powell                // Don't disallow intercept at all if we have a peeking view, we're probably
59532a53a670d1f6ff07454135a22e970f2154260dcAdam Powell                // going to intercept it later anyway.
59632a53a670d1f6ff07454135a22e970f2154260dcAdam Powell                return;
59732a53a670d1f6ff07454135a22e970f2154260dcAdam Powell            }
59832a53a670d1f6ff07454135a22e970f2154260dcAdam Powell        }
5991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        super.requestDisallowInterceptTouchEvent(disallowIntercept);
6001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (disallowIntercept) {
6011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            closeDrawers(true);
6021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
6031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
6041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
6061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public boolean onTouchEvent(MotionEvent ev) {
6071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mLeftDragger.processTouchEvent(ev);
6081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mRightDragger.processTouchEvent(ev);
6091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int action = ev.getAction();
6111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean wantTouchEvents = true;
6121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        switch (action & MotionEventCompat.ACTION_MASK) {
6141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_DOWN: {
6151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float x = ev.getX();
6161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float y = ev.getY();
6171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionX = x;
6181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mInitialMotionY = y;
6191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
6201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
6211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_UP: {
6231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float x = ev.getX();
6241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final float y = ev.getY();
6251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                boolean peekingOnly = true;
6268bc268e9c40e4ae375a0d65dc1293dccc541186fAdam Powell                final View touchedView = mLeftDragger.findTopChildUnder((int) x, (int) y);
6278bc268e9c40e4ae375a0d65dc1293dccc541186fAdam Powell                if (touchedView != null && isContentView(touchedView)) {
6281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    final float dx = x - mInitialMotionX;
6291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    final float dy = y - mInitialMotionY;
6301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    final int slop = mLeftDragger.getTouchSlop();
6311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    if (dx * dx + dy * dy < slop * slop) {
6321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        // Taps close a dimmed open pane.
6331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        peekingOnly = false;
6341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    }
6351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                }
6361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawers(peekingOnly);
6371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
6381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
6391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            case MotionEvent.ACTION_CANCEL: {
6411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawers(true);
6421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                break;
6431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
6441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
6451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return wantTouchEvents;
6471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
6481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
6501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Close all currently open drawer views by animating them out of view.
6511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
6521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void closeDrawers() {
6531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        closeDrawers(false);
6541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
6551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    void closeDrawers(boolean peekingOnly) {
6571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean needsInvalidate = false;
6581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int childCount = getChildCount();
6591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        for (int i = 0; i < childCount; i++) {
6601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View child = getChildAt(i);
6611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
6621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (!isDrawerView(child) || (peekingOnly && !lp.isPeeking)) {
6641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                continue;
6651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
6661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childWidth = child.getWidth();
6681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (checkDrawerViewGravity(child, Gravity.LEFT)) {
6701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                needsInvalidate |= mLeftDragger.smoothSlideViewTo(child,
6711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        -childWidth, child.getTop());
6721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
6731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                needsInvalidate |= mRightDragger.smoothSlideViewTo(child,
6741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        getWidth(), child.getTop());
6751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
6761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            lp.isPeeking = false;
6781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
6791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (needsInvalidate) {
6811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            invalidate();
6821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
6831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
6841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
6851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
6861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Open the specified drawer view by animating it into view.
6871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
6881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param drawerView Drawer view to open
6891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
6901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void openDrawer(View drawerView) {
6911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (!isDrawerView(drawerView)) {
6921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            throw new IllegalArgumentException("View " + drawerView + " is not a sliding drawer");
6931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
6941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
69557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        if (mFirstLayout) {
69657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
69757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            lp.onScreen = 1.f;
69857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            lp.knownOpen = true;
6991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        } else {
70057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            if (checkDrawerViewGravity(drawerView, Gravity.LEFT)) {
70157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mLeftDragger.smoothSlideViewTo(drawerView, 0, drawerView.getTop());
70257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            } else {
70357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mRightDragger.smoothSlideViewTo(drawerView, getWidth() - drawerView.getWidth(),
70457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                        drawerView.getTop());
70557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
7061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
7071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        invalidate();
7081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
7091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
7111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Open the specified drawer by animating it out of view.
7121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
7131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param gravity Gravity.LEFT to move the left drawer or Gravity.RIGHT for the right.
7141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *                GravityCompat.START or GravityCompat.END may also be used.
7151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
7161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void openDrawer(int gravity) {
7171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int absGravity = GravityCompat.getAbsoluteGravity(gravity,
7181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                ViewCompat.getLayoutDirection(this));
7191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final View drawerView = findDrawerWithGravity(absGravity);
7201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (drawerView == null) {
7221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            throw new IllegalArgumentException("No drawer view found with absolute gravity " +
7231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    gravityToString(absGravity));
7241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
7251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        openDrawer(drawerView);
7261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
7271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
7291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Close the specified drawer view by animating it into view.
7301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
7311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param drawerView Drawer view to close
7321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
7331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void closeDrawer(View drawerView) {
7341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (!isDrawerView(drawerView)) {
7351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            throw new IllegalArgumentException("View " + drawerView + " is not a sliding drawer");
7361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
7371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
73857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        if (mFirstLayout) {
73957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
74057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            lp.onScreen = 0.f;
74157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            lp.knownOpen = false;
7421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        } else {
74357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            if (checkDrawerViewGravity(drawerView, Gravity.LEFT)) {
74457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mLeftDragger.smoothSlideViewTo(drawerView, -drawerView.getWidth(),
74557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                        drawerView.getTop());
74657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            } else {
74757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                mRightDragger.smoothSlideViewTo(drawerView, getWidth(), drawerView.getTop());
74857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
7491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
7501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        invalidate();
7511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
7521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    /**
7541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * Close the specified drawer by animating it out of view.
7551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *
7561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     * @param gravity Gravity.LEFT to move the left drawer or Gravity.RIGHT for the right.
7571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     *                GravityCompat.START or GravityCompat.END may also be used.
7581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell     */
7591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public void closeDrawer(int gravity) {
7601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final int absGravity = GravityCompat.getAbsoluteGravity(gravity,
7611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                ViewCompat.getLayoutDirection(this));
7621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        final View drawerView = findDrawerWithGravity(absGravity);
7631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
7641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        if (drawerView == null) {
7651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            throw new IllegalArgumentException("No drawer view found with absolute gravity " +
7661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    gravityToString(absGravity));
7671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
7681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        closeDrawer(drawerView);
7691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
7701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
771b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
772b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Check if the given drawer view is currently in an open state.
773b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * To be considered "open" the drawer must have settled into its fully
774b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * visible state. To check for partial visibility use
775b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * {@link #isDrawerVisible(android.view.View)}.
776b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
777b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param drawer Drawer view to check
778b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @return true if the given drawer view is in an open state
779b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @see #isDrawerVisible(android.view.View)
780b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
781b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public boolean isDrawerOpen(View drawer) {
782b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (!isDrawerView(drawer)) {
783b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            throw new IllegalArgumentException("View " + drawer + " is not a drawer");
784b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
785b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        return ((LayoutParams) drawer.getLayoutParams()).knownOpen;
786b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
787b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
788b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    /**
789b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * Check if a given drawer view is currently visible on-screen. The drawer
790b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * may be only peeking onto the screen, fully extended, or anywhere inbetween.
791b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     *
792b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @param drawer Drawer view to check
793b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @return true if the given drawer is visible on-screen
794b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     * @see #isDrawerOpen(android.view.View)
795b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell     */
796b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    public boolean isDrawerVisible(View drawer) {
797b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        if (!isDrawerView(drawer)) {
798b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            throw new IllegalArgumentException("View " + drawer + " is not a drawer");
799b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        }
800b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        return ((LayoutParams) drawer.getLayoutParams()).onScreen > 0;
801b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell    }
802b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell
8031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
8041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
8051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
8061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
8071d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8081d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
8091d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
8101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return p instanceof LayoutParams
8111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                ? new LayoutParams((LayoutParams) p)
8121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                : new LayoutParams(p);
8131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
8141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
8161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
8171d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return p instanceof LayoutParams && super.checkLayoutParams(p);
8181d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
8191d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
8201d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
8211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
8221d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return new LayoutParams(getContext(), attrs);
8231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
8241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
825791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    private boolean hasVisibleDrawer() {
826791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        final int childCount = getChildCount();
827791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        for (int i = 0; i < childCount; i++) {
828791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            final View child = getChildAt(i);
829791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            if (isDrawerView(child) && isDrawerVisible(child)) {
830791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell                return true;
831791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            }
832791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        }
833791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        return false;
834791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    }
835791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
836791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    @Override
837791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    public boolean onKeyDown(int keyCode, KeyEvent event) {
838791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        if (keyCode == KeyEvent.KEYCODE_BACK && hasVisibleDrawer()) {
839791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            KeyEventCompat.startTracking(event);
840791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            return true;
841791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        }
842791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        return super.onKeyDown(keyCode, event);
843791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    }
844791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
845791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    @Override
846791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    public boolean onKeyUp(int keyCode, KeyEvent event) {
847791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        if (keyCode == KeyEvent.KEYCODE_BACK && hasVisibleDrawer()) {
848791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            closeDrawers();
849791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell            return true;
850791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        }
851791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell        return super.onKeyUp(keyCode, event);
852791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell    }
853791f31bbba40b8b51694a1b2cdc804f360786ed1Adam Powell
85457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
85557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected void onRestoreInstanceState(Parcelable state) {
85657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        final SavedState ss = (SavedState) state;
85757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        super.onRestoreInstanceState(ss.getSuperState());
85857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
85957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        if (ss.openDrawerGravity != Gravity.NO_GRAVITY) {
86057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            final View toOpen = findDrawerWithGravity(ss.openDrawerGravity);
86157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            if (toOpen != null) {
86257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                openDrawer(toOpen);
86357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
86457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
86557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
86657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
86757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    @Override
86857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected Parcelable onSaveInstanceState() {
86957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        final Parcelable superState = super.onSaveInstanceState();
87057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
87157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        final SavedState ss = new SavedState(superState);
87257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
87357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        final int childCount = getChildCount();
87457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        for (int i = 0; i < childCount; i++) {
87557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            final View child = getChildAt(i);
87657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            if (!isDrawerView(child)) {
87757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                continue;
87857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
87957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
88057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
88157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            if (lp.knownOpen) {
88257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                ss.openDrawerGravity = lp.gravity;
88357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                // Only one drawer can be open at a time.
88457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                break;
88557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
88657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
88757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
88857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        return ss;
88957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
89057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
89157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    /**
89257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell     * State persisted across instances
89357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell     */
89457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    protected static class SavedState extends BaseSavedState {
89557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        int openDrawerGravity = Gravity.NO_GRAVITY;
89657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
89757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        public SavedState(Parcel in) {
89857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            super(in);
89957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            openDrawerGravity = in.readInt();
90057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
90157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
90257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        public SavedState(Parcelable superState) {
90357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            super(superState);
90457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
90557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
90657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        @Override
90757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        public void writeToParcel(Parcel dest, int flags) {
90857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            super.writeToParcel(dest, flags);
90957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            dest.writeInt(openDrawerGravity);
91057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        }
91157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
91257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        public static final Parcelable.Creator<SavedState> CREATOR =
91357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                new Parcelable.Creator<SavedState>() {
91457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            @Override
91557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            public SavedState createFromParcel(Parcel source) {
91657902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                return new SavedState(source);
91757902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
91857902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
91957902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            @Override
92057902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            public SavedState[] newArray(int size) {
92157902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell                return new SavedState[size];
92257902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell            }
92357902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell        };
92457902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell    }
92557902cff6c54c245feea589b06d12dba8f1a2a24Adam Powell
9261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    private class ViewDragCallback extends ViewDragHelper.Callback {
9271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        private final int mGravity;
9291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        private ViewDragHelper mDragger;
9301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public ViewDragCallback(int gravity) {
9321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mGravity = gravity;
9331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void setDragger(ViewDragHelper dragger) {
9361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mDragger = dragger;
9371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
9401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public boolean tryCaptureView(View child, int pointerId) {
9411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // Only capture views where the gravity matches what we're looking for.
9421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // This lets us use two ViewDragHelpers, one for each side drawer.
9431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return isDrawerView(child) && checkDrawerViewGravity(child, mGravity);
9441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
9471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewDragStateChanged(int state) {
948b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            updateDrawerState(mGravity, state, mDragger.getCapturedView());
9491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
9521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
9531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            float offset;
9541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childWidth = changedView.getWidth();
9551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // This reverses the positioning shown in onLayout.
9571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (checkDrawerViewGravity(changedView, Gravity.LEFT)) {
9581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                offset = (float) (childWidth + left) / childWidth;
9591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
9601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int width = getWidth();
9611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                offset = (float) (width - left) / childWidth;
9621d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
9631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            setDrawerViewOffset(changedView, offset);
964b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            changedView.setVisibility(offset == 0 ? INVISIBLE : VISIBLE);
9651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            invalidate();
9661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
9691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewCaptured(View capturedChild, int activePointerId) {
9701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final LayoutParams lp = (LayoutParams) capturedChild.getLayoutParams();
9711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            lp.isPeeking = false;
9721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            closeOtherDrawer();
9741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        private void closeOtherDrawer() {
9771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int otherGrav = mGravity == Gravity.LEFT ? Gravity.RIGHT : Gravity.LEFT;
9781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View toClose = findDrawerWithGravity(otherGrav);
9791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (toClose != null) {
9801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeDrawer(toClose);
9811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
9821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
9831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
9851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewReleased(View releasedChild, float xvel, float yvel) {
9861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // Offset is how open the drawer is, therefore left/right values
9871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            // are reversed from one another.
9881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final float offset = getDrawerViewOffset(releasedChild);
9891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childWidth = releasedChild.getWidth();
9901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            int left;
9921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (checkDrawerViewGravity(releasedChild, Gravity.LEFT)) {
9931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                left = xvel > 0 || xvel == 0 && offset > 0.5f ? 0 : -childWidth;
9941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
9951d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int width = getWidth();
9961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                left = xvel < 0 || xvel == 0 && offset < 0.5f ? width - childWidth : width;
9971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
9981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
9991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            mDragger.settleCapturedViewAt(left, releasedChild.getTop());
10001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            invalidate();
10011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
10021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
10041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onEdgeTouched(int edgeFlags, int pointerId) {
10051d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View toCapture;
10061d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int childLeft;
1007b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            final boolean leftEdge =
1008b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    (edgeFlags & ViewDragHelper.EDGE_LEFT) == ViewDragHelper.EDGE_LEFT;
1009b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            if (leftEdge) {
10101d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.LEFT);
10111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                childLeft = -toCapture.getWidth() + mDrawerPeekDistance;
10121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
10131d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.RIGHT);
10141d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                childLeft = getWidth() - mDrawerPeekDistance;
10151d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
10161d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1017b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            // Only peek if it would mean making the drawer more visible
1018b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell            if (toCapture != null && ((leftEdge && toCapture.getLeft() < childLeft) ||
1019b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                    (!leftEdge && toCapture.getLeft() > childLeft))) {
1020b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                final LayoutParams lp = (LayoutParams) toCapture.getLayoutParams();
10211d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mDragger.smoothSlideViewTo(toCapture, childLeft, toCapture.getTop());
1022b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell                lp.isPeeking = true;
10231d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                invalidate();
10241d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10251d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                closeOtherDrawer();
10261d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
10271d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
10281d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10291d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
10301d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onEdgeDragStarted(int edgeFlags, int pointerId) {
10311d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final View toCapture;
10321d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if ((edgeFlags & ViewDragHelper.EDGE_LEFT) == ViewDragHelper.EDGE_LEFT) {
10331d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.LEFT);
10341d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
10351d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                toCapture = findDrawerWithGravity(Gravity.RIGHT);
10361d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
10371d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10381d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (toCapture != null) {
10391d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                mDragger.captureChildView(toCapture, pointerId);
10401d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
10411d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
10421d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10431d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
10441d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public int getViewHorizontalDragRange(View child) {
10451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return child.getWidth();
10461d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
10471d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10481d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        @Override
10491d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public int clampViewPositionHorizontal(View child, int left, int dx) {
10501d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            if (checkDrawerViewGravity(child, Gravity.LEFT)) {
10511d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                return Math.max(-child.getWidth(), Math.min(left, 0));
10521d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            } else {
10531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                final int width = getWidth();
10541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                return Math.max(width - child.getWidth(), Math.min(left, width));
10551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            }
10561d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
10571d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
10581d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10591d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    public static class LayoutParams extends ViewGroup.LayoutParams {
10601d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10611d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public int gravity = Gravity.NO_GRAVITY;
1062b562d856f6ff58b7fc421a3b0cd1e0e089b994abAdam Powell        float onScreen;
10631d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean isPeeking;
10641d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        boolean knownOpen;
10651d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10661d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(Context c, AttributeSet attrs) {
10671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(c, attrs);
10681d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10691d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final TypedArray a = c.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
10701d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this.gravity = a.getInt(0, Gravity.NO_GRAVITY);
10711d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            a.recycle();
10721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
10731d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(int width, int height) {
10751d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(width, height);
10761d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
10771d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10781d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(int width, int height, int gravity) {
10791d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this(width, height);
10801d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this.gravity = gravity;
10811d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
10821d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10831d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(LayoutParams source) {
10841d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(source);
10851d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            this.gravity = source.gravity;
10861d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
10871d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10881d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public LayoutParams(ViewGroup.LayoutParams source) {
10891d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            super(source);
10901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        }
10911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
10921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell}
1093