SlidingPaneLayout.java revision c89f53833f1e272d32f7928837f0704fa33be309
197341bdc5bea1d7bf777de65228039142d249f38Adam Powell/*
297341bdc5bea1d7bf777de65228039142d249f38Adam Powell * Copyright (C) 2012 The Android Open Source Project
397341bdc5bea1d7bf777de65228039142d249f38Adam Powell *
497341bdc5bea1d7bf777de65228039142d249f38Adam Powell * Licensed under the Apache License, Version 2.0 (the "License");
597341bdc5bea1d7bf777de65228039142d249f38Adam Powell * you may not use this file except in compliance with the License.
697341bdc5bea1d7bf777de65228039142d249f38Adam Powell * You may obtain a copy of the License at
797341bdc5bea1d7bf777de65228039142d249f38Adam Powell *
897341bdc5bea1d7bf777de65228039142d249f38Adam Powell *      http://www.apache.org/licenses/LICENSE-2.0
997341bdc5bea1d7bf777de65228039142d249f38Adam Powell *
1097341bdc5bea1d7bf777de65228039142d249f38Adam Powell * Unless required by applicable law or agreed to in writing, software
1197341bdc5bea1d7bf777de65228039142d249f38Adam Powell * distributed under the License is distributed on an "AS IS" BASIS,
1297341bdc5bea1d7bf777de65228039142d249f38Adam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1397341bdc5bea1d7bf777de65228039142d249f38Adam Powell * See the License for the specific language governing permissions and
1497341bdc5bea1d7bf777de65228039142d249f38Adam Powell * limitations under the License.
1597341bdc5bea1d7bf777de65228039142d249f38Adam Powell */
1697341bdc5bea1d7bf777de65228039142d249f38Adam Powell
1797341bdc5bea1d7bf777de65228039142d249f38Adam Powellpackage android.support.v4.widget;
1897341bdc5bea1d7bf777de65228039142d249f38Adam Powell
1997341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport android.content.Context;
2097341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport android.content.res.TypedArray;
2197341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport android.graphics.Bitmap;
2297341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport android.graphics.Canvas;
2397341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport android.graphics.Paint;
24c89f53833f1e272d32f7928837f0704fa33be309Adam Powellimport android.graphics.PixelFormat;
2597341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport android.graphics.PorterDuff;
2697341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport android.graphics.PorterDuffColorFilter;
271e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powellimport android.graphics.Rect;
28ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powellimport android.graphics.drawable.Drawable;
2997341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport android.os.Build;
3097341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport android.os.Parcel;
3197341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport android.os.Parcelable;
32c89f53833f1e272d32f7928837f0704fa33be309Adam Powellimport android.support.v4.view.AccessibilityDelegateCompat;
3397341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport android.support.v4.view.MotionEventCompat;
3497341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport android.support.v4.view.ViewCompat;
35c89f53833f1e272d32f7928837f0704fa33be309Adam Powellimport android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
3697341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport android.util.AttributeSet;
3797341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport android.util.Log;
3897341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport android.view.MotionEvent;
3997341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport android.view.View;
4097341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport android.view.ViewConfiguration;
4197341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport android.view.ViewGroup;
42c89f53833f1e272d32f7928837f0704fa33be309Adam Powellimport android.view.accessibility.AccessibilityEvent;
4397341bdc5bea1d7bf777de65228039142d249f38Adam Powell
4497341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport java.lang.reflect.Field;
4597341bdc5bea1d7bf777de65228039142d249f38Adam Powellimport java.lang.reflect.Method;
4697341bdc5bea1d7bf777de65228039142d249f38Adam Powell
4797341bdc5bea1d7bf777de65228039142d249f38Adam Powell/**
4897341bdc5bea1d7bf777de65228039142d249f38Adam Powell * SlidingPaneLayout provides a horizontal, multi-pane layout for use at the top level
49ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell * of a UI. A left (or first) pane is treated as a content list or browser, subordinate to a
5097341bdc5bea1d7bf777de65228039142d249f38Adam Powell * primary detail view for displaying content.
5197341bdc5bea1d7bf777de65228039142d249f38Adam Powell *
5297341bdc5bea1d7bf777de65228039142d249f38Adam Powell * <p>Child views may overlap if their combined width exceeds the available width
5397341bdc5bea1d7bf777de65228039142d249f38Adam Powell * in the SlidingPaneLayout. When this occurs the user may slide the topmost view out of the way
5497341bdc5bea1d7bf777de65228039142d249f38Adam Powell * by dragging it, or by navigating in the direction of the overlapped view using a keyboard.
5597341bdc5bea1d7bf777de65228039142d249f38Adam Powell * If the content of the dragged child view is itself horizontally scrollable, the user may
5697341bdc5bea1d7bf777de65228039142d249f38Adam Powell * grab it by the very edge.</p>
5797341bdc5bea1d7bf777de65228039142d249f38Adam Powell *
5897341bdc5bea1d7bf777de65228039142d249f38Adam Powell * <p>Thanks to this sliding behavior, SlidingPaneLayout may be suitable for creating layouts
5997341bdc5bea1d7bf777de65228039142d249f38Adam Powell * that can smoothly adapt across many different screen sizes, expanding out fully on larger
6097341bdc5bea1d7bf777de65228039142d249f38Adam Powell * screens and collapsing on smaller screens.</p>
6197341bdc5bea1d7bf777de65228039142d249f38Adam Powell *
62ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell * <p>SlidingPaneLayout is distinct from a navigation drawer as described in the design
63ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell * guide and should not be used in the same scenarios. SlidingPaneLayout should be thought
64ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell * of only as a way to allow a two-pane layout normally used on larger screens to adapt to smaller
65ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell * screens in a natural way. The interaction patterns expressed by SlidingPaneLayout imply
66ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell * a physicality and direct information hierarchy between panes that does not necessarily exist
67ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell * in a scenario where a navigation drawer should be used instead.</p>
68ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell *
69ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell * <p>Appropriate uses of SlidingPaneLayout include pairings of panes such as a contact list and
70ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell * subordinate interactions with those contacts, or an email thread list with the content pane
71ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell * displaying the contents of the selected thread. Inappropriate uses of SlidingPaneLayout include
72ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell * switching between disparate functions of your app, such as jumping from a social stream view
73ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell * to a view of your personal profile - cases such as this should use the navigation drawer
741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell * pattern instead. ({@link DrawerLayout DrawerLayout} implements this pattern.)</p>
75ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell *
7697341bdc5bea1d7bf777de65228039142d249f38Adam Powell * <p>Like {@link android.widget.LinearLayout LinearLayout}, SlidingPaneLayout supports
7797341bdc5bea1d7bf777de65228039142d249f38Adam Powell * the use of the layout parameter <code>layout_weight</code> on child views to determine
7897341bdc5bea1d7bf777de65228039142d249f38Adam Powell * how to divide leftover space after measurement is complete. It is only relevant for width.
7997341bdc5bea1d7bf777de65228039142d249f38Adam Powell * When views do not overlap weight behaves as it does in a LinearLayout.</p>
8097341bdc5bea1d7bf777de65228039142d249f38Adam Powell *
8197341bdc5bea1d7bf777de65228039142d249f38Adam Powell * <p>When views do overlap, weight on a slideable pane indicates that the pane should be
8297341bdc5bea1d7bf777de65228039142d249f38Adam Powell * sized to fill all available space in the closed state. Weight on a pane that becomes covered
8397341bdc5bea1d7bf777de65228039142d249f38Adam Powell * indicates that the pane should be sized to fill all available space except a small minimum strip
8497341bdc5bea1d7bf777de65228039142d249f38Adam Powell * that the user may use to grab the slideable view and pull it back over into a closed state.</p>
85ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell *
86ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell * <p>Experimental. This class may be removed.</p>
8797341bdc5bea1d7bf777de65228039142d249f38Adam Powell */
8897341bdc5bea1d7bf777de65228039142d249f38Adam Powellpublic class SlidingPaneLayout extends ViewGroup {
8997341bdc5bea1d7bf777de65228039142d249f38Adam Powell    private static final String TAG = "SlidingPaneLayout";
9097341bdc5bea1d7bf777de65228039142d249f38Adam Powell
9197341bdc5bea1d7bf777de65228039142d249f38Adam Powell    /**
9297341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * Default size of the overhang for a pane in the open state.
9397341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * At least this much of a sliding pane will remain visible.
9497341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * This indicates that there is more content available and provides
9597341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * a "physical" edge to grab to pull it closed.
9697341bdc5bea1d7bf777de65228039142d249f38Adam Powell     */
97ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell    private static final int DEFAULT_OVERHANG_SIZE = 32; // dp;
9897341bdc5bea1d7bf777de65228039142d249f38Adam Powell
9997341bdc5bea1d7bf777de65228039142d249f38Adam Powell    /**
100ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell     * If no fade color is given by default it will fade to 80% gray.
101ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell     */
102ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell    private static final int DEFAULT_FADE_COLOR = 0xcccccccc;
103ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell
104ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell    /**
10581e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell     * The fade color used for the sliding panel. 0 = no fading.
10681e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell     */
10781e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell    private int mSliderFadeColor = DEFAULT_FADE_COLOR;
10881e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell
10981e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell    /**
11081e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell     * The fade color used for the panel covered by the slider. 0 = no fading.
11181e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell     */
11281e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell    private int mCoveredFadeColor;
11381e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell
11481e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell    /**
115ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell     * Drawable used to draw the shadow between panes.
116ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell     */
117ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell    private Drawable mShadowDrawable;
118ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell
119ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell    /**
12097341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * The size of the overhang in pixels.
12197341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * This is the minimum section of the sliding panel that will
12297341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * be visible in the open state to allow for a closing drag.
12397341bdc5bea1d7bf777de65228039142d249f38Adam Powell     */
12497341bdc5bea1d7bf777de65228039142d249f38Adam Powell    private final int mOverhangSize;
12597341bdc5bea1d7bf777de65228039142d249f38Adam Powell
12697341bdc5bea1d7bf777de65228039142d249f38Adam Powell    /**
12797341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * True if a panel can slide with the current measurements
12897341bdc5bea1d7bf777de65228039142d249f38Adam Powell     */
12997341bdc5bea1d7bf777de65228039142d249f38Adam Powell    private boolean mCanSlide;
13097341bdc5bea1d7bf777de65228039142d249f38Adam Powell
13197341bdc5bea1d7bf777de65228039142d249f38Adam Powell    /**
1320eefe9ad0819b223006533cbc79a35d66684af32Adam Powell     * The child view that can slide, if any.
13397341bdc5bea1d7bf777de65228039142d249f38Adam Powell     */
1340eefe9ad0819b223006533cbc79a35d66684af32Adam Powell    private View mSlideableView;
13597341bdc5bea1d7bf777de65228039142d249f38Adam Powell
1360eefe9ad0819b223006533cbc79a35d66684af32Adam Powell    /**
1370eefe9ad0819b223006533cbc79a35d66684af32Adam Powell     * How far the panel is offset from its closed position.
1380eefe9ad0819b223006533cbc79a35d66684af32Adam Powell     * range [0, 1] where 0 = closed, 1 = open.
1390eefe9ad0819b223006533cbc79a35d66684af32Adam Powell     */
1400eefe9ad0819b223006533cbc79a35d66684af32Adam Powell    private float mSlideOffset;
1410eefe9ad0819b223006533cbc79a35d66684af32Adam Powell
1420eefe9ad0819b223006533cbc79a35d66684af32Adam Powell    /**
1430eefe9ad0819b223006533cbc79a35d66684af32Adam Powell     * How far the non-sliding panel is parallaxed from its usual position when open.
1440eefe9ad0819b223006533cbc79a35d66684af32Adam Powell     * range [0, 1]
1450eefe9ad0819b223006533cbc79a35d66684af32Adam Powell     */
1460eefe9ad0819b223006533cbc79a35d66684af32Adam Powell    private float mParallaxOffset;
1470eefe9ad0819b223006533cbc79a35d66684af32Adam Powell
1480eefe9ad0819b223006533cbc79a35d66684af32Adam Powell    /**
1490eefe9ad0819b223006533cbc79a35d66684af32Adam Powell     * How far in pixels the slideable panel may move.
1500eefe9ad0819b223006533cbc79a35d66684af32Adam Powell     */
1510eefe9ad0819b223006533cbc79a35d66684af32Adam Powell    private int mSlideRange;
15297341bdc5bea1d7bf777de65228039142d249f38Adam Powell
15397341bdc5bea1d7bf777de65228039142d249f38Adam Powell    /**
15497341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * A panel view is locked into internal scrolling or another condition that
15597341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * is preventing a drag.
15697341bdc5bea1d7bf777de65228039142d249f38Adam Powell     */
15797341bdc5bea1d7bf777de65228039142d249f38Adam Powell    private boolean mIsUnableToDrag;
15897341bdc5bea1d7bf777de65228039142d249f38Adam Powell
1596debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell    /**
1606debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell     * Distance in pixels to parallax the fixed pane by when fully closed
1616debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell     */
1626debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell    private int mParallaxBy;
1636debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell
16497341bdc5bea1d7bf777de65228039142d249f38Adam Powell    private float mInitialMotionX;
165ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell    private float mInitialMotionY;
16697341bdc5bea1d7bf777de65228039142d249f38Adam Powell
16797341bdc5bea1d7bf777de65228039142d249f38Adam Powell    private PanelSlideListener mPanelSlideListener;
16897341bdc5bea1d7bf777de65228039142d249f38Adam Powell
169c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell    private final ViewDragHelper mDragHelper;
170c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell
17189e17886e6149bddfdb08a242c9e88889596419cAdam Powell    /**
17289e17886e6149bddfdb08a242c9e88889596419cAdam Powell     * Stores whether or not the pane was open the last time it was slideable.
17389e17886e6149bddfdb08a242c9e88889596419cAdam Powell     * If open/close operations are invoked this state is modified. Used by
17489e17886e6149bddfdb08a242c9e88889596419cAdam Powell     * instance state save/restore.
17589e17886e6149bddfdb08a242c9e88889596419cAdam Powell     */
17689e17886e6149bddfdb08a242c9e88889596419cAdam Powell    private boolean mPreservedOpenState;
17789e17886e6149bddfdb08a242c9e88889596419cAdam Powell    private boolean mFirstLayout = true;
17889e17886e6149bddfdb08a242c9e88889596419cAdam Powell
1791e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell    private final Rect mTmpRect = new Rect();
1801e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell
18197341bdc5bea1d7bf777de65228039142d249f38Adam Powell    static final SlidingPanelLayoutImpl IMPL;
18297341bdc5bea1d7bf777de65228039142d249f38Adam Powell
18397341bdc5bea1d7bf777de65228039142d249f38Adam Powell    static {
1846debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell        final int deviceVersion = Build.VERSION.SDK_INT;
1856debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell        if (deviceVersion >= 17) {
1866debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell            IMPL = new SlidingPanelLayoutImplJBMR1();
1876debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell        } else if (deviceVersion >= 16) {
18897341bdc5bea1d7bf777de65228039142d249f38Adam Powell            IMPL = new SlidingPanelLayoutImplJB();
18997341bdc5bea1d7bf777de65228039142d249f38Adam Powell        } else {
19097341bdc5bea1d7bf777de65228039142d249f38Adam Powell            IMPL = new SlidingPanelLayoutImplBase();
19197341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
19297341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
19397341bdc5bea1d7bf777de65228039142d249f38Adam Powell
19497341bdc5bea1d7bf777de65228039142d249f38Adam Powell    /**
19597341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * Listener for monitoring events about sliding panes.
19697341bdc5bea1d7bf777de65228039142d249f38Adam Powell     */
19797341bdc5bea1d7bf777de65228039142d249f38Adam Powell    public interface PanelSlideListener {
19897341bdc5bea1d7bf777de65228039142d249f38Adam Powell        /**
19997341bdc5bea1d7bf777de65228039142d249f38Adam Powell         * Called when a sliding pane's position changes.
20097341bdc5bea1d7bf777de65228039142d249f38Adam Powell         * @param panel The child view that was moved
20197341bdc5bea1d7bf777de65228039142d249f38Adam Powell         * @param slideOffset The new offset of this sliding pane within its range, from 0-1
20297341bdc5bea1d7bf777de65228039142d249f38Adam Powell         */
20397341bdc5bea1d7bf777de65228039142d249f38Adam Powell        public void onPanelSlide(View panel, float slideOffset);
20497341bdc5bea1d7bf777de65228039142d249f38Adam Powell        /**
20597341bdc5bea1d7bf777de65228039142d249f38Adam Powell         * Called when a sliding pane becomes slid completely open. The pane may or may not
20697341bdc5bea1d7bf777de65228039142d249f38Adam Powell         * be interactive at this point depending on how much of the pane is visible.
20797341bdc5bea1d7bf777de65228039142d249f38Adam Powell         * @param panel The child view that was slid to an open position, revealing other panes
20897341bdc5bea1d7bf777de65228039142d249f38Adam Powell         */
20997341bdc5bea1d7bf777de65228039142d249f38Adam Powell        public void onPanelOpened(View panel);
21097341bdc5bea1d7bf777de65228039142d249f38Adam Powell
21197341bdc5bea1d7bf777de65228039142d249f38Adam Powell        /**
21297341bdc5bea1d7bf777de65228039142d249f38Adam Powell         * Called when a sliding pane becomes slid completely closed. The pane is now guaranteed
21397341bdc5bea1d7bf777de65228039142d249f38Adam Powell         * to be interactive. It may now obscure other views in the layout.
21497341bdc5bea1d7bf777de65228039142d249f38Adam Powell         * @param panel The child view that was slid to a closed position
21597341bdc5bea1d7bf777de65228039142d249f38Adam Powell         */
21697341bdc5bea1d7bf777de65228039142d249f38Adam Powell        public void onPanelClosed(View panel);
21797341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
21897341bdc5bea1d7bf777de65228039142d249f38Adam Powell
21997341bdc5bea1d7bf777de65228039142d249f38Adam Powell    /**
22097341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * No-op stubs for {@link PanelSlideListener}. If you only want to implement a subset
22197341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * of the listener methods you can extend this instead of implement the full interface.
22297341bdc5bea1d7bf777de65228039142d249f38Adam Powell     */
22397341bdc5bea1d7bf777de65228039142d249f38Adam Powell    public static class SimplePanelSlideListener implements PanelSlideListener {
22497341bdc5bea1d7bf777de65228039142d249f38Adam Powell        @Override
22597341bdc5bea1d7bf777de65228039142d249f38Adam Powell        public void onPanelSlide(View panel, float slideOffset) {
22697341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
22797341bdc5bea1d7bf777de65228039142d249f38Adam Powell        @Override
22897341bdc5bea1d7bf777de65228039142d249f38Adam Powell        public void onPanelOpened(View panel) {
22997341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
23097341bdc5bea1d7bf777de65228039142d249f38Adam Powell        @Override
23197341bdc5bea1d7bf777de65228039142d249f38Adam Powell        public void onPanelClosed(View panel) {
23297341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
23397341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
23497341bdc5bea1d7bf777de65228039142d249f38Adam Powell
23597341bdc5bea1d7bf777de65228039142d249f38Adam Powell    public SlidingPaneLayout(Context context) {
23697341bdc5bea1d7bf777de65228039142d249f38Adam Powell        this(context, null);
23797341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
23897341bdc5bea1d7bf777de65228039142d249f38Adam Powell
23997341bdc5bea1d7bf777de65228039142d249f38Adam Powell    public SlidingPaneLayout(Context context, AttributeSet attrs) {
24097341bdc5bea1d7bf777de65228039142d249f38Adam Powell        this(context, attrs, 0);
24197341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
24297341bdc5bea1d7bf777de65228039142d249f38Adam Powell
24397341bdc5bea1d7bf777de65228039142d249f38Adam Powell    public SlidingPaneLayout(Context context, AttributeSet attrs, int defStyle) {
24497341bdc5bea1d7bf777de65228039142d249f38Adam Powell        super(context, attrs, defStyle);
24597341bdc5bea1d7bf777de65228039142d249f38Adam Powell
24697341bdc5bea1d7bf777de65228039142d249f38Adam Powell        final float density = context.getResources().getDisplayMetrics().density;
24797341bdc5bea1d7bf777de65228039142d249f38Adam Powell        mOverhangSize = (int) (DEFAULT_OVERHANG_SIZE * density + 0.5f);
24897341bdc5bea1d7bf777de65228039142d249f38Adam Powell
24997341bdc5bea1d7bf777de65228039142d249f38Adam Powell        final ViewConfiguration viewConfig = ViewConfiguration.get(context);
250ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell
251ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell        setWillNotDraw(false);
252c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell
253c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        ViewCompat.setAccessibilityDelegate(this, new AccessibilityDelegate());
254c89f53833f1e272d32f7928837f0704fa33be309Adam Powell
2551d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        mDragHelper = ViewDragHelper.create(this, 0.5f, new DragHelperCallback());
256c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
25797341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
25897341bdc5bea1d7bf777de65228039142d249f38Adam Powell
2596debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell    /**
2606debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell     * Set a distance to parallax the lower pane by when the upper pane is in its
2616debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell     * fully closed state. The lower pane will scroll between this position and
2626debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell     * its fully open state.
2636debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell     *
2646debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell     * @param parallaxBy Distance to parallax by in pixels
2656debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell     */
2666debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell    public void setParallaxDistance(int parallaxBy) {
2676debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell        mParallaxBy = parallaxBy;
2686debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell        requestLayout();
2696debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell    }
2706debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell
2716debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell    /**
2726debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell     * @return The distance the lower pane will parallax by when the upper pane is fully closed.
2736debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell     *
2746debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell     * @see #setParallaxDistance(int)
2756debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell     */
2766debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell    public int getParallaxDistance() {
2776debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell        return mParallaxBy;
2786debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell    }
2796debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell
28081e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell    /**
28181e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell     * Set the color used to fade the sliding pane out when it is slid most of the way offscreen.
28281e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell     *
28381e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell     * @param color An ARGB-packed color value
28481e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell     */
28581e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell    public void setSliderFadeColor(int color) {
28681e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell        mSliderFadeColor = color;
28781e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell    }
28881e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell
28981e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell    /**
29081e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell     * @return The ARGB-packed color value used to fade the sliding pane
29181e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell     */
29281e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell    public int getSliderFadeColor() {
29381e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell        return mSliderFadeColor;
29481e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell    }
29581e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell
29681e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell    /**
29781e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell     * Set the color used to fade the pane covered by the sliding pane out when the pane
29881e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell     * will become fully covered in the closed state.
29981e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell     *
30081e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell     * @param color An ARGB-packed color value
30181e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell     */
30281e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell    public void setCoveredFadeColor(int color) {
30381e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell        mCoveredFadeColor = color;
30481e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell    }
30581e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell
30681e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell    /**
30781e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell     * @return The ARGB-packed color value used to fade the fixed pane
30881e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell     */
30981e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell    public int getCoveredFadeColor() {
31081e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell        return mCoveredFadeColor;
31181e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell    }
31281e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell
31397341bdc5bea1d7bf777de65228039142d249f38Adam Powell    public void setPanelSlideListener(PanelSlideListener listener) {
31497341bdc5bea1d7bf777de65228039142d249f38Adam Powell        mPanelSlideListener = listener;
31597341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
31697341bdc5bea1d7bf777de65228039142d249f38Adam Powell
31797341bdc5bea1d7bf777de65228039142d249f38Adam Powell    void dispatchOnPanelSlide(View panel) {
31897341bdc5bea1d7bf777de65228039142d249f38Adam Powell        if (mPanelSlideListener != null) {
3190eefe9ad0819b223006533cbc79a35d66684af32Adam Powell            mPanelSlideListener.onPanelSlide(panel, mSlideOffset);
32097341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
32197341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
32297341bdc5bea1d7bf777de65228039142d249f38Adam Powell
32397341bdc5bea1d7bf777de65228039142d249f38Adam Powell    void dispatchOnPanelOpened(View panel) {
32497341bdc5bea1d7bf777de65228039142d249f38Adam Powell        if (mPanelSlideListener != null) {
32597341bdc5bea1d7bf777de65228039142d249f38Adam Powell            mPanelSlideListener.onPanelOpened(panel);
32697341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
327c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
32897341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
32997341bdc5bea1d7bf777de65228039142d249f38Adam Powell
33097341bdc5bea1d7bf777de65228039142d249f38Adam Powell    void dispatchOnPanelClosed(View panel) {
33197341bdc5bea1d7bf777de65228039142d249f38Adam Powell        if (mPanelSlideListener != null) {
33297341bdc5bea1d7bf777de65228039142d249f38Adam Powell            mPanelSlideListener.onPanelClosed(panel);
33397341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
334c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
335c89f53833f1e272d32f7928837f0704fa33be309Adam Powell    }
336c89f53833f1e272d32f7928837f0704fa33be309Adam Powell
337c89f53833f1e272d32f7928837f0704fa33be309Adam Powell    void updateObscuredViewsVisibility(View panel) {
338c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        final int left;
339c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        final int right;
340c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        final int top;
341c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        final int bottom;
342c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        if (panel != null && hasOpaqueBackground(panel)) {
343c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            left = panel.getLeft();
344c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            right = panel.getRight();
345c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            top = panel.getTop();
346c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            bottom = panel.getBottom();
347c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        } else {
348c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            left = right = top = bottom = 0;
349c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        }
350c89f53833f1e272d32f7928837f0704fa33be309Adam Powell
351c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        for (int i = 0, childCount = getChildCount(); i < childCount; i++) {
352c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            final View child = getChildAt(i);
353c89f53833f1e272d32f7928837f0704fa33be309Adam Powell
354c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            if (child == panel) {
355c89f53833f1e272d32f7928837f0704fa33be309Adam Powell                // There are still more children above the panel but they won't be affected.
356c89f53833f1e272d32f7928837f0704fa33be309Adam Powell                break;
357c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            }
358c89f53833f1e272d32f7928837f0704fa33be309Adam Powell
359c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            final int vis;
360c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            if (child.getLeft() >= left && child.getTop() >= top &&
361c89f53833f1e272d32f7928837f0704fa33be309Adam Powell                    child.getRight() <= right && child.getBottom() <= bottom) {
362c89f53833f1e272d32f7928837f0704fa33be309Adam Powell                vis = INVISIBLE;
363c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            } else {
364c89f53833f1e272d32f7928837f0704fa33be309Adam Powell                vis = VISIBLE;
365c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            }
366c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            child.setVisibility(vis);
367c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        }
368c89f53833f1e272d32f7928837f0704fa33be309Adam Powell    }
369c89f53833f1e272d32f7928837f0704fa33be309Adam Powell
370c89f53833f1e272d32f7928837f0704fa33be309Adam Powell    void setAllChildrenVisible() {
371c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        for (int i = 0, childCount = getChildCount(); i < childCount; i++) {
372c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            final View child = getChildAt(i);
373c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            if (child.getVisibility() == INVISIBLE) {
374c89f53833f1e272d32f7928837f0704fa33be309Adam Powell                child.setVisibility(VISIBLE);
375c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            }
376c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        }
377c89f53833f1e272d32f7928837f0704fa33be309Adam Powell    }
378c89f53833f1e272d32f7928837f0704fa33be309Adam Powell
379c89f53833f1e272d32f7928837f0704fa33be309Adam Powell    private static boolean hasOpaqueBackground(View v) {
380c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        final Drawable bg = v.getBackground();
381c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        if (bg != null) {
382c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            return bg.getOpacity() == PixelFormat.OPAQUE;
383c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        }
384c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        return false;
38597341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
38697341bdc5bea1d7bf777de65228039142d249f38Adam Powell
38797341bdc5bea1d7bf777de65228039142d249f38Adam Powell    @Override
38889e17886e6149bddfdb08a242c9e88889596419cAdam Powell    protected void onAttachedToWindow() {
38989e17886e6149bddfdb08a242c9e88889596419cAdam Powell        super.onAttachedToWindow();
39089e17886e6149bddfdb08a242c9e88889596419cAdam Powell        mFirstLayout = true;
39189e17886e6149bddfdb08a242c9e88889596419cAdam Powell    }
39289e17886e6149bddfdb08a242c9e88889596419cAdam Powell
39389e17886e6149bddfdb08a242c9e88889596419cAdam Powell    @Override
39489e17886e6149bddfdb08a242c9e88889596419cAdam Powell    protected void onDetachedFromWindow() {
39589e17886e6149bddfdb08a242c9e88889596419cAdam Powell        super.onDetachedFromWindow();
39689e17886e6149bddfdb08a242c9e88889596419cAdam Powell        mFirstLayout = true;
39789e17886e6149bddfdb08a242c9e88889596419cAdam Powell    }
39889e17886e6149bddfdb08a242c9e88889596419cAdam Powell
39989e17886e6149bddfdb08a242c9e88889596419cAdam Powell    @Override
40097341bdc5bea1d7bf777de65228039142d249f38Adam Powell    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
40197341bdc5bea1d7bf777de65228039142d249f38Adam Powell        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
40297341bdc5bea1d7bf777de65228039142d249f38Adam Powell        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
40397341bdc5bea1d7bf777de65228039142d249f38Adam Powell        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
40497341bdc5bea1d7bf777de65228039142d249f38Adam Powell        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
40597341bdc5bea1d7bf777de65228039142d249f38Adam Powell
40697341bdc5bea1d7bf777de65228039142d249f38Adam Powell        if (widthMode != MeasureSpec.EXACTLY) {
40797341bdc5bea1d7bf777de65228039142d249f38Adam Powell            throw new IllegalStateException("Width must have an exact value or MATCH_PARENT");
40897341bdc5bea1d7bf777de65228039142d249f38Adam Powell        } else if (heightMode == MeasureSpec.UNSPECIFIED) {
40997341bdc5bea1d7bf777de65228039142d249f38Adam Powell            throw new IllegalStateException("Height must not be UNSPECIFIED");
41097341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
41197341bdc5bea1d7bf777de65228039142d249f38Adam Powell
41297341bdc5bea1d7bf777de65228039142d249f38Adam Powell        int layoutHeight = 0;
41397341bdc5bea1d7bf777de65228039142d249f38Adam Powell        int maxLayoutHeight = -1;
41497341bdc5bea1d7bf777de65228039142d249f38Adam Powell        switch (heightMode) {
41597341bdc5bea1d7bf777de65228039142d249f38Adam Powell            case MeasureSpec.EXACTLY:
41697341bdc5bea1d7bf777de65228039142d249f38Adam Powell                layoutHeight = maxLayoutHeight = heightSize - getPaddingTop() - getPaddingBottom();
41797341bdc5bea1d7bf777de65228039142d249f38Adam Powell                break;
41897341bdc5bea1d7bf777de65228039142d249f38Adam Powell            case MeasureSpec.AT_MOST:
41997341bdc5bea1d7bf777de65228039142d249f38Adam Powell                maxLayoutHeight = heightSize - getPaddingTop() - getPaddingBottom();
42097341bdc5bea1d7bf777de65228039142d249f38Adam Powell                break;
42197341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
42297341bdc5bea1d7bf777de65228039142d249f38Adam Powell
42397341bdc5bea1d7bf777de65228039142d249f38Adam Powell        float weightSum = 0;
4240eefe9ad0819b223006533cbc79a35d66684af32Adam Powell        boolean canSlide = false;
42597341bdc5bea1d7bf777de65228039142d249f38Adam Powell        int widthRemaining = widthSize - getPaddingLeft() - getPaddingRight();
42697341bdc5bea1d7bf777de65228039142d249f38Adam Powell        final int childCount = getChildCount();
42797341bdc5bea1d7bf777de65228039142d249f38Adam Powell
42897341bdc5bea1d7bf777de65228039142d249f38Adam Powell        if (childCount > 2) {
4290eefe9ad0819b223006533cbc79a35d66684af32Adam Powell            Log.e(TAG, "onMeasure: More than two child views are not supported.");
43097341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
43197341bdc5bea1d7bf777de65228039142d249f38Adam Powell
4321e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell        // We'll find the current one below.
4331e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell        mSlideableView = null;
4341e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell
43597341bdc5bea1d7bf777de65228039142d249f38Adam Powell        // First pass. Measure based on child LayoutParams width/height.
43697341bdc5bea1d7bf777de65228039142d249f38Adam Powell        // Weight will incur a second pass.
43797341bdc5bea1d7bf777de65228039142d249f38Adam Powell        for (int i = 0; i < childCount; i++) {
43897341bdc5bea1d7bf777de65228039142d249f38Adam Powell            final View child = getChildAt(i);
43997341bdc5bea1d7bf777de65228039142d249f38Adam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
44097341bdc5bea1d7bf777de65228039142d249f38Adam Powell
4410eefe9ad0819b223006533cbc79a35d66684af32Adam Powell            if (child.getVisibility() == GONE) {
4420eefe9ad0819b223006533cbc79a35d66684af32Adam Powell                lp.dimWhenOffset = false;
4430eefe9ad0819b223006533cbc79a35d66684af32Adam Powell                continue;
44497341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
44597341bdc5bea1d7bf777de65228039142d249f38Adam Powell
44697341bdc5bea1d7bf777de65228039142d249f38Adam Powell            if (lp.weight > 0) {
44797341bdc5bea1d7bf777de65228039142d249f38Adam Powell                weightSum += lp.weight;
44897341bdc5bea1d7bf777de65228039142d249f38Adam Powell
44997341bdc5bea1d7bf777de65228039142d249f38Adam Powell                // If we have no width, weight is the only contributor to the final size.
45097341bdc5bea1d7bf777de65228039142d249f38Adam Powell                // Measure this view on the weight pass only.
45197341bdc5bea1d7bf777de65228039142d249f38Adam Powell                if (lp.width == 0) continue;
45297341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
45397341bdc5bea1d7bf777de65228039142d249f38Adam Powell
45497341bdc5bea1d7bf777de65228039142d249f38Adam Powell            int childWidthSpec;
45597341bdc5bea1d7bf777de65228039142d249f38Adam Powell            final int horizontalMargin = lp.leftMargin + lp.rightMargin;
45697341bdc5bea1d7bf777de65228039142d249f38Adam Powell            if (lp.width == LayoutParams.WRAP_CONTENT) {
45797341bdc5bea1d7bf777de65228039142d249f38Adam Powell                childWidthSpec = MeasureSpec.makeMeasureSpec(widthSize - horizontalMargin,
45897341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        MeasureSpec.AT_MOST);
45997341bdc5bea1d7bf777de65228039142d249f38Adam Powell            } else if (lp.width == LayoutParams.FILL_PARENT) {
46097341bdc5bea1d7bf777de65228039142d249f38Adam Powell                childWidthSpec = MeasureSpec.makeMeasureSpec(widthSize - horizontalMargin,
46197341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        MeasureSpec.EXACTLY);
46297341bdc5bea1d7bf777de65228039142d249f38Adam Powell            } else {
46397341bdc5bea1d7bf777de65228039142d249f38Adam Powell                childWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
46497341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
46597341bdc5bea1d7bf777de65228039142d249f38Adam Powell
46697341bdc5bea1d7bf777de65228039142d249f38Adam Powell            int childHeightSpec;
46797341bdc5bea1d7bf777de65228039142d249f38Adam Powell            if (lp.height == LayoutParams.WRAP_CONTENT) {
46897341bdc5bea1d7bf777de65228039142d249f38Adam Powell                childHeightSpec = MeasureSpec.makeMeasureSpec(maxLayoutHeight, MeasureSpec.AT_MOST);
46997341bdc5bea1d7bf777de65228039142d249f38Adam Powell            } else if (lp.height == LayoutParams.FILL_PARENT) {
47097341bdc5bea1d7bf777de65228039142d249f38Adam Powell                childHeightSpec = MeasureSpec.makeMeasureSpec(maxLayoutHeight, MeasureSpec.EXACTLY);
47197341bdc5bea1d7bf777de65228039142d249f38Adam Powell            } else {
47297341bdc5bea1d7bf777de65228039142d249f38Adam Powell                childHeightSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);
47397341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
47497341bdc5bea1d7bf777de65228039142d249f38Adam Powell
47597341bdc5bea1d7bf777de65228039142d249f38Adam Powell            child.measure(childWidthSpec, childHeightSpec);
47697341bdc5bea1d7bf777de65228039142d249f38Adam Powell            final int childWidth = child.getMeasuredWidth();
47797341bdc5bea1d7bf777de65228039142d249f38Adam Powell            final int childHeight = child.getMeasuredHeight();
47897341bdc5bea1d7bf777de65228039142d249f38Adam Powell
47997341bdc5bea1d7bf777de65228039142d249f38Adam Powell            if (heightMode == MeasureSpec.AT_MOST && childHeight > layoutHeight) {
48097341bdc5bea1d7bf777de65228039142d249f38Adam Powell                layoutHeight = Math.min(childHeight, maxLayoutHeight);
48197341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
48297341bdc5bea1d7bf777de65228039142d249f38Adam Powell
48397341bdc5bea1d7bf777de65228039142d249f38Adam Powell            widthRemaining -= childWidth;
4840eefe9ad0819b223006533cbc79a35d66684af32Adam Powell            canSlide |= lp.slideable = widthRemaining < 0;
4850eefe9ad0819b223006533cbc79a35d66684af32Adam Powell            if (lp.slideable) {
4860eefe9ad0819b223006533cbc79a35d66684af32Adam Powell                mSlideableView = child;
4870eefe9ad0819b223006533cbc79a35d66684af32Adam Powell            }
48897341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
48997341bdc5bea1d7bf777de65228039142d249f38Adam Powell
49097341bdc5bea1d7bf777de65228039142d249f38Adam Powell        // Resolve weight and make sure non-sliding panels are smaller than the full screen.
49197341bdc5bea1d7bf777de65228039142d249f38Adam Powell        if (canSlide || weightSum > 0) {
49297341bdc5bea1d7bf777de65228039142d249f38Adam Powell            final int fixedPanelWidthLimit = widthSize - mOverhangSize;
49397341bdc5bea1d7bf777de65228039142d249f38Adam Powell
49497341bdc5bea1d7bf777de65228039142d249f38Adam Powell            for (int i = 0; i < childCount; i++) {
49597341bdc5bea1d7bf777de65228039142d249f38Adam Powell                final View child = getChildAt(i);
4960eefe9ad0819b223006533cbc79a35d66684af32Adam Powell
4970eefe9ad0819b223006533cbc79a35d66684af32Adam Powell                if (child.getVisibility() == GONE) {
4980eefe9ad0819b223006533cbc79a35d66684af32Adam Powell                    continue;
4990eefe9ad0819b223006533cbc79a35d66684af32Adam Powell                }
5000eefe9ad0819b223006533cbc79a35d66684af32Adam Powell
50197341bdc5bea1d7bf777de65228039142d249f38Adam Powell                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
50297341bdc5bea1d7bf777de65228039142d249f38Adam Powell
50397341bdc5bea1d7bf777de65228039142d249f38Adam Powell                final boolean skippedFirstPass = lp.width == 0 && lp.weight > 0;
50497341bdc5bea1d7bf777de65228039142d249f38Adam Powell                final int measuredWidth = skippedFirstPass ? 0 : child.getMeasuredWidth();
5050eefe9ad0819b223006533cbc79a35d66684af32Adam Powell                if (canSlide && child != mSlideableView) {
50697341bdc5bea1d7bf777de65228039142d249f38Adam Powell                    if (lp.width < 0 && (measuredWidth > fixedPanelWidthLimit || lp.weight > 0)) {
50797341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        // Fixed panels in a sliding configuration should
50897341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        // be clamped to the fixed panel limit.
50997341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        final int childHeightSpec;
51097341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        if (skippedFirstPass) {
51197341bdc5bea1d7bf777de65228039142d249f38Adam Powell                            // Do initial height measurement if we skipped measuring this view
51297341bdc5bea1d7bf777de65228039142d249f38Adam Powell                            // the first time around.
51397341bdc5bea1d7bf777de65228039142d249f38Adam Powell                            if (lp.height == LayoutParams.WRAP_CONTENT) {
51497341bdc5bea1d7bf777de65228039142d249f38Adam Powell                                childHeightSpec = MeasureSpec.makeMeasureSpec(maxLayoutHeight,
51597341bdc5bea1d7bf777de65228039142d249f38Adam Powell                                        MeasureSpec.AT_MOST);
51697341bdc5bea1d7bf777de65228039142d249f38Adam Powell                            } else if (lp.height == LayoutParams.FILL_PARENT) {
51797341bdc5bea1d7bf777de65228039142d249f38Adam Powell                                childHeightSpec = MeasureSpec.makeMeasureSpec(maxLayoutHeight,
51897341bdc5bea1d7bf777de65228039142d249f38Adam Powell                                        MeasureSpec.EXACTLY);
51997341bdc5bea1d7bf777de65228039142d249f38Adam Powell                            } else {
52097341bdc5bea1d7bf777de65228039142d249f38Adam Powell                                childHeightSpec = MeasureSpec.makeMeasureSpec(lp.height,
52197341bdc5bea1d7bf777de65228039142d249f38Adam Powell                                        MeasureSpec.EXACTLY);
52297341bdc5bea1d7bf777de65228039142d249f38Adam Powell                            }
52397341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        } else {
52497341bdc5bea1d7bf777de65228039142d249f38Adam Powell                            childHeightSpec = MeasureSpec.makeMeasureSpec(
52597341bdc5bea1d7bf777de65228039142d249f38Adam Powell                                    child.getMeasuredHeight(), MeasureSpec.EXACTLY);
52697341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        }
52797341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        final int childWidthSpec = MeasureSpec.makeMeasureSpec(
52897341bdc5bea1d7bf777de65228039142d249f38Adam Powell                                fixedPanelWidthLimit, MeasureSpec.EXACTLY);
52997341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        child.measure(childWidthSpec, childHeightSpec);
53097341bdc5bea1d7bf777de65228039142d249f38Adam Powell                    }
53197341bdc5bea1d7bf777de65228039142d249f38Adam Powell                } else if (lp.weight > 0) {
53297341bdc5bea1d7bf777de65228039142d249f38Adam Powell                    int childHeightSpec;
53397341bdc5bea1d7bf777de65228039142d249f38Adam Powell                    if (lp.width == 0) {
53497341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        // This was skipped the first time; figure out a real height spec.
53597341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        if (lp.height == LayoutParams.WRAP_CONTENT) {
53697341bdc5bea1d7bf777de65228039142d249f38Adam Powell                            childHeightSpec = MeasureSpec.makeMeasureSpec(maxLayoutHeight,
53797341bdc5bea1d7bf777de65228039142d249f38Adam Powell                                    MeasureSpec.AT_MOST);
53897341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        } else if (lp.height == LayoutParams.FILL_PARENT) {
53997341bdc5bea1d7bf777de65228039142d249f38Adam Powell                            childHeightSpec = MeasureSpec.makeMeasureSpec(maxLayoutHeight,
54097341bdc5bea1d7bf777de65228039142d249f38Adam Powell                                    MeasureSpec.EXACTLY);
54197341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        } else {
54297341bdc5bea1d7bf777de65228039142d249f38Adam Powell                            childHeightSpec = MeasureSpec.makeMeasureSpec(lp.height,
54397341bdc5bea1d7bf777de65228039142d249f38Adam Powell                                    MeasureSpec.EXACTLY);
54497341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        }
54597341bdc5bea1d7bf777de65228039142d249f38Adam Powell                    } else {
54697341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        childHeightSpec = MeasureSpec.makeMeasureSpec(
54797341bdc5bea1d7bf777de65228039142d249f38Adam Powell                                child.getMeasuredHeight(), MeasureSpec.EXACTLY);
54897341bdc5bea1d7bf777de65228039142d249f38Adam Powell                    }
54997341bdc5bea1d7bf777de65228039142d249f38Adam Powell
55097341bdc5bea1d7bf777de65228039142d249f38Adam Powell                    if (canSlide) {
55197341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        // Consume available space
55297341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        final int horizontalMargin = lp.leftMargin + lp.rightMargin;
55397341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        final int newWidth = widthSize - horizontalMargin;
55497341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        final int childWidthSpec = MeasureSpec.makeMeasureSpec(
55597341bdc5bea1d7bf777de65228039142d249f38Adam Powell                                newWidth, MeasureSpec.EXACTLY);
55697341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        if (measuredWidth != newWidth) {
55797341bdc5bea1d7bf777de65228039142d249f38Adam Powell                            child.measure(childWidthSpec, childHeightSpec);
55897341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        }
55997341bdc5bea1d7bf777de65228039142d249f38Adam Powell                    } else {
56097341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        // Distribute the extra width proportionally similar to LinearLayout
56197341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        final int widthToDistribute = Math.max(0, widthRemaining);
56297341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        final int addedWidth = (int) (lp.weight * widthToDistribute / weightSum);
56397341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        final int childWidthSpec = MeasureSpec.makeMeasureSpec(
56497341bdc5bea1d7bf777de65228039142d249f38Adam Powell                                measuredWidth + addedWidth, MeasureSpec.EXACTLY);
56597341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        child.measure(childWidthSpec, childHeightSpec);
56697341bdc5bea1d7bf777de65228039142d249f38Adam Powell                    }
56797341bdc5bea1d7bf777de65228039142d249f38Adam Powell                }
56897341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
56997341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
57097341bdc5bea1d7bf777de65228039142d249f38Adam Powell
57197341bdc5bea1d7bf777de65228039142d249f38Adam Powell        setMeasuredDimension(widthSize, layoutHeight);
57297341bdc5bea1d7bf777de65228039142d249f38Adam Powell        mCanSlide = canSlide;
573471f0f4e84c7d1f96e48fb26713f246d69c3241fAdam Powell        if (mDragHelper.getViewDragState() != ViewDragHelper.STATE_IDLE && !canSlide) {
5740eefe9ad0819b223006533cbc79a35d66684af32Adam Powell            // Cancel scrolling in progress, it's no longer relevant.
575471f0f4e84c7d1f96e48fb26713f246d69c3241fAdam Powell            mDragHelper.abort();
57697341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
57797341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
57897341bdc5bea1d7bf777de65228039142d249f38Adam Powell
57997341bdc5bea1d7bf777de65228039142d249f38Adam Powell    @Override
58097341bdc5bea1d7bf777de65228039142d249f38Adam Powell    protected void onLayout(boolean changed, int l, int t, int r, int b) {
58197341bdc5bea1d7bf777de65228039142d249f38Adam Powell        final int width = r - l;
58297341bdc5bea1d7bf777de65228039142d249f38Adam Powell        final int paddingLeft = getPaddingLeft();
58397341bdc5bea1d7bf777de65228039142d249f38Adam Powell        final int paddingRight = getPaddingRight();
58497341bdc5bea1d7bf777de65228039142d249f38Adam Powell        final int paddingTop = getPaddingTop();
58597341bdc5bea1d7bf777de65228039142d249f38Adam Powell
5866debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell        final int childCount = getChildCount();
58797341bdc5bea1d7bf777de65228039142d249f38Adam Powell        int xStart = paddingLeft;
58897341bdc5bea1d7bf777de65228039142d249f38Adam Powell        int nextXStart = xStart;
58997341bdc5bea1d7bf777de65228039142d249f38Adam Powell
590d44315a54e002b20365189f03a09011f2bf6ba07Adam Powell        if (mFirstLayout) {
591d44315a54e002b20365189f03a09011f2bf6ba07Adam Powell            mSlideOffset = mCanSlide && mPreservedOpenState ? 1.f : 0.f;
592d44315a54e002b20365189f03a09011f2bf6ba07Adam Powell        }
593d44315a54e002b20365189f03a09011f2bf6ba07Adam Powell
59497341bdc5bea1d7bf777de65228039142d249f38Adam Powell        for (int i = 0; i < childCount; i++) {
59597341bdc5bea1d7bf777de65228039142d249f38Adam Powell            final View child = getChildAt(i);
5960eefe9ad0819b223006533cbc79a35d66684af32Adam Powell
5970eefe9ad0819b223006533cbc79a35d66684af32Adam Powell            if (child.getVisibility() == GONE) {
5980eefe9ad0819b223006533cbc79a35d66684af32Adam Powell                continue;
5990eefe9ad0819b223006533cbc79a35d66684af32Adam Powell            }
6000eefe9ad0819b223006533cbc79a35d66684af32Adam Powell
60197341bdc5bea1d7bf777de65228039142d249f38Adam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
60297341bdc5bea1d7bf777de65228039142d249f38Adam Powell
60397341bdc5bea1d7bf777de65228039142d249f38Adam Powell            final int childWidth = child.getMeasuredWidth();
6046debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell            int offset = 0;
60597341bdc5bea1d7bf777de65228039142d249f38Adam Powell
6060eefe9ad0819b223006533cbc79a35d66684af32Adam Powell            if (lp.slideable) {
6076debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell                final int margin = lp.leftMargin + lp.rightMargin;
6086debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell                final int range = Math.min(nextXStart,
6096debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell                        width - paddingRight - mOverhangSize) - xStart - margin;
6100eefe9ad0819b223006533cbc79a35d66684af32Adam Powell                mSlideRange = range;
6113f50aafe43ea3c7d1c09fbd7afa87bf7453beb18Adam Powell                lp.dimWhenOffset = xStart + lp.leftMargin + range + childWidth / 2 >
6123f50aafe43ea3c7d1c09fbd7afa87bf7453beb18Adam Powell                        width - paddingRight;
6130eefe9ad0819b223006533cbc79a35d66684af32Adam Powell                xStart += (int) (range * mSlideOffset) + lp.leftMargin;
6140eefe9ad0819b223006533cbc79a35d66684af32Adam Powell            } else if (mCanSlide && mParallaxBy != 0) {
6150eefe9ad0819b223006533cbc79a35d66684af32Adam Powell                offset = (int) ((1 - mSlideOffset) * mParallaxBy);
6166debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell                xStart = nextXStart;
61797341bdc5bea1d7bf777de65228039142d249f38Adam Powell            } else {
61897341bdc5bea1d7bf777de65228039142d249f38Adam Powell                xStart = nextXStart;
61997341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
62097341bdc5bea1d7bf777de65228039142d249f38Adam Powell
6210eefe9ad0819b223006533cbc79a35d66684af32Adam Powell            final int childLeft = xStart - offset;
62297341bdc5bea1d7bf777de65228039142d249f38Adam Powell            final int childRight = childLeft + childWidth;
62397341bdc5bea1d7bf777de65228039142d249f38Adam Powell            final int childTop = paddingTop;
62497341bdc5bea1d7bf777de65228039142d249f38Adam Powell            final int childBottom = childTop + child.getMeasuredHeight();
62597341bdc5bea1d7bf777de65228039142d249f38Adam Powell            child.layout(childLeft, paddingTop, childRight, childBottom);
62697341bdc5bea1d7bf777de65228039142d249f38Adam Powell
6276debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell            nextXStart += child.getWidth();
62897341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
62989e17886e6149bddfdb08a242c9e88889596419cAdam Powell
63058898b639b18392580694bc6c902479274331bf2Adam Powell        if (mFirstLayout) {
63158898b639b18392580694bc6c902479274331bf2Adam Powell            if (mCanSlide) {
63258898b639b18392580694bc6c902479274331bf2Adam Powell                if (mParallaxBy != 0) {
63358898b639b18392580694bc6c902479274331bf2Adam Powell                    parallaxOtherViews(mSlideOffset);
63458898b639b18392580694bc6c902479274331bf2Adam Powell                }
63558898b639b18392580694bc6c902479274331bf2Adam Powell                if (((LayoutParams) mSlideableView.getLayoutParams()).dimWhenOffset) {
63658898b639b18392580694bc6c902479274331bf2Adam Powell                    dimChildView(mSlideableView, mSlideOffset, mSliderFadeColor);
63758898b639b18392580694bc6c902479274331bf2Adam Powell                }
63858898b639b18392580694bc6c902479274331bf2Adam Powell            } else {
63958898b639b18392580694bc6c902479274331bf2Adam Powell                // Reset the dim level of all children; it's irrelevant when nothing moves.
64058898b639b18392580694bc6c902479274331bf2Adam Powell                for (int i = 0; i < childCount; i++) {
64158898b639b18392580694bc6c902479274331bf2Adam Powell                    dimChildView(getChildAt(i), 0, mSliderFadeColor);
64258898b639b18392580694bc6c902479274331bf2Adam Powell                }
64389e17886e6149bddfdb08a242c9e88889596419cAdam Powell            }
644c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            updateObscuredViewsVisibility(mSlideableView);
64589e17886e6149bddfdb08a242c9e88889596419cAdam Powell        }
64689e17886e6149bddfdb08a242c9e88889596419cAdam Powell
64789e17886e6149bddfdb08a242c9e88889596419cAdam Powell        mFirstLayout = false;
64889e17886e6149bddfdb08a242c9e88889596419cAdam Powell    }
64989e17886e6149bddfdb08a242c9e88889596419cAdam Powell
65089e17886e6149bddfdb08a242c9e88889596419cAdam Powell    @Override
65189e17886e6149bddfdb08a242c9e88889596419cAdam Powell    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
65289e17886e6149bddfdb08a242c9e88889596419cAdam Powell        super.onSizeChanged(w, h, oldw, oldh);
65389e17886e6149bddfdb08a242c9e88889596419cAdam Powell        // Recalculate sliding panes and their details
65472c7316b081c3134f7b0566f703dfee7c970eadeAdam Powell        if (w != oldw) {
65572c7316b081c3134f7b0566f703dfee7c970eadeAdam Powell            mFirstLayout = true;
65672c7316b081c3134f7b0566f703dfee7c970eadeAdam Powell        }
65789e17886e6149bddfdb08a242c9e88889596419cAdam Powell    }
65889e17886e6149bddfdb08a242c9e88889596419cAdam Powell
65989e17886e6149bddfdb08a242c9e88889596419cAdam Powell    @Override
66089e17886e6149bddfdb08a242c9e88889596419cAdam Powell    public void requestChildFocus(View child, View focused) {
66189e17886e6149bddfdb08a242c9e88889596419cAdam Powell        super.requestChildFocus(child, focused);
66289e17886e6149bddfdb08a242c9e88889596419cAdam Powell        if (!isInTouchMode() && !mCanSlide) {
66389e17886e6149bddfdb08a242c9e88889596419cAdam Powell            mPreservedOpenState = child == mSlideableView;
66489e17886e6149bddfdb08a242c9e88889596419cAdam Powell        }
66597341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
66697341bdc5bea1d7bf777de65228039142d249f38Adam Powell
66797341bdc5bea1d7bf777de65228039142d249f38Adam Powell    @Override
66897341bdc5bea1d7bf777de65228039142d249f38Adam Powell    public boolean onInterceptTouchEvent(MotionEvent ev) {
66989e17886e6149bddfdb08a242c9e88889596419cAdam Powell        final int action = MotionEventCompat.getActionMasked(ev);
67089e17886e6149bddfdb08a242c9e88889596419cAdam Powell
67189e17886e6149bddfdb08a242c9e88889596419cAdam Powell        // Preserve the open state based on the last view that was touched.
67289e17886e6149bddfdb08a242c9e88889596419cAdam Powell        if (!mCanSlide && action == MotionEvent.ACTION_DOWN && getChildCount() > 1) {
67389e17886e6149bddfdb08a242c9e88889596419cAdam Powell            // After the first things will be slideable.
67489e17886e6149bddfdb08a242c9e88889596419cAdam Powell            final View secondChild = getChildAt(1);
67589e17886e6149bddfdb08a242c9e88889596419cAdam Powell            if (secondChild != null) {
67689e17886e6149bddfdb08a242c9e88889596419cAdam Powell                mPreservedOpenState = !mDragHelper.isViewUnder(secondChild,
67789e17886e6149bddfdb08a242c9e88889596419cAdam Powell                        (int) ev.getX(), (int) ev.getY());
67889e17886e6149bddfdb08a242c9e88889596419cAdam Powell            }
67989e17886e6149bddfdb08a242c9e88889596419cAdam Powell        }
6800eefe9ad0819b223006533cbc79a35d66684af32Adam Powell
6810eefe9ad0819b223006533cbc79a35d66684af32Adam Powell        if (!mCanSlide || (mIsUnableToDrag && action != MotionEvent.ACTION_DOWN)) {
6826580cf4b7e74a2a017ed95b0dc50155b9995edebAdam Powell            mDragHelper.cancel();
68397341bdc5bea1d7bf777de65228039142d249f38Adam Powell            return super.onInterceptTouchEvent(ev);
68497341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
68597341bdc5bea1d7bf777de65228039142d249f38Adam Powell
68697341bdc5bea1d7bf777de65228039142d249f38Adam Powell        if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
6876580cf4b7e74a2a017ed95b0dc50155b9995edebAdam Powell            mDragHelper.cancel();
68897341bdc5bea1d7bf777de65228039142d249f38Adam Powell            return false;
68997341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
69097341bdc5bea1d7bf777de65228039142d249f38Adam Powell
69197341bdc5bea1d7bf777de65228039142d249f38Adam Powell        boolean interceptTap = false;
69297341bdc5bea1d7bf777de65228039142d249f38Adam Powell
69397341bdc5bea1d7bf777de65228039142d249f38Adam Powell        switch (action) {
6946580cf4b7e74a2a017ed95b0dc50155b9995edebAdam Powell            case MotionEvent.ACTION_DOWN: {
69597341bdc5bea1d7bf777de65228039142d249f38Adam Powell                mIsUnableToDrag = false;
6966580cf4b7e74a2a017ed95b0dc50155b9995edebAdam Powell                final float x = ev.getX();
6976580cf4b7e74a2a017ed95b0dc50155b9995edebAdam Powell                final float y = ev.getY();
698ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell                mInitialMotionX = x;
699ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell                mInitialMotionY = y;
70089e17886e6149bddfdb08a242c9e88889596419cAdam Powell
7016580cf4b7e74a2a017ed95b0dc50155b9995edebAdam Powell                if (mDragHelper.isViewUnder(mSlideableView, (int) x, (int) y) &&
7021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                        isDimmed(mSlideableView)) {
703c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell                    interceptTap = true;
70497341bdc5bea1d7bf777de65228039142d249f38Adam Powell                }
70597341bdc5bea1d7bf777de65228039142d249f38Adam Powell                break;
70697341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
70729836199390f71d05b15eedb487c1f7465776f1dAdam Powell
70829836199390f71d05b15eedb487c1f7465776f1dAdam Powell            case MotionEvent.ACTION_MOVE: {
70929836199390f71d05b15eedb487c1f7465776f1dAdam Powell                final float x = ev.getX();
71029836199390f71d05b15eedb487c1f7465776f1dAdam Powell                final float y = ev.getY();
71129836199390f71d05b15eedb487c1f7465776f1dAdam Powell                final float adx = Math.abs(x - mInitialMotionX);
71229836199390f71d05b15eedb487c1f7465776f1dAdam Powell                final float ady = Math.abs(y - mInitialMotionY);
71329836199390f71d05b15eedb487c1f7465776f1dAdam Powell                final int slop = mDragHelper.getTouchSlop();
71429836199390f71d05b15eedb487c1f7465776f1dAdam Powell                if (adx > slop && ady > adx) {
71529836199390f71d05b15eedb487c1f7465776f1dAdam Powell                    mDragHelper.cancel();
71629836199390f71d05b15eedb487c1f7465776f1dAdam Powell                    mIsUnableToDrag = true;
71729836199390f71d05b15eedb487c1f7465776f1dAdam Powell                    return false;
71829836199390f71d05b15eedb487c1f7465776f1dAdam Powell                }
71929836199390f71d05b15eedb487c1f7465776f1dAdam Powell            }
72097341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
72197341bdc5bea1d7bf777de65228039142d249f38Adam Powell
72229836199390f71d05b15eedb487c1f7465776f1dAdam Powell        final boolean interceptForDrag = mDragHelper.shouldInterceptTouchEvent(ev);
72329836199390f71d05b15eedb487c1f7465776f1dAdam Powell
724c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        return interceptForDrag || interceptTap;
72597341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
72697341bdc5bea1d7bf777de65228039142d249f38Adam Powell
72797341bdc5bea1d7bf777de65228039142d249f38Adam Powell    @Override
72897341bdc5bea1d7bf777de65228039142d249f38Adam Powell    public boolean onTouchEvent(MotionEvent ev) {
72997341bdc5bea1d7bf777de65228039142d249f38Adam Powell        if (!mCanSlide) {
73097341bdc5bea1d7bf777de65228039142d249f38Adam Powell            return super.onTouchEvent(ev);
73197341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
73297341bdc5bea1d7bf777de65228039142d249f38Adam Powell
733c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        mDragHelper.processTouchEvent(ev);
73497341bdc5bea1d7bf777de65228039142d249f38Adam Powell
73597341bdc5bea1d7bf777de65228039142d249f38Adam Powell        final int action = ev.getAction();
7366debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell        boolean wantTouchEvents = true;
73797341bdc5bea1d7bf777de65228039142d249f38Adam Powell
73897341bdc5bea1d7bf777de65228039142d249f38Adam Powell        switch (action & MotionEventCompat.ACTION_MASK) {
73997341bdc5bea1d7bf777de65228039142d249f38Adam Powell            case MotionEvent.ACTION_DOWN: {
74097341bdc5bea1d7bf777de65228039142d249f38Adam Powell                final float x = ev.getX();
74197341bdc5bea1d7bf777de65228039142d249f38Adam Powell                final float y = ev.getY();
742ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell                mInitialMotionX = x;
743ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell                mInitialMotionY = y;
74497341bdc5bea1d7bf777de65228039142d249f38Adam Powell                break;
74597341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
74697341bdc5bea1d7bf777de65228039142d249f38Adam Powell
74797341bdc5bea1d7bf777de65228039142d249f38Adam Powell            case MotionEvent.ACTION_UP: {
748ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell                if (isDimmed(mSlideableView)) {
7496580cf4b7e74a2a017ed95b0dc50155b9995edebAdam Powell                    final float x = ev.getX();
7506580cf4b7e74a2a017ed95b0dc50155b9995edebAdam Powell                    final float y = ev.getY();
751ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell                    final float dx = x - mInitialMotionX;
752ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell                    final float dy = y - mInitialMotionY;
7531d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    final int slop = mDragHelper.getTouchSlop();
7541d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell                    if (dx * dx + dy * dy < slop * slop &&
7556580cf4b7e74a2a017ed95b0dc50155b9995edebAdam Powell                            mDragHelper.isViewUnder(mSlideableView, (int) x, (int) y)) {
756ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell                        // Taps close a dimmed open pane.
757ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell                        closePane(mSlideableView, 0);
758ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell                        break;
759ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell                    }
760ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell                }
76197341bdc5bea1d7bf777de65228039142d249f38Adam Powell                break;
76297341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
76397341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
76497341bdc5bea1d7bf777de65228039142d249f38Adam Powell
76597341bdc5bea1d7bf777de65228039142d249f38Adam Powell        return wantTouchEvents;
76697341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
76797341bdc5bea1d7bf777de65228039142d249f38Adam Powell
76889e17886e6149bddfdb08a242c9e88889596419cAdam Powell    private boolean closePane(View pane, int initialVelocity) {
76989e17886e6149bddfdb08a242c9e88889596419cAdam Powell        if (mFirstLayout || smoothSlideTo(0.f, initialVelocity)) {
77089e17886e6149bddfdb08a242c9e88889596419cAdam Powell            mPreservedOpenState = false;
77189e17886e6149bddfdb08a242c9e88889596419cAdam Powell            return true;
7720eefe9ad0819b223006533cbc79a35d66684af32Adam Powell        }
77389e17886e6149bddfdb08a242c9e88889596419cAdam Powell        return false;
77497341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
77597341bdc5bea1d7bf777de65228039142d249f38Adam Powell
77689e17886e6149bddfdb08a242c9e88889596419cAdam Powell    private boolean openPane(View pane, int initialVelocity) {
77789e17886e6149bddfdb08a242c9e88889596419cAdam Powell        if (mFirstLayout || smoothSlideTo(1.f, initialVelocity)) {
77889e17886e6149bddfdb08a242c9e88889596419cAdam Powell            mPreservedOpenState = true;
77989e17886e6149bddfdb08a242c9e88889596419cAdam Powell            return true;
7800eefe9ad0819b223006533cbc79a35d66684af32Adam Powell        }
78189e17886e6149bddfdb08a242c9e88889596419cAdam Powell        return false;
78297341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
78397341bdc5bea1d7bf777de65228039142d249f38Adam Powell
78497341bdc5bea1d7bf777de65228039142d249f38Adam Powell    /**
78589e17886e6149bddfdb08a242c9e88889596419cAdam Powell     * @deprecated Renamed to {@link #openPane()} - this method is going away soon!
78697341bdc5bea1d7bf777de65228039142d249f38Adam Powell     */
78789e17886e6149bddfdb08a242c9e88889596419cAdam Powell    @Deprecated
78897341bdc5bea1d7bf777de65228039142d249f38Adam Powell    public void smoothSlideOpen() {
78989e17886e6149bddfdb08a242c9e88889596419cAdam Powell        openPane();
79089e17886e6149bddfdb08a242c9e88889596419cAdam Powell    }
79189e17886e6149bddfdb08a242c9e88889596419cAdam Powell
79289e17886e6149bddfdb08a242c9e88889596419cAdam Powell    /**
79389e17886e6149bddfdb08a242c9e88889596419cAdam Powell     * Open the sliding pane if it is currently slideable. If first layout
79489e17886e6149bddfdb08a242c9e88889596419cAdam Powell     * has already completed this will animate.
79589e17886e6149bddfdb08a242c9e88889596419cAdam Powell     *
79689e17886e6149bddfdb08a242c9e88889596419cAdam Powell     * @return true if the pane was slideable and is now open/in the process of opening
79789e17886e6149bddfdb08a242c9e88889596419cAdam Powell     */
79889e17886e6149bddfdb08a242c9e88889596419cAdam Powell    public boolean openPane() {
79989e17886e6149bddfdb08a242c9e88889596419cAdam Powell        return openPane(mSlideableView, 0);
80097341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
80197341bdc5bea1d7bf777de65228039142d249f38Adam Powell
80297341bdc5bea1d7bf777de65228039142d249f38Adam Powell    /**
80389e17886e6149bddfdb08a242c9e88889596419cAdam Powell     * @deprecated Renamed to {@link #closePane()} - this method is going away soon!
80497341bdc5bea1d7bf777de65228039142d249f38Adam Powell     */
80589e17886e6149bddfdb08a242c9e88889596419cAdam Powell    @Deprecated
80697341bdc5bea1d7bf777de65228039142d249f38Adam Powell    public void smoothSlideClosed() {
80789e17886e6149bddfdb08a242c9e88889596419cAdam Powell        closePane();
80889e17886e6149bddfdb08a242c9e88889596419cAdam Powell    }
80989e17886e6149bddfdb08a242c9e88889596419cAdam Powell
81089e17886e6149bddfdb08a242c9e88889596419cAdam Powell    /**
81189e17886e6149bddfdb08a242c9e88889596419cAdam Powell     * Close the sliding pane if it is currently slideable. If first layout
81289e17886e6149bddfdb08a242c9e88889596419cAdam Powell     * has already completed this will animate.
81389e17886e6149bddfdb08a242c9e88889596419cAdam Powell     *
81489e17886e6149bddfdb08a242c9e88889596419cAdam Powell     * @return true if the pane was slideable and is now closed/in the process of closing
81589e17886e6149bddfdb08a242c9e88889596419cAdam Powell     */
81689e17886e6149bddfdb08a242c9e88889596419cAdam Powell    public boolean closePane() {
81789e17886e6149bddfdb08a242c9e88889596419cAdam Powell        return closePane(mSlideableView, 0);
81897341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
81997341bdc5bea1d7bf777de65228039142d249f38Adam Powell
82097341bdc5bea1d7bf777de65228039142d249f38Adam Powell    /**
82189e17886e6149bddfdb08a242c9e88889596419cAdam Powell     * Check if the layout is completely open. It can be open either because the slider
82289e17886e6149bddfdb08a242c9e88889596419cAdam Powell     * itself is open revealing the left pane, or if all content fits without sliding.
82389e17886e6149bddfdb08a242c9e88889596419cAdam Powell     *
82497341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * @return true if sliding panels are completely open
82597341bdc5bea1d7bf777de65228039142d249f38Adam Powell     */
82697341bdc5bea1d7bf777de65228039142d249f38Adam Powell    public boolean isOpen() {
8270eefe9ad0819b223006533cbc79a35d66684af32Adam Powell        return !mCanSlide || mSlideOffset == 1;
82897341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
82997341bdc5bea1d7bf777de65228039142d249f38Adam Powell
83097341bdc5bea1d7bf777de65228039142d249f38Adam Powell    /**
83197341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * @return true if content in this layout can be slid open and closed
83289e17886e6149bddfdb08a242c9e88889596419cAdam Powell     * @deprecated Renamed to {@link #isSlideable()} - this method is going away soon!
83397341bdc5bea1d7bf777de65228039142d249f38Adam Powell     */
83489e17886e6149bddfdb08a242c9e88889596419cAdam Powell    @Deprecated
83597341bdc5bea1d7bf777de65228039142d249f38Adam Powell    public boolean canSlide() {
83697341bdc5bea1d7bf777de65228039142d249f38Adam Powell        return mCanSlide;
83797341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
83897341bdc5bea1d7bf777de65228039142d249f38Adam Powell
83989e17886e6149bddfdb08a242c9e88889596419cAdam Powell    /**
84089e17886e6149bddfdb08a242c9e88889596419cAdam Powell     * Check if the content in this layout cannot fully fit side by side and therefore
84189e17886e6149bddfdb08a242c9e88889596419cAdam Powell     * the content pane can be slid back and forth.
84289e17886e6149bddfdb08a242c9e88889596419cAdam Powell     *
84389e17886e6149bddfdb08a242c9e88889596419cAdam Powell     * @return true if content in this layout can be slid open and closed
84489e17886e6149bddfdb08a242c9e88889596419cAdam Powell     */
84589e17886e6149bddfdb08a242c9e88889596419cAdam Powell    public boolean isSlideable() {
84689e17886e6149bddfdb08a242c9e88889596419cAdam Powell        return mCanSlide;
84789e17886e6149bddfdb08a242c9e88889596419cAdam Powell    }
84889e17886e6149bddfdb08a242c9e88889596419cAdam Powell
849d44315a54e002b20365189f03a09011f2bf6ba07Adam Powell    private void onPanelDragged(int newLeft) {
8500eefe9ad0819b223006533cbc79a35d66684af32Adam Powell        final LayoutParams lp = (LayoutParams) mSlideableView.getLayoutParams();
85197341bdc5bea1d7bf777de65228039142d249f38Adam Powell        final int leftBound = getPaddingLeft() + lp.leftMargin;
85297341bdc5bea1d7bf777de65228039142d249f38Adam Powell
853c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        mSlideOffset = (float) (newLeft - leftBound) / mSlideRange;
85497341bdc5bea1d7bf777de65228039142d249f38Adam Powell
8556debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell        if (mParallaxBy != 0) {
8560eefe9ad0819b223006533cbc79a35d66684af32Adam Powell            parallaxOtherViews(mSlideOffset);
8576debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell        }
8586debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell
859ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell        if (lp.dimWhenOffset) {
86081e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell            dimChildView(mSlideableView, mSlideOffset, mSliderFadeColor);
861ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell        }
8620eefe9ad0819b223006533cbc79a35d66684af32Adam Powell        dispatchOnPanelSlide(mSlideableView);
86397341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
86497341bdc5bea1d7bf777de65228039142d249f38Adam Powell
86581e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell    private void dimChildView(View v, float mag, int fadeColor) {
86697341bdc5bea1d7bf777de65228039142d249f38Adam Powell        final LayoutParams lp = (LayoutParams) v.getLayoutParams();
86797341bdc5bea1d7bf777de65228039142d249f38Adam Powell
86881e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell        if (mag > 0 && fadeColor != 0) {
86981e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell            final int baseAlpha = (fadeColor & 0xff000000) >>> 24;
870ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell            int imag = (int) (baseAlpha * mag);
87181e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell            int color = imag << 24 | (fadeColor & 0xffffff);
87297341bdc5bea1d7bf777de65228039142d249f38Adam Powell            if (lp.dimPaint == null) {
87397341bdc5bea1d7bf777de65228039142d249f38Adam Powell                lp.dimPaint = new Paint();
87497341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
875ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell            lp.dimPaint.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_OVER));
87697341bdc5bea1d7bf777de65228039142d249f38Adam Powell            if (ViewCompat.getLayerType(v) != ViewCompat.LAYER_TYPE_HARDWARE) {
87797341bdc5bea1d7bf777de65228039142d249f38Adam Powell                ViewCompat.setLayerType(v, ViewCompat.LAYER_TYPE_HARDWARE, lp.dimPaint);
87897341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
87997341bdc5bea1d7bf777de65228039142d249f38Adam Powell            invalidateChildRegion(v);
88097341bdc5bea1d7bf777de65228039142d249f38Adam Powell        } else if (ViewCompat.getLayerType(v) != ViewCompat.LAYER_TYPE_NONE) {
88158898b639b18392580694bc6c902479274331bf2Adam Powell            if (lp.dimPaint != null) {
88258898b639b18392580694bc6c902479274331bf2Adam Powell                lp.dimPaint.setColorFilter(null);
88358898b639b18392580694bc6c902479274331bf2Adam Powell            }
88497341bdc5bea1d7bf777de65228039142d249f38Adam Powell            ViewCompat.setLayerType(v, ViewCompat.LAYER_TYPE_NONE, null);
88558898b639b18392580694bc6c902479274331bf2Adam Powell            invalidateChildRegion(v);
88697341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
88797341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
88897341bdc5bea1d7bf777de65228039142d249f38Adam Powell
88997341bdc5bea1d7bf777de65228039142d249f38Adam Powell    @Override
89097341bdc5bea1d7bf777de65228039142d249f38Adam Powell    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
8911e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
8921e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell        boolean result;
8931e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell        final int save = canvas.save(Canvas.CLIP_SAVE_FLAG);
8941e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell
8951e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell        if (mCanSlide && !lp.slideable && mSlideableView != null) {
8961e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell            // Clip against the slider; no sense drawing what will immediately be covered.
8971e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell            canvas.getClipBounds(mTmpRect);
8981e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell            mTmpRect.right = Math.min(mTmpRect.right, mSlideableView.getLeft());
8991e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell            canvas.clipRect(mTmpRect);
90097341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
90197341bdc5bea1d7bf777de65228039142d249f38Adam Powell
9021e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell        if (Build.VERSION.SDK_INT >= 11) { // HC
9031e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell            result = super.drawChild(canvas, child, drawingTime);
90497341bdc5bea1d7bf777de65228039142d249f38Adam Powell        } else {
9051e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell            if (lp.dimWhenOffset && mSlideOffset > 0) {
9061e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell                if (!child.isDrawingCacheEnabled()) {
9071e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell                    child.setDrawingCacheEnabled(true);
9081e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell                }
9091e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell                final Bitmap cache = child.getDrawingCache();
9101e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell                canvas.drawBitmap(cache, child.getLeft(), child.getTop(), lp.dimPaint);
9111e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell                result = false;
9121e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell            } else {
9131e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell                if (child.isDrawingCacheEnabled()) {
9141e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell                    child.setDrawingCacheEnabled(false);
9151e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell                }
9161e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell                result = super.drawChild(canvas, child, drawingTime);
91797341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
91897341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
9191e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell
9201e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell        canvas.restoreToCount(save);
9211e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell
9221e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell        return result;
92397341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
92497341bdc5bea1d7bf777de65228039142d249f38Adam Powell
92597341bdc5bea1d7bf777de65228039142d249f38Adam Powell    private void invalidateChildRegion(View v) {
92697341bdc5bea1d7bf777de65228039142d249f38Adam Powell        IMPL.invalidateChildRegion(this, v);
92797341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
92897341bdc5bea1d7bf777de65228039142d249f38Adam Powell
92997341bdc5bea1d7bf777de65228039142d249f38Adam Powell    /**
93097341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * Smoothly animate mDraggingPane to the target X position within its range.
93197341bdc5bea1d7bf777de65228039142d249f38Adam Powell     *
93297341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * @param slideOffset position to animate to
93397341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * @param velocity initial velocity in case of fling, or 0.
93497341bdc5bea1d7bf777de65228039142d249f38Adam Powell     */
93589e17886e6149bddfdb08a242c9e88889596419cAdam Powell    boolean smoothSlideTo(float slideOffset, int velocity) {
9360eefe9ad0819b223006533cbc79a35d66684af32Adam Powell        if (!mCanSlide) {
93797341bdc5bea1d7bf777de65228039142d249f38Adam Powell            // Nothing to do.
93889e17886e6149bddfdb08a242c9e88889596419cAdam Powell            return false;
93997341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
94097341bdc5bea1d7bf777de65228039142d249f38Adam Powell
9410eefe9ad0819b223006533cbc79a35d66684af32Adam Powell        final LayoutParams lp = (LayoutParams) mSlideableView.getLayoutParams();
94297341bdc5bea1d7bf777de65228039142d249f38Adam Powell
94397341bdc5bea1d7bf777de65228039142d249f38Adam Powell        final int leftBound = getPaddingLeft() + lp.leftMargin;
9440eefe9ad0819b223006533cbc79a35d66684af32Adam Powell        int x = (int) (leftBound + slideOffset * mSlideRange);
94597341bdc5bea1d7bf777de65228039142d249f38Adam Powell
946c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        if (mDragHelper.smoothSlideViewTo(mSlideableView, x, mSlideableView.getTop())) {
947c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            setAllChildrenVisible();
948c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell            ViewCompat.postInvalidateOnAnimation(this);
94989e17886e6149bddfdb08a242c9e88889596419cAdam Powell            return true;
95097341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
95189e17886e6149bddfdb08a242c9e88889596419cAdam Powell        return false;
95297341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
95397341bdc5bea1d7bf777de65228039142d249f38Adam Powell
95497341bdc5bea1d7bf777de65228039142d249f38Adam Powell    @Override
95597341bdc5bea1d7bf777de65228039142d249f38Adam Powell    public void computeScroll() {
956c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        if (mDragHelper.continueSettling(true)) {
9570eefe9ad0819b223006533cbc79a35d66684af32Adam Powell            if (!mCanSlide) {
958c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell                mDragHelper.abort();
95997341bdc5bea1d7bf777de65228039142d249f38Adam Powell                return;
96097341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
96197341bdc5bea1d7bf777de65228039142d249f38Adam Powell
96297341bdc5bea1d7bf777de65228039142d249f38Adam Powell            ViewCompat.postInvalidateOnAnimation(this);
96397341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
96497341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
96597341bdc5bea1d7bf777de65228039142d249f38Adam Powell
966ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell    /**
967ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell     * Set a drawable to use as a shadow cast by the right pane onto the left pane
968ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell     * during opening/closing.
969ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell     *
970ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell     * @param d drawable to use as a shadow
971ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell     */
972ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell    public void setShadowDrawable(Drawable d) {
973ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell        mShadowDrawable = d;
974ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell    }
975ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell
976ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell    /**
977ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell     * Set a drawable to use as a shadow cast by the right pane onto the left pane
978ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell     * during opening/closing.
979ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell     *
980ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell     * @param resId Resource ID of a drawable to use
981ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell     */
982ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell    public void setShadowResource(int resId) {
983ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell        setShadowDrawable(getResources().getDrawable(resId));
984ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell    }
985ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell
986ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell    @Override
987ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell    public void draw(Canvas c) {
988ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell        super.draw(c);
989ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell
9901e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell        final View shadowView = getChildCount() > 1 ? getChildAt(1) : null;
9911e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell        if (shadowView == null || mShadowDrawable == null) {
9923783c4b814bf70711fc4d674e9c7fbc34b1e5a83Adam Powell            // No need to draw a shadow if we don't have one.
993ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell            return;
994ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell        }
995ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell
996ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell        final int shadowWidth = mShadowDrawable.getIntrinsicWidth();
9971e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell        final int right = shadowView.getLeft();
9981e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell        final int top = shadowView.getTop();
9991e43161e9e1f1dc10637a68d5c2304c1f95c9c46Adam Powell        final int bottom = shadowView.getBottom();
1000ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell        final int left = right - shadowWidth;
1001ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell        mShadowDrawable.setBounds(left, top, right, bottom);
1002ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell        mShadowDrawable.draw(c);
1003ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell    }
1004ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell
10056debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell    private void parallaxOtherViews(float slideOffset) {
1006ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell        final LayoutParams slideLp = (LayoutParams) mSlideableView.getLayoutParams();
1007ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell        final boolean dimViews = slideLp.dimWhenOffset && slideLp.leftMargin <= 0;
10086debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell        final int childCount = getChildCount();
10096debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell        for (int i = 0; i < childCount; i++) {
10106debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell            final View v = getChildAt(i);
10110eefe9ad0819b223006533cbc79a35d66684af32Adam Powell            if (v == mSlideableView) continue;
10126debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell
10130eefe9ad0819b223006533cbc79a35d66684af32Adam Powell            final int oldOffset = (int) ((1 - mParallaxOffset) * mParallaxBy);
10140eefe9ad0819b223006533cbc79a35d66684af32Adam Powell            mParallaxOffset = slideOffset;
10156debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell            final int newOffset = (int) ((1 - slideOffset) * mParallaxBy);
1016ad9696cf0da9b65c4a52f00fe5adaa17b99a05caAdam Powell            final int dx = oldOffset - newOffset;
1017ad9696cf0da9b65c4a52f00fe5adaa17b99a05caAdam Powell
1018ad9696cf0da9b65c4a52f00fe5adaa17b99a05caAdam Powell            v.offsetLeftAndRight(dx);
1019ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell
1020ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell            if (dimViews) {
102181e2f002d1b4ebf2d951eb9f239858b8a9481a24Adam Powell                dimChildView(v, 1 - mParallaxOffset, mCoveredFadeColor);
1022ee3f0ffb0199e295cbf48aa1a61c8ae7056526abAdam Powell            }
10236debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell        }
10246debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell    }
10256debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell
102697341bdc5bea1d7bf777de65228039142d249f38Adam Powell    /**
102797341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * Tests scrollability within child views of v given a delta of dx.
102897341bdc5bea1d7bf777de65228039142d249f38Adam Powell     *
102997341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * @param v View to test for horizontal scrollability
103097341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * @param checkV Whether the view v passed should itself be checked for scrollability (true),
103197341bdc5bea1d7bf777de65228039142d249f38Adam Powell     *               or just its children (false).
103297341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * @param dx Delta scrolled in pixels
103397341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * @param x X coordinate of the active touch point
103497341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * @param y Y coordinate of the active touch point
103597341bdc5bea1d7bf777de65228039142d249f38Adam Powell     * @return true if child views of v can be scrolled by delta of dx.
103697341bdc5bea1d7bf777de65228039142d249f38Adam Powell     */
103797341bdc5bea1d7bf777de65228039142d249f38Adam Powell    protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
103897341bdc5bea1d7bf777de65228039142d249f38Adam Powell        if (v instanceof ViewGroup) {
103997341bdc5bea1d7bf777de65228039142d249f38Adam Powell            final ViewGroup group = (ViewGroup) v;
104097341bdc5bea1d7bf777de65228039142d249f38Adam Powell            final int scrollX = v.getScrollX();
104197341bdc5bea1d7bf777de65228039142d249f38Adam Powell            final int scrollY = v.getScrollY();
104297341bdc5bea1d7bf777de65228039142d249f38Adam Powell            final int count = group.getChildCount();
104397341bdc5bea1d7bf777de65228039142d249f38Adam Powell            // Count backwards - let topmost views consume scroll distance first.
104497341bdc5bea1d7bf777de65228039142d249f38Adam Powell            for (int i = count - 1; i >= 0; i--) {
104597341bdc5bea1d7bf777de65228039142d249f38Adam Powell                // TODO: Add versioned support here for transformed views.
104697341bdc5bea1d7bf777de65228039142d249f38Adam Powell                // This will not work for transformed views in Honeycomb+
104797341bdc5bea1d7bf777de65228039142d249f38Adam Powell                final View child = group.getChildAt(i);
104897341bdc5bea1d7bf777de65228039142d249f38Adam Powell                if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() &&
104997341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        y + scrollY >= child.getTop() && y + scrollY < child.getBottom() &&
105097341bdc5bea1d7bf777de65228039142d249f38Adam Powell                        canScroll(child, true, dx, x + scrollX - child.getLeft(),
105197341bdc5bea1d7bf777de65228039142d249f38Adam Powell                                y + scrollY - child.getTop())) {
105297341bdc5bea1d7bf777de65228039142d249f38Adam Powell                    return true;
105397341bdc5bea1d7bf777de65228039142d249f38Adam Powell                }
105497341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
105597341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
105697341bdc5bea1d7bf777de65228039142d249f38Adam Powell
105797341bdc5bea1d7bf777de65228039142d249f38Adam Powell        return checkV && ViewCompat.canScrollHorizontally(v, -dx);
105897341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
105997341bdc5bea1d7bf777de65228039142d249f38Adam Powell
10600eefe9ad0819b223006533cbc79a35d66684af32Adam Powell    boolean isDimmed(View child) {
10610eefe9ad0819b223006533cbc79a35d66684af32Adam Powell        if (child == null) {
10620eefe9ad0819b223006533cbc79a35d66684af32Adam Powell            return false;
10630eefe9ad0819b223006533cbc79a35d66684af32Adam Powell        }
106497341bdc5bea1d7bf777de65228039142d249f38Adam Powell        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
10650eefe9ad0819b223006533cbc79a35d66684af32Adam Powell        return mCanSlide && lp.dimWhenOffset && mSlideOffset > 0;
106697341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
106797341bdc5bea1d7bf777de65228039142d249f38Adam Powell
106897341bdc5bea1d7bf777de65228039142d249f38Adam Powell    @Override
106997341bdc5bea1d7bf777de65228039142d249f38Adam Powell    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
107097341bdc5bea1d7bf777de65228039142d249f38Adam Powell        return new LayoutParams();
107197341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
107297341bdc5bea1d7bf777de65228039142d249f38Adam Powell
107397341bdc5bea1d7bf777de65228039142d249f38Adam Powell    @Override
107497341bdc5bea1d7bf777de65228039142d249f38Adam Powell    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
107597341bdc5bea1d7bf777de65228039142d249f38Adam Powell        return p instanceof MarginLayoutParams
107697341bdc5bea1d7bf777de65228039142d249f38Adam Powell                ? new LayoutParams((MarginLayoutParams) p)
107797341bdc5bea1d7bf777de65228039142d249f38Adam Powell                : new LayoutParams(p);
107897341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
107997341bdc5bea1d7bf777de65228039142d249f38Adam Powell
108097341bdc5bea1d7bf777de65228039142d249f38Adam Powell    @Override
108197341bdc5bea1d7bf777de65228039142d249f38Adam Powell    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
108297341bdc5bea1d7bf777de65228039142d249f38Adam Powell        return p instanceof LayoutParams && super.checkLayoutParams(p);
108397341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
108497341bdc5bea1d7bf777de65228039142d249f38Adam Powell
108597341bdc5bea1d7bf777de65228039142d249f38Adam Powell    @Override
108697341bdc5bea1d7bf777de65228039142d249f38Adam Powell    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
108797341bdc5bea1d7bf777de65228039142d249f38Adam Powell        return new LayoutParams(getContext(), attrs);
108897341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
108997341bdc5bea1d7bf777de65228039142d249f38Adam Powell
10901d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
10911d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected Parcelable onSaveInstanceState() {
10921d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        Parcelable superState = super.onSaveInstanceState();
10931d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10941d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        SavedState ss = new SavedState(superState);
109589e17886e6149bddfdb08a242c9e88889596419cAdam Powell        ss.isOpen = isSlideable() ? isOpen() : mPreservedOpenState;
10961d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
10971d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        return ss;
10981d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
10991d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
11001d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    @Override
11011d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    protected void onRestoreInstanceState(Parcelable state) {
11021d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        SavedState ss = (SavedState) state;
11031d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        super.onRestoreInstanceState(ss.getSuperState());
11041d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
110589e17886e6149bddfdb08a242c9e88889596419cAdam Powell        if (ss.isOpen) {
110689e17886e6149bddfdb08a242c9e88889596419cAdam Powell            openPane();
110789e17886e6149bddfdb08a242c9e88889596419cAdam Powell        } else {
110889e17886e6149bddfdb08a242c9e88889596419cAdam Powell            closePane();
110989e17886e6149bddfdb08a242c9e88889596419cAdam Powell        }
111089e17886e6149bddfdb08a242c9e88889596419cAdam Powell        mPreservedOpenState = ss.isOpen;
11111d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell    }
11121d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell
1113c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell    private class DragHelperCallback extends ViewDragHelper.Callback {
1114c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell
1115c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        @Override
1116c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        public boolean tryCaptureView(View child, int pointerId) {
1117c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell            if (mIsUnableToDrag) {
1118c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell                return false;
1119c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell            }
1120c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell
1121c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell            return ((LayoutParams) child.getLayoutParams()).slideable;
1122c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        }
1123c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell
1124c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        @Override
1125c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        public void onViewDragStateChanged(int state) {
1126471f0f4e84c7d1f96e48fb26713f246d69c3241fAdam Powell            if (mDragHelper.getViewDragState() == ViewDragHelper.STATE_IDLE) {
11276580cf4b7e74a2a017ed95b0dc50155b9995edebAdam Powell                if (mSlideOffset == 0) {
1128c89f53833f1e272d32f7928837f0704fa33be309Adam Powell                    updateObscuredViewsVisibility(mSlideableView);
11296580cf4b7e74a2a017ed95b0dc50155b9995edebAdam Powell                    dispatchOnPanelClosed(mSlideableView);
113072c7316b081c3134f7b0566f703dfee7c970eadeAdam Powell                    mPreservedOpenState = false;
11316580cf4b7e74a2a017ed95b0dc50155b9995edebAdam Powell                } else {
11326580cf4b7e74a2a017ed95b0dc50155b9995edebAdam Powell                    dispatchOnPanelOpened(mSlideableView);
113372c7316b081c3134f7b0566f703dfee7c970eadeAdam Powell                    mPreservedOpenState = true;
11346580cf4b7e74a2a017ed95b0dc50155b9995edebAdam Powell                }
1135c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell            }
1136c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        }
1137c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell
1138c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        @Override
1139c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        public void onViewCaptured(View capturedChild, int activePointerId) {
1140c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            // Make all child views visible in preparation for sliding things around
1141c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            setAllChildrenVisible();
1142c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        }
1143c89f53833f1e272d32f7928837f0704fa33be309Adam Powell
1144c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        @Override
11451d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
1146d44315a54e002b20365189f03a09011f2bf6ba07Adam Powell            onPanelDragged(left);
1147c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell            invalidate();
1148c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        }
1149c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell
1150c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        @Override
1151c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        public void onViewReleased(View releasedChild, float xvel, float yvel) {
1152c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell            final LayoutParams lp = (LayoutParams) releasedChild.getLayoutParams();
1153c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell            int left = getPaddingLeft() + lp.leftMargin;
1154c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell            if (xvel > 0 || (xvel == 0 && mSlideOffset > 0.5f)) {
1155c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell                left += mSlideRange;
1156c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell            }
1157c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell            mDragHelper.settleCapturedViewAt(left, releasedChild.getTop());
1158c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell            invalidate();
1159c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        }
1160c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell
1161c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        @Override
1162c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        public int getViewHorizontalDragRange(View child) {
1163c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell            return mSlideRange;
1164c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        }
1165c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell
1166c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        @Override
11671d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell        public int clampViewPositionHorizontal(View child, int left, int dx) {
1168c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell            final LayoutParams lp = (LayoutParams) mSlideableView.getLayoutParams();
1169c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell            final int leftBound = getPaddingLeft() + lp.leftMargin;
1170c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell            final int rightBound = leftBound + mSlideRange;
1171c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell
11721d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            final int newLeft = Math.min(Math.max(left, leftBound), rightBound);
1173c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell
11741d26501f0c8e9f3577f651938a03f6b3a1a672c7Adam Powell            return newLeft;
1175c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        }
1176c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell
1177c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        @Override
1178c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        public void onEdgeDragStarted(int edgeFlags, int pointerId) {
1179c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell            mDragHelper.captureChildView(mSlideableView, pointerId);
1180c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell        }
1181c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell    }
1182c56ba65d20be8742ff717907a3a2cd81dd0e5f3cAdam Powell
118397341bdc5bea1d7bf777de65228039142d249f38Adam Powell    public static class LayoutParams extends ViewGroup.MarginLayoutParams {
118497341bdc5bea1d7bf777de65228039142d249f38Adam Powell        private static final int[] ATTRS = new int[] {
118597341bdc5bea1d7bf777de65228039142d249f38Adam Powell            android.R.attr.layout_weight
118697341bdc5bea1d7bf777de65228039142d249f38Adam Powell        };
118797341bdc5bea1d7bf777de65228039142d249f38Adam Powell
11886debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell        /**
11896debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell         * The weighted proportion of how much of the leftover space
11906debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell         * this child should consume after measurement.
11916debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell         */
119297341bdc5bea1d7bf777de65228039142d249f38Adam Powell        public float weight = 0;
119397341bdc5bea1d7bf777de65228039142d249f38Adam Powell
119497341bdc5bea1d7bf777de65228039142d249f38Adam Powell        /**
11950eefe9ad0819b223006533cbc79a35d66684af32Adam Powell         * True if this pane is the slideable pane in the layout.
119697341bdc5bea1d7bf777de65228039142d249f38Adam Powell         */
11970eefe9ad0819b223006533cbc79a35d66684af32Adam Powell        boolean slideable;
119897341bdc5bea1d7bf777de65228039142d249f38Adam Powell
119997341bdc5bea1d7bf777de65228039142d249f38Adam Powell        /**
120097341bdc5bea1d7bf777de65228039142d249f38Adam Powell         * True if this view should be drawn dimmed
120197341bdc5bea1d7bf777de65228039142d249f38Adam Powell         * when it's been offset from its default position.
120297341bdc5bea1d7bf777de65228039142d249f38Adam Powell         */
120397341bdc5bea1d7bf777de65228039142d249f38Adam Powell        boolean dimWhenOffset;
120497341bdc5bea1d7bf777de65228039142d249f38Adam Powell
120597341bdc5bea1d7bf777de65228039142d249f38Adam Powell        Paint dimPaint;
120697341bdc5bea1d7bf777de65228039142d249f38Adam Powell
120797341bdc5bea1d7bf777de65228039142d249f38Adam Powell        public LayoutParams() {
120897341bdc5bea1d7bf777de65228039142d249f38Adam Powell            super(FILL_PARENT, FILL_PARENT);
120997341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
121097341bdc5bea1d7bf777de65228039142d249f38Adam Powell
121197341bdc5bea1d7bf777de65228039142d249f38Adam Powell        public LayoutParams(int width, int height) {
121297341bdc5bea1d7bf777de65228039142d249f38Adam Powell            super(width, height);
121397341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
121497341bdc5bea1d7bf777de65228039142d249f38Adam Powell
121597341bdc5bea1d7bf777de65228039142d249f38Adam Powell        public LayoutParams(android.view.ViewGroup.LayoutParams source) {
121697341bdc5bea1d7bf777de65228039142d249f38Adam Powell            super(source);
121797341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
121897341bdc5bea1d7bf777de65228039142d249f38Adam Powell
121997341bdc5bea1d7bf777de65228039142d249f38Adam Powell        public LayoutParams(MarginLayoutParams source) {
122097341bdc5bea1d7bf777de65228039142d249f38Adam Powell            super(source);
122197341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
122297341bdc5bea1d7bf777de65228039142d249f38Adam Powell
122397341bdc5bea1d7bf777de65228039142d249f38Adam Powell        public LayoutParams(LayoutParams source) {
122497341bdc5bea1d7bf777de65228039142d249f38Adam Powell            super(source);
122597341bdc5bea1d7bf777de65228039142d249f38Adam Powell            this.weight = source.weight;
122697341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
122797341bdc5bea1d7bf777de65228039142d249f38Adam Powell
122897341bdc5bea1d7bf777de65228039142d249f38Adam Powell        public LayoutParams(Context c, AttributeSet attrs) {
122997341bdc5bea1d7bf777de65228039142d249f38Adam Powell            super(c, attrs);
123097341bdc5bea1d7bf777de65228039142d249f38Adam Powell
123197341bdc5bea1d7bf777de65228039142d249f38Adam Powell            final TypedArray a = c.obtainStyledAttributes(attrs, ATTRS);
12320eefe9ad0819b223006533cbc79a35d66684af32Adam Powell            this.weight = a.getFloat(0, 0);
123397341bdc5bea1d7bf777de65228039142d249f38Adam Powell            a.recycle();
123497341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
123597341bdc5bea1d7bf777de65228039142d249f38Adam Powell
123697341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
123797341bdc5bea1d7bf777de65228039142d249f38Adam Powell
123897341bdc5bea1d7bf777de65228039142d249f38Adam Powell    static class SavedState extends BaseSavedState {
123997341bdc5bea1d7bf777de65228039142d249f38Adam Powell        boolean isOpen;
124097341bdc5bea1d7bf777de65228039142d249f38Adam Powell
124197341bdc5bea1d7bf777de65228039142d249f38Adam Powell        SavedState(Parcelable superState) {
124297341bdc5bea1d7bf777de65228039142d249f38Adam Powell            super(superState);
124397341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
124497341bdc5bea1d7bf777de65228039142d249f38Adam Powell
124597341bdc5bea1d7bf777de65228039142d249f38Adam Powell        private SavedState(Parcel in) {
124697341bdc5bea1d7bf777de65228039142d249f38Adam Powell            super(in);
124797341bdc5bea1d7bf777de65228039142d249f38Adam Powell            isOpen = in.readInt() != 0;
124897341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
124997341bdc5bea1d7bf777de65228039142d249f38Adam Powell
125097341bdc5bea1d7bf777de65228039142d249f38Adam Powell        @Override
125197341bdc5bea1d7bf777de65228039142d249f38Adam Powell        public void writeToParcel(Parcel out, int flags) {
125297341bdc5bea1d7bf777de65228039142d249f38Adam Powell            super.writeToParcel(out, flags);
125397341bdc5bea1d7bf777de65228039142d249f38Adam Powell            out.writeInt(isOpen ? 1 : 0);
125497341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
125597341bdc5bea1d7bf777de65228039142d249f38Adam Powell
125697341bdc5bea1d7bf777de65228039142d249f38Adam Powell        public static final Parcelable.Creator<SavedState> CREATOR =
125797341bdc5bea1d7bf777de65228039142d249f38Adam Powell                new Parcelable.Creator<SavedState>() {
125897341bdc5bea1d7bf777de65228039142d249f38Adam Powell            public SavedState createFromParcel(Parcel in) {
125997341bdc5bea1d7bf777de65228039142d249f38Adam Powell                return new SavedState(in);
126097341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
126197341bdc5bea1d7bf777de65228039142d249f38Adam Powell
126297341bdc5bea1d7bf777de65228039142d249f38Adam Powell            public SavedState[] newArray(int size) {
126397341bdc5bea1d7bf777de65228039142d249f38Adam Powell                return new SavedState[size];
126497341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
126597341bdc5bea1d7bf777de65228039142d249f38Adam Powell        };
126697341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
126797341bdc5bea1d7bf777de65228039142d249f38Adam Powell
126897341bdc5bea1d7bf777de65228039142d249f38Adam Powell    interface SlidingPanelLayoutImpl {
126997341bdc5bea1d7bf777de65228039142d249f38Adam Powell        void invalidateChildRegion(SlidingPaneLayout parent, View child);
127097341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
127197341bdc5bea1d7bf777de65228039142d249f38Adam Powell
127297341bdc5bea1d7bf777de65228039142d249f38Adam Powell    static class SlidingPanelLayoutImplBase implements SlidingPanelLayoutImpl {
127397341bdc5bea1d7bf777de65228039142d249f38Adam Powell        public void invalidateChildRegion(SlidingPaneLayout parent, View child) {
127497341bdc5bea1d7bf777de65228039142d249f38Adam Powell            ViewCompat.postInvalidateOnAnimation(parent, child.getLeft(), child.getTop(),
127597341bdc5bea1d7bf777de65228039142d249f38Adam Powell                    child.getRight(), child.getBottom());
127697341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
127797341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
127897341bdc5bea1d7bf777de65228039142d249f38Adam Powell
127997341bdc5bea1d7bf777de65228039142d249f38Adam Powell    static class SlidingPanelLayoutImplJB extends SlidingPanelLayoutImplBase {
128097341bdc5bea1d7bf777de65228039142d249f38Adam Powell        /*
128197341bdc5bea1d7bf777de65228039142d249f38Adam Powell         * Private API hacks! Nasty! Bad!
128297341bdc5bea1d7bf777de65228039142d249f38Adam Powell         *
128397341bdc5bea1d7bf777de65228039142d249f38Adam Powell         * In Jellybean, some optimizations in the hardware UI renderer
128497341bdc5bea1d7bf777de65228039142d249f38Adam Powell         * prevent a changed Paint on a View using a hardware layer from having
128597341bdc5bea1d7bf777de65228039142d249f38Adam Powell         * the intended effect. This twiddles some internal bits on the view to force
128697341bdc5bea1d7bf777de65228039142d249f38Adam Powell         * it to recreate the display list.
128797341bdc5bea1d7bf777de65228039142d249f38Adam Powell         */
128897341bdc5bea1d7bf777de65228039142d249f38Adam Powell        private Method mGetDisplayList;
128997341bdc5bea1d7bf777de65228039142d249f38Adam Powell        private Field mRecreateDisplayList;
129097341bdc5bea1d7bf777de65228039142d249f38Adam Powell
129197341bdc5bea1d7bf777de65228039142d249f38Adam Powell        SlidingPanelLayoutImplJB() {
129297341bdc5bea1d7bf777de65228039142d249f38Adam Powell            try {
129397341bdc5bea1d7bf777de65228039142d249f38Adam Powell                mGetDisplayList = View.class.getDeclaredMethod("getDisplayList", (Class[]) null);
129497341bdc5bea1d7bf777de65228039142d249f38Adam Powell            } catch (NoSuchMethodException e) {
129597341bdc5bea1d7bf777de65228039142d249f38Adam Powell                Log.e(TAG, "Couldn't fetch getDisplayList method; dimming won't work right.", e);
129697341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
129797341bdc5bea1d7bf777de65228039142d249f38Adam Powell            try {
129897341bdc5bea1d7bf777de65228039142d249f38Adam Powell                mRecreateDisplayList = View.class.getDeclaredField("mRecreateDisplayList");
129997341bdc5bea1d7bf777de65228039142d249f38Adam Powell                mRecreateDisplayList.setAccessible(true);
130097341bdc5bea1d7bf777de65228039142d249f38Adam Powell            } catch (NoSuchFieldException e) {
130197341bdc5bea1d7bf777de65228039142d249f38Adam Powell                Log.e(TAG, "Couldn't fetch mRecreateDisplayList field; dimming will be slow.", e);
130297341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
130397341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
130497341bdc5bea1d7bf777de65228039142d249f38Adam Powell
130597341bdc5bea1d7bf777de65228039142d249f38Adam Powell        @Override
130697341bdc5bea1d7bf777de65228039142d249f38Adam Powell        public void invalidateChildRegion(SlidingPaneLayout parent, View child) {
130797341bdc5bea1d7bf777de65228039142d249f38Adam Powell            if (mGetDisplayList != null && mRecreateDisplayList != null) {
130897341bdc5bea1d7bf777de65228039142d249f38Adam Powell                try {
130997341bdc5bea1d7bf777de65228039142d249f38Adam Powell                    mRecreateDisplayList.setBoolean(child, true);
131097341bdc5bea1d7bf777de65228039142d249f38Adam Powell                    mGetDisplayList.invoke(child, (Object[]) null);
131197341bdc5bea1d7bf777de65228039142d249f38Adam Powell                } catch (Exception e) {
131297341bdc5bea1d7bf777de65228039142d249f38Adam Powell                    Log.e(TAG, "Error refreshing display list state", e);
131397341bdc5bea1d7bf777de65228039142d249f38Adam Powell                }
131497341bdc5bea1d7bf777de65228039142d249f38Adam Powell            } else {
131597341bdc5bea1d7bf777de65228039142d249f38Adam Powell                // Slow path. REALLY slow path. Let's hope we don't get here.
131697341bdc5bea1d7bf777de65228039142d249f38Adam Powell                child.invalidate();
131797341bdc5bea1d7bf777de65228039142d249f38Adam Powell                return;
131897341bdc5bea1d7bf777de65228039142d249f38Adam Powell            }
131997341bdc5bea1d7bf777de65228039142d249f38Adam Powell            super.invalidateChildRegion(parent, child);
132097341bdc5bea1d7bf777de65228039142d249f38Adam Powell        }
132197341bdc5bea1d7bf777de65228039142d249f38Adam Powell    }
13226debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell
13236debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell    static class SlidingPanelLayoutImplJBMR1 extends SlidingPanelLayoutImplBase {
13246debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell        @Override
13256debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell        public void invalidateChildRegion(SlidingPaneLayout parent, View child) {
13266debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell            ViewCompat.setLayerPaint(child, ((LayoutParams) child.getLayoutParams()).dimPaint);
13276debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell        }
13286debd2bbcae1cd285d2e21db633998b7801f9f40Adam Powell    }
1329c89f53833f1e272d32f7928837f0704fa33be309Adam Powell
1330c89f53833f1e272d32f7928837f0704fa33be309Adam Powell    class AccessibilityDelegate extends AccessibilityDelegateCompat {
1331c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        @Override
1332c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
1333c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            final int childCount = getChildCount();
1334c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            for (int i = 0; i < childCount; i++) {
1335c89f53833f1e272d32f7928837f0704fa33be309Adam Powell                final View child = getChildAt(i);
1336c89f53833f1e272d32f7928837f0704fa33be309Adam Powell                if (!filter(child)) {
1337c89f53833f1e272d32f7928837f0704fa33be309Adam Powell                    info.addChild(child);
1338c89f53833f1e272d32f7928837f0704fa33be309Adam Powell                }
1339c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            }
1340c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        }
1341c89f53833f1e272d32f7928837f0704fa33be309Adam Powell
1342c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        @Override
1343c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
1344c89f53833f1e272d32f7928837f0704fa33be309Adam Powell                AccessibilityEvent event) {
1345c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            if (!filter(child)) {
1346c89f53833f1e272d32f7928837f0704fa33be309Adam Powell                return super.onRequestSendAccessibilityEvent(host, child, event);
1347c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            }
1348c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            return false;
1349c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        }
1350c89f53833f1e272d32f7928837f0704fa33be309Adam Powell
1351c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        public boolean filter(View child) {
1352c89f53833f1e272d32f7928837f0704fa33be309Adam Powell            return isDimmed(child);
1353c89f53833f1e272d32f7928837f0704fa33be309Adam Powell        }
1354c89f53833f1e272d32f7928837f0704fa33be309Adam Powell    }
135597341bdc5bea1d7bf777de65228039142d249f38Adam Powell}
1356