OverlappingPaneLayout.java revision 40ed60dab29e90e28f95a0d8a9c612fed7a253ce
1e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee/*
2e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * Copyright (C) 2012 The Android Open Source Project
3e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee *
4e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * Licensed under the Apache License, Version 2.0 (the "License");
5e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * you may not use this file except in compliance with the License.
6e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * You may obtain a copy of the License at
7e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee *
8e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee *      http://www.apache.org/licenses/LICENSE-2.0
9e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee *
10e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * Unless required by applicable law or agreed to in writing, software
11e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * distributed under the License is distributed on an "AS IS" BASIS,
12e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * See the License for the specific language governing permissions and
14e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * limitations under the License.
15e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */
16e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
17e709fd21eda44df07327f649e4e6a257918555a9Yorke Leepackage com.android.dialer.widget;
18e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
19e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.content.Context;
20e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.content.res.TypedArray;
21e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.graphics.Canvas;
22e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.graphics.PixelFormat;
23e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.graphics.Rect;
24e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.graphics.drawable.Drawable;
25e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.os.Build;
26e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.os.Parcel;
27e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.os.Parcelable;
28e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.support.v4.view.AccessibilityDelegateCompat;
29e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.support.v4.view.MotionEventCompat;
30e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.support.v4.view.ViewCompat;
31e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
32e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.util.AttributeSet;
33e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.util.Log;
34e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.view.MotionEvent;
35e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.view.View;
36e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.view.ViewGroup;
37e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.view.ViewParent;
38e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.view.accessibility.AccessibilityEvent;
39e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
40e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee/**
41e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * A custom layout that aligns its child views vertically as two panes, and allows for the bottom
42e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * pane to be dragged upwards to overlap and hide the top pane. This layout is adapted from
43e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * {@link android.support.v4.widget.SlidingPaneLayout}.
44e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */
45e709fd21eda44df07327f649e4e6a257918555a9Yorke Leepublic class OverlappingPaneLayout extends ViewGroup {
46e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private static final String TAG = "SlidingPaneLayout";
475c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee    private static final boolean DEBUG = false;
48e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
49e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    /**
50e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * Default size of the overhang for a pane in the open state.
51e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * At least this much of a sliding pane will remain visible.
52e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * This indicates that there is more content available and provides
53e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * a "physical" edge to grab to pull it closed.
54e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     */
55e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private static final int DEFAULT_OVERHANG_SIZE = 32; // dp;
56e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
57e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    /**
58e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * If no fade color is given by default it will fade to 80% gray.
59e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     */
60e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private static final int DEFAULT_FADE_COLOR = 0xcccccccc;
61e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
62e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    /**
63e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * Minimum velocity that will be detected as a fling
64e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     */
65e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private static final int MIN_FLING_VELOCITY = 400; // dips per second
66e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
67e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    /**
68e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * The size of the overhang in pixels.
69e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * This is the minimum section of the sliding panel that will
70e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * be visible in the open state to allow for a closing drag.
71e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     */
72e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private final int mOverhangSize;
73e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
74e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    /**
75e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * True if a panel can slide with the current measurements
76e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     */
77e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private boolean mCanSlide;
78e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
79e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    /**
80e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * The child view that can slide, if any.
81e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     */
82e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private View mSlideableView;
83e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
84e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    /**
85e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * The view that can be used to start the drag with.
86e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     */
87e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private View mCapturableView;
88e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
89e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    /**
90e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * How far the panel is offset from its closed position.
91e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * range [0, 1] where 0 = closed, 1 = open.
92e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     */
93e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private float mSlideOffset;
94e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
95e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    /**
965c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee     * How far the panel is offset from its closed position, in pixels.
975c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee     * range [0, {@link #mSlideRange}] where 0 is completely closed.
985c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee     */
995c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee    private int mSlideOffsetPx;
1005c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee
1015c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee    /**
102e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * How far in pixels the slideable panel may move.
103e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     */
104e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private int mSlideRange;
105e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
106e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    /**
107e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * A panel view is locked into internal scrolling or another condition that
108e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * is preventing a drag.
109e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     */
110e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private boolean mIsUnableToDrag;
111e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
112bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee    /**
113bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee     * Tracks whether or not a child view is in the process of a nested scroll.
114bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee     */
115bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee    private boolean mIsInNestedScroll;
116bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee
1175c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee    /**
1185c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee     * Indicates that the layout is currently in the process of a nested pre-scroll operation where
11940ed60dab29e90e28f95a0d8a9c612fed7a253ceYorke Lee     * the child scrolling view is being dragged downwards, and still has the ability to consume
12040ed60dab29e90e28f95a0d8a9c612fed7a253ceYorke Lee     * scroll events itself. If so, we should open the pane up to the maximum offset defined in
12140ed60dab29e90e28f95a0d8a9c612fed7a253ceYorke Lee     * {@link #mIntermediateOffset}, and no further, so that the child view can continue performing
12240ed60dab29e90e28f95a0d8a9c612fed7a253ceYorke Lee     * its own scroll.
1235c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee     */
12440ed60dab29e90e28f95a0d8a9c612fed7a253ceYorke Lee    private boolean mInNestedPreScrollDownwards = false;
12540ed60dab29e90e28f95a0d8a9c612fed7a253ceYorke Lee
12640ed60dab29e90e28f95a0d8a9c612fed7a253ceYorke Lee    /**
12740ed60dab29e90e28f95a0d8a9c612fed7a253ceYorke Lee     * Indicates whether or not a nested scrolling child is able to scroll internally at this point
12840ed60dab29e90e28f95a0d8a9c612fed7a253ceYorke Lee     * in time.
12940ed60dab29e90e28f95a0d8a9c612fed7a253ceYorke Lee     */
13040ed60dab29e90e28f95a0d8a9c612fed7a253ceYorke Lee    private boolean mChildCannotConsumeScroll;
1315c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee
1325c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee    /**
1335c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee     * Stores an offset used to represent a point somewhere in between the panel's fully closed
1345c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee     * state and fully opened state where the panel can be temporarily pinned or opened up to
1355c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee     * during scrolling.
1365c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee     */
1375c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee    private int mIntermediateOffset = 0;
1385c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee
139e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private float mInitialMotionX;
140e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private float mInitialMotionY;
141e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
142e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private PanelSlideListener mPanelSlideListener;
143e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
144e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private final ViewDragHelper mDragHelper;
145e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
146e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    /**
147e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * Stores whether or not the pane was open the last time it was slideable.
148e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * If open/close operations are invoked this state is modified. Used by
149e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * instance state save/restore.
150e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     */
151e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private boolean mPreservedOpenState;
152e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private boolean mFirstLayout = true;
153e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
154e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private final Rect mTmpRect = new Rect();
155e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
156e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    /**
157e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * Listener for monitoring events about sliding panes.
158e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     */
159e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    public interface PanelSlideListener {
160e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        /**
161e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         * Called when a sliding pane's position changes.
162e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         * @param panel The child view that was moved
163e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         * @param slideOffset The new offset of this sliding pane within its range, from 0-1
164e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         */
165e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public void onPanelSlide(View panel, float slideOffset);
166e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        /**
167e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         * Called when a sliding pane becomes slid completely open. The pane may or may not
168e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         * be interactive at this point depending on how much of the pane is visible.
169e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         * @param panel The child view that was slid to an open position, revealing other panes
170e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         */
171e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public void onPanelOpened(View panel);
172e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
173e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        /**
174e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         * Called when a sliding pane becomes slid completely closed. The pane is now guaranteed
175e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         * to be interactive. It may now obscure other views in the layout.
176e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         * @param panel The child view that was slid to a closed position
177e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         */
178e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public void onPanelClosed(View panel);
179e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
180e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
181e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    public OverlappingPaneLayout(Context context) {
182e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        this(context, null);
183e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
184e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
185e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    public OverlappingPaneLayout(Context context, AttributeSet attrs) {
186e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        this(context, attrs, 0);
187e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
188e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
189e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    public OverlappingPaneLayout(Context context, AttributeSet attrs, int defStyle) {
190e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        super(context, attrs, defStyle);
191e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
192e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final float density = context.getResources().getDisplayMetrics().density;
193e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        mOverhangSize = (int) (DEFAULT_OVERHANG_SIZE * density + 0.5f);
194e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
195e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        setWillNotDraw(false);
196e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
197e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        ViewCompat.setAccessibilityDelegate(this, new AccessibilityDelegate());
198e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        ViewCompat.setImportantForAccessibility(this, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
199e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
200e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        mDragHelper = ViewDragHelper.create(this, 0.5f, new DragHelperCallback());
201e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        mDragHelper.setMinVelocity(MIN_FLING_VELOCITY * density);
202e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
203e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
204e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    /**
2055c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee     * Set an offset, somewhere in between the panel's fully closed state and fully opened state,
2065c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee     * where the panel can be temporarily pinned or opened up to.
2075c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee     *
2085c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee     * @param offset Offset in pixels
2095c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee     */
2105c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee    public void setIntermediatePinnedOffset(int offset) {
2115c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        mIntermediateOffset = offset;
2125c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee    }
2135c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee
2145c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee    /**
215e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * Set the view that can be used to start dragging the sliding pane.
216e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     */
217e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    public void setCapturableView(View capturableView) {
218e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        mCapturableView = capturableView;
219e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
220e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
221e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    public void setPanelSlideListener(PanelSlideListener listener) {
222e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        mPanelSlideListener = listener;
223e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
224e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
225e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    void dispatchOnPanelSlide(View panel) {
226e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (mPanelSlideListener != null) {
227e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            mPanelSlideListener.onPanelSlide(panel, mSlideOffset);
228e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
229e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
230e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
231e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    void dispatchOnPanelOpened(View panel) {
232e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (mPanelSlideListener != null) {
233e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            mPanelSlideListener.onPanelOpened(panel);
234e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
235e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
236e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
237e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
238e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    void dispatchOnPanelClosed(View panel) {
239e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (mPanelSlideListener != null) {
240e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            mPanelSlideListener.onPanelClosed(panel);
241e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
242e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
243e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
244e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
245e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    void updateObscuredViewsVisibility(View panel) {
246e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int startBound = getPaddingTop();
247e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int endBound = getHeight() - getPaddingBottom();
248e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
249e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int leftBound = getPaddingLeft();
250e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int rightBound = getWidth() - getPaddingRight();
251e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int left;
252e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int right;
253e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int top;
254e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int bottom;
255e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (panel != null && viewIsOpaque(panel)) {
256e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            left = panel.getLeft();
257e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            right = panel.getRight();
258e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            top = panel.getTop();
259e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            bottom = panel.getBottom();
260e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        } else {
261e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            left = right = top = bottom = 0;
262e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
263e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
264e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        for (int i = 0, childCount = getChildCount(); i < childCount; i++) {
265e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final View child = getChildAt(i);
266e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
267e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            if (child == panel) {
268e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                // There are still more children above the panel but they won't be affected.
269e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                break;
270e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
271e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
272e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final int clampedChildLeft = Math.max(leftBound, child.getLeft());
273e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final int clampedChildRight = Math.min(rightBound, child.getRight());
274e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final int clampedChildTop = Math.max(startBound, child.getTop());
275e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final int clampedChildBottom = Math.min(endBound, child.getBottom());
276e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
277e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final int vis;
278e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            if (clampedChildLeft >= left && clampedChildTop >= top &&
279e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    clampedChildRight <= right && clampedChildBottom <= bottom) {
280e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                vis = INVISIBLE;
281e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            } else {
282e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                vis = VISIBLE;
283e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
284e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            child.setVisibility(vis);
285e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
286e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
287e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
288e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    void setAllChildrenVisible() {
289e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        for (int i = 0, childCount = getChildCount(); i < childCount; i++) {
290e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final View child = getChildAt(i);
291e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            if (child.getVisibility() == INVISIBLE) {
292e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                child.setVisibility(VISIBLE);
293e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
294e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
295e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
296e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
297e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private static boolean viewIsOpaque(View v) {
298e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (ViewCompat.isOpaque(v)) return true;
299e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
300e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final Drawable bg = v.getBackground();
301e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (bg != null) {
302e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            return bg.getOpacity() == PixelFormat.OPAQUE;
303e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
304e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        return false;
305e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
306e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
307e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    @Override
308e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    protected void onAttachedToWindow() {
309e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        super.onAttachedToWindow();
310e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        mFirstLayout = true;
311e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
312e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
313e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    @Override
314e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    protected void onDetachedFromWindow() {
315e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        super.onDetachedFromWindow();
316e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        mFirstLayout = true;
317e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
318e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
319e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    @Override
320e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
321e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
322e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
323e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
324e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
325e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
326e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
327e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (widthMode != MeasureSpec.EXACTLY) {
328e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            if (isInEditMode()) {
329e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                // Don't crash the layout editor. Consume all of the space if specified
330e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                // or pick a magic number from thin air otherwise.
331e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                // TODO Better communication with tools of this bogus state.
332e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                // It will crash on a real device.
333e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                if (widthMode == MeasureSpec.AT_MOST) {
334e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    widthMode = MeasureSpec.EXACTLY;
335e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                } else if (widthMode == MeasureSpec.UNSPECIFIED) {
336e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    widthMode = MeasureSpec.EXACTLY;
337e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    widthSize = 300;
338e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                }
339e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            } else {
340e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                throw new IllegalStateException("Width must have an exact value or MATCH_PARENT");
341e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
342e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        } else if (heightMode == MeasureSpec.UNSPECIFIED) {
343e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            if (isInEditMode()) {
344e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                // Don't crash the layout editor. Pick a magic number from thin air instead.
345e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                // TODO Better communication with tools of this bogus state.
346e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                // It will crash on a real device.
347e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                if (heightMode == MeasureSpec.UNSPECIFIED) {
348e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    heightMode = MeasureSpec.AT_MOST;
349e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    heightSize = 300;
350e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                }
351e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            } else {
352e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                throw new IllegalStateException("Height must not be UNSPECIFIED");
353e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
354e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
355e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
356e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        int layoutWidth = 0;
357e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        int maxLayoutWidth = -1;
358e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        switch (widthMode) {
359e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            case MeasureSpec.EXACTLY:
360e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                layoutWidth = maxLayoutWidth = widthSize - getPaddingLeft() - getPaddingRight();
361e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                break;
362e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            case MeasureSpec.AT_MOST:
363e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                maxLayoutWidth = widthSize - getPaddingLeft() - getPaddingRight();
364e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                break;
365e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
366e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
367e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        float weightSum = 0;
368e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        boolean canSlide = false;
369e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int heightAvailable = heightSize - getPaddingTop() - getPaddingBottom();
370e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        int heightRemaining = heightAvailable;
371e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int childCount = getChildCount();
372e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
373e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (childCount > 2) {
374e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            Log.e(TAG, "onMeasure: More than two child views are not supported.");
375e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
376e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
377e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        // We'll find the current one below.
378e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        mSlideableView = null;
379e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
380e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        // First pass. Measure based on child LayoutParams width/height.
381e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        // Weight will incur a second pass.
382e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        for (int i = 0; i < childCount; i++) {
383e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final View child = getChildAt(i);
384e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
385e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
386e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            if (child.getVisibility() == GONE) {
387e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                continue;
388e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
389e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
390e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            if (lp.weight > 0) {
391e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                weightSum += lp.weight;
392e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
393e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                // If we have no height, weight is the only contributor to the final size.
394e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                // Measure this view on the weight pass only.
395e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                if (lp.height == 0) continue;
396e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
397e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
398e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            int childHeightSpec;
399e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final int verticalMargin = lp.topMargin + lp.bottomMargin;
400e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            if (lp.height == LayoutParams.WRAP_CONTENT) {
401e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                childHeightSpec = MeasureSpec.makeMeasureSpec(heightAvailable - verticalMargin,
402e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        MeasureSpec.AT_MOST);
403e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            } else if (lp.height == LayoutParams.MATCH_PARENT) {
404e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                childHeightSpec = MeasureSpec.makeMeasureSpec(heightAvailable - verticalMargin,
405e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        MeasureSpec.EXACTLY);
406e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            } else {
407e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                childHeightSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);
408e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
409e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
410e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            int childWidthSpec;
411e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            if (lp.width == LayoutParams.WRAP_CONTENT) {
412e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                childWidthSpec = MeasureSpec.makeMeasureSpec(maxLayoutWidth, MeasureSpec.AT_MOST);
413e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            } else if (lp.width == LayoutParams.MATCH_PARENT) {
414e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                childWidthSpec = MeasureSpec.makeMeasureSpec(maxLayoutWidth, MeasureSpec.EXACTLY);
415e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            } else {
416e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                childWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
417e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
418e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
419e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            child.measure(childWidthSpec, childHeightSpec);
420e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final int childWidth = child.getMeasuredWidth();
421e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final int childHeight = child.getMeasuredHeight();
422e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
423e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            if (widthMode == MeasureSpec.AT_MOST && childWidth > layoutWidth) {
424e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                layoutWidth = Math.min(childWidth, maxLayoutWidth);
425e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
426e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
427e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            heightRemaining -= childHeight;
428e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            canSlide |= lp.slideable = heightRemaining < 0;
429e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            if (lp.slideable) {
430e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                mSlideableView = child;
431e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
432e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
433e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
434e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        // Resolve weight and make sure non-sliding panels are smaller than the full screen.
435e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (canSlide || weightSum > 0) {
436e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final int fixedPanelHeightLimit = heightAvailable - mOverhangSize;
437e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
438e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            for (int i = 0; i < childCount; i++) {
439e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                final View child = getChildAt(i);
440e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
441e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                if (child.getVisibility() == GONE) {
442e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    continue;
443e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                }
444e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
445e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
446e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
447e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                if (child.getVisibility() == GONE) {
448e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    continue;
449e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                }
450e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
451e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                final boolean skippedFirstPass = lp.height == 0 && lp.weight > 0;
452e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                final int measuredHeight = skippedFirstPass ? 0 : child.getMeasuredHeight();
453e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                if (canSlide && child != mSlideableView) {
454e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    if (lp.height < 0 && (measuredHeight > fixedPanelHeightLimit || lp.weight > 0)) {
455e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        // Fixed panels in a sliding configuration should
456e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        // be clamped to the fixed panel limit.
457e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        final int childWidthSpec;
458e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        if (skippedFirstPass) {
459e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                            // Do initial width measurement if we skipped measuring this view
460e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                            // the first time around.
461e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                            if (lp.width == LayoutParams.WRAP_CONTENT) {
462e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                                childWidthSpec = MeasureSpec.makeMeasureSpec(maxLayoutWidth,
463e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                                        MeasureSpec.AT_MOST);
464e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                            } else if (lp.height == LayoutParams.MATCH_PARENT) {
465e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                                childWidthSpec = MeasureSpec.makeMeasureSpec(maxLayoutWidth,
466e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                                        MeasureSpec.EXACTLY);
467e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                            } else {
468e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                                childWidthSpec = MeasureSpec.makeMeasureSpec(lp.width,
469e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                                        MeasureSpec.EXACTLY);
470e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                            }
471e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        } else {
472e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                            childWidthSpec = MeasureSpec.makeMeasureSpec(
473e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                                    child.getMeasuredWidth(), MeasureSpec.EXACTLY);
474e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        }
475e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        final int childHeightSpec = MeasureSpec.makeMeasureSpec(
476e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                                fixedPanelHeightLimit, MeasureSpec.EXACTLY);
477e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        child.measure(childWidthSpec, childHeightSpec);
478e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    }
479e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                } else if (lp.weight > 0) {
480e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    int childWidthSpec;
481e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    if (lp.height == 0) {
482e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        // This was skipped the first time; figure out a real width spec.
483e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        if (lp.width == LayoutParams.WRAP_CONTENT) {
484e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                            childWidthSpec = MeasureSpec.makeMeasureSpec(maxLayoutWidth,
485e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                                    MeasureSpec.AT_MOST);
486e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        } else if (lp.width == LayoutParams.MATCH_PARENT) {
487e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                            childWidthSpec = MeasureSpec.makeMeasureSpec(maxLayoutWidth,
488e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                                    MeasureSpec.EXACTLY);
489e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        } else {
490e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                            childWidthSpec = MeasureSpec.makeMeasureSpec(lp.width,
491e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                                    MeasureSpec.EXACTLY);
492e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        }
493e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    } else {
494e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        childWidthSpec = MeasureSpec.makeMeasureSpec(
495e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                                child.getMeasuredWidth(), MeasureSpec.EXACTLY);
496e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    }
497e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
498e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    if (canSlide) {
499e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        // Consume available space
500e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        final int verticalMargin = lp.topMargin + lp.bottomMargin;
501e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        final int newHeight = heightAvailable - verticalMargin;
502e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        final int childHeightSpec = MeasureSpec.makeMeasureSpec(
503e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                                newHeight, MeasureSpec.EXACTLY);
504e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        if (measuredHeight != newHeight) {
505e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                            child.measure(childWidthSpec, childHeightSpec);
506e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        }
507e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    } else {
508e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        // Distribute the extra width proportionally similar to LinearLayout
509e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        final int heightToDistribute = Math.max(0, heightRemaining);
510e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        final int addedHeight = (int) (lp.weight * heightToDistribute / weightSum);
511e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        final int childHeightSpec = MeasureSpec.makeMeasureSpec(
512e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                                measuredHeight + addedHeight, MeasureSpec.EXACTLY);
513e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        child.measure(childWidthSpec, childHeightSpec);
514e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    }
515e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                }
516e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
517e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
518e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
519e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int measuredHeight = heightSize;
520e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int measuredWidth = layoutWidth + getPaddingLeft() + getPaddingRight();
521e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
522e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        setMeasuredDimension(measuredWidth, measuredHeight);
523e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        mCanSlide = canSlide;
524e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
525e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (mDragHelper.getViewDragState() != ViewDragHelper.STATE_IDLE && !canSlide) {
526e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            // Cancel scrolling in progress, it's no longer relevant.
527e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            mDragHelper.abort();
528e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
529e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
530e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
531e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    @Override
532e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    protected void onLayout(boolean changed, int l, int t, int r, int b) {
533e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_TOP);
534e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
535e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int height = b - t;
536e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int paddingTop = getPaddingTop();
537e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int paddingBottom = getPaddingBottom();
538e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int paddingLeft = getPaddingLeft();
539e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
540e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int childCount = getChildCount();
541e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        int yStart = paddingTop;
542e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        int nextYStart = yStart;
543e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
544e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (mFirstLayout) {
545e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            mSlideOffset = mCanSlide && mPreservedOpenState ? 1.f : 0.f;
546e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
547e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
548e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        for (int i = 0; i < childCount; i++) {
549e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final View child = getChildAt(i);
550e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
551e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            if (child.getVisibility() == GONE) {
552e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                continue;
553e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
554e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
555e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
556e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
557e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final int childHeight = child.getMeasuredHeight();
558e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
559e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            if (lp.slideable) {
560e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                final int margin = lp.topMargin + lp.bottomMargin;
561e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                final int range = Math.min(nextYStart,
562e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        height - paddingBottom - mOverhangSize) - yStart - margin;
563e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                mSlideRange = range;
564e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                final int lpMargin = lp.topMargin;
565e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                final int pos = (int) (range * mSlideOffset);
566e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                yStart += pos + lpMargin;
5675c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee                updateSlideOffset(pos);
568e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            } else {
569e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                yStart = nextYStart;
570e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
571e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
572e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final int childTop = yStart;
573e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final int childBottom = childTop + childHeight;
574e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final int childLeft = paddingLeft;
575e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final int childRight = childLeft + child.getMeasuredWidth();
576e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
577e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            child.layout(childLeft, childTop, childRight, childBottom);
578e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
579e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            nextYStart += child.getHeight();
580e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
581e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
582e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (mFirstLayout) {
583e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            updateObscuredViewsVisibility(mSlideableView);
584e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
585e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
586e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        mFirstLayout = false;
587e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
588e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
589e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    @Override
590e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
591e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        super.onSizeChanged(w, h, oldw, oldh);
592e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        // Recalculate sliding panes and their details
593e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (h != oldh) {
594e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            mFirstLayout = true;
595e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
596e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
597e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
598e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    @Override
599e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    public void requestChildFocus(View child, View focused) {
600e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        super.requestChildFocus(child, focused);
601e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (!isInTouchMode() && !mCanSlide) {
602e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            mPreservedOpenState = child == mSlideableView;
603e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
604e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
605e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
606e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    @Override
607e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    public boolean onInterceptTouchEvent(MotionEvent ev) {
608e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int action = MotionEventCompat.getActionMasked(ev);
609e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
610e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        // Preserve the open state based on the last view that was touched.
611e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (!mCanSlide && action == MotionEvent.ACTION_DOWN && getChildCount() > 1) {
612e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            // After the first things will be slideable.
613e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final View secondChild = getChildAt(1);
614e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            if (secondChild != null) {
615e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                mPreservedOpenState = !mDragHelper.isViewUnder(secondChild,
616e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                        (int) ev.getX(), (int) ev.getY());
617e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
618e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
619e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
620e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (!mCanSlide || (mIsUnableToDrag && action != MotionEvent.ACTION_DOWN)) {
621bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee            if (!mIsInNestedScroll) {
622bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee                mDragHelper.cancel();
623bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee            }
624e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            return super.onInterceptTouchEvent(ev);
625e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
626e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
627e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
628bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee            if (!mIsInNestedScroll) {
629bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee                mDragHelper.cancel();
630bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee            }
631e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            return false;
632e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
633e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
634e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        switch (action) {
635e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            case MotionEvent.ACTION_DOWN: {
636e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                mIsUnableToDrag = false;
637e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                final float x = ev.getX();
638e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                final float y = ev.getY();
639e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                mInitialMotionX = x;
640e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                mInitialMotionY = y;
641e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
642e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                break;
643e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
644e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
645e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            case MotionEvent.ACTION_MOVE: {
646e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                final float x = ev.getX();
647e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                final float y = ev.getY();
648e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                final float adx = Math.abs(x - mInitialMotionX);
649e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                final float ady = Math.abs(y - mInitialMotionY);
650e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                final int slop = mDragHelper.getTouchSlop();
651e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                if (ady > slop && adx > ady || !isCapturableViewUnder((int) x, (int) y)) {
652bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee                    if (!mIsInNestedScroll) {
653bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee                        mDragHelper.cancel();
654bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee                    }
655e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    mIsUnableToDrag = true;
656e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    return false;
657e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                }
658e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
659e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
660e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
661e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final boolean interceptForDrag = mDragHelper.shouldInterceptTouchEvent(ev);
662e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
66310812203e52353f666cbb3ef02e423711dd64758Yorke Lee        return interceptForDrag;
664e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
665e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
666e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    @Override
667e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    public boolean onTouchEvent(MotionEvent ev) {
668e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (!mCanSlide) {
669e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            return super.onTouchEvent(ev);
670e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
671e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
672e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        mDragHelper.processTouchEvent(ev);
673e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
674e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int action = ev.getAction();
675e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        boolean wantTouchEvents = true;
676e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
677e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        switch (action & MotionEventCompat.ACTION_MASK) {
678e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            case MotionEvent.ACTION_DOWN: {
679e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                final float x = ev.getX();
680e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                final float y = ev.getY();
681e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                mInitialMotionX = x;
682e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                mInitialMotionY = y;
683e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                break;
684e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
685e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
686e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
687e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        return wantTouchEvents;
688e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
689e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
690e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private boolean closePane(View pane, int initialVelocity) {
691e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (mFirstLayout || smoothSlideTo(0.f, initialVelocity)) {
692e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            mPreservedOpenState = false;
693e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            return true;
694e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
695e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        return false;
696e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
697e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
698e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private boolean openPane(View pane, int initialVelocity) {
699e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (mFirstLayout || smoothSlideTo(1.f, initialVelocity)) {
700e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            mPreservedOpenState = true;
701e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            return true;
702e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
703e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        return false;
704e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
705e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
7065c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee    private void updateSlideOffset(int offsetPx) {
7075c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        mSlideOffsetPx = offsetPx;
7085c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        mSlideOffset = (float) mSlideOffsetPx / mSlideRange;
7095c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee    }
7105c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee
711e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    /**
712e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * Open the sliding pane if it is currently slideable. If first layout
713e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * has already completed this will animate.
714e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     *
715e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * @return true if the pane was slideable and is now open/in the process of opening
716e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     */
717e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    public boolean openPane() {
718e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        return openPane(mSlideableView, 0);
719e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
720e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
721e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    /**
722e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * Close the sliding pane if it is currently slideable. If first layout
723e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * has already completed this will animate.
724e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     *
725e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * @return true if the pane was slideable and is now closed/in the process of closing
726e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     */
727e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    public boolean closePane() {
728e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        return closePane(mSlideableView, 0);
729e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
730e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
731e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    /**
7325c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee     * Check if the layout is open. It can be open either because the slider
733e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * itself is open revealing the left pane, or if all content fits without sliding.
734e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     *
7355c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee     * @return true if sliding panels are open
736e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     */
737e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    public boolean isOpen() {
7385c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        return !mCanSlide || mSlideOffset > 0;
739e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
740e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
741e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    /**
742e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * Check if the content in this layout cannot fully fit side by side and therefore
743e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * the content pane can be slid back and forth.
744e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     *
745e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * @return true if content in this layout can be slid open and closed
746e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     */
747e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    public boolean isSlideable() {
748e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        return mCanSlide;
749e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
750e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
751e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private void onPanelDragged(int newTop) {
752e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (mSlideableView == null) {
753e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            // This can happen if we're aborting motion during layout because everything now fits.
754e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            mSlideOffset = 0;
755e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            return;
756e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
757e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final LayoutParams lp = (LayoutParams) mSlideableView.getLayoutParams();
758e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
759e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int lpMargin = lp.topMargin;
760e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int topBound = getPaddingTop() + lpMargin;
761e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
7625c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        updateSlideOffset(newTop - topBound);
763e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
764e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        dispatchOnPanelSlide(mSlideableView);
765e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
766e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
767e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    @Override
768e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
769e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
770e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        boolean result;
771e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final int save = canvas.save(Canvas.CLIP_SAVE_FLAG);
772e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
773e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (mCanSlide && !lp.slideable && mSlideableView != null) {
774e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            // Clip against the slider; no sense drawing what will immediately be covered.
775e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            canvas.getClipBounds(mTmpRect);
776e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
777e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            mTmpRect.bottom = Math.min(mTmpRect.bottom, mSlideableView.getTop());
778e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            canvas.clipRect(mTmpRect);
779e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
780e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
781e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (Build.VERSION.SDK_INT >= 11) { // HC
782e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            result = super.drawChild(canvas, child, drawingTime);
783e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        } else {
78410812203e52353f666cbb3ef02e423711dd64758Yorke Lee            if (child.isDrawingCacheEnabled()) {
78510812203e52353f666cbb3ef02e423711dd64758Yorke Lee                child.setDrawingCacheEnabled(false);
786e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
78710812203e52353f666cbb3ef02e423711dd64758Yorke Lee            result = super.drawChild(canvas, child, drawingTime);
788e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
789e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
790e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        canvas.restoreToCount(save);
791e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
792e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        return result;
793e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
794e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
795e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    /**
796e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * Smoothly animate mDraggingPane to the target X position within its range.
797e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     *
798e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * @param slideOffset position to animate to
799e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     * @param velocity initial velocity in case of fling, or 0.
800e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee     */
801e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    boolean smoothSlideTo(float slideOffset, int velocity) {
802e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (!mCanSlide) {
803e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            // Nothing to do.
804e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            return false;
805e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
806e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
807e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        final LayoutParams lp = (LayoutParams) mSlideableView.getLayoutParams();
808e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
809e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        int y;
810e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        int topBound = getPaddingTop() + lp.topMargin;
811e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        y = (int) (topBound + slideOffset * mSlideRange);
812e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
813e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (mDragHelper.smoothSlideViewTo(mSlideableView, mSlideableView.getLeft(), y)) {
814e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            setAllChildrenVisible();
815e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            ViewCompat.postInvalidateOnAnimation(this);
816e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            return true;
817e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
818e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        return false;
819e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
820e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
821e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    @Override
822e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    public void computeScroll() {
823e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (mDragHelper.continueSettling(true)) {
824e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            if (!mCanSlide) {
825e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                mDragHelper.abort();
826e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                return;
827e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
828e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
829e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            ViewCompat.postInvalidateOnAnimation(this);
830e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
831e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
832e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
833e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private boolean isCapturableViewUnder(int x, int y) {
834e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        View capturableView = mCapturableView != null ? mCapturableView : mSlideableView;
835e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (capturableView == null) {
836e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            return false;
837e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
838e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        int[] viewLocation = new int[2];
839e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        capturableView.getLocationOnScreen(viewLocation);
840e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        int[] parentLocation = new int[2];
841e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        this.getLocationOnScreen(parentLocation);
842e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        int screenX = parentLocation[0] + x;
843e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        int screenY = parentLocation[1] + y;
844e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        return screenX >= viewLocation[0]
845e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                && screenX < viewLocation[0] + capturableView.getWidth()
846e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                && screenY >= viewLocation[1]
847e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                && screenY < viewLocation[1] + capturableView.getHeight();
848e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
849e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
850e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    @Override
851e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
852e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        return new LayoutParams();
853e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
854e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
855e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    @Override
856e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
857e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        return p instanceof MarginLayoutParams
858e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                ? new LayoutParams((MarginLayoutParams) p)
859e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                : new LayoutParams(p);
860e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
861e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
862e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    @Override
863e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
864e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        return p instanceof LayoutParams && super.checkLayoutParams(p);
865e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
866e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
867e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    @Override
868e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
869e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        return new LayoutParams(getContext(), attrs);
870e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
871e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
872e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    @Override
873e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    protected Parcelable onSaveInstanceState() {
874e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        Parcelable superState = super.onSaveInstanceState();
875e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
876e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        SavedState ss = new SavedState(superState);
877e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        ss.isOpen = isSlideable() ? isOpen() : mPreservedOpenState;
878e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
879e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        return ss;
880e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
881e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
882e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    @Override
883e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    protected void onRestoreInstanceState(Parcelable state) {
884e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        SavedState ss = (SavedState) state;
885e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        super.onRestoreInstanceState(ss.getSuperState());
886e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
887e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        if (ss.isOpen) {
888e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            openPane();
889e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        } else {
890e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            closePane();
891e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
892e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        mPreservedOpenState = ss.isOpen;
893e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
894e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
895bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee    @Override
896bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee    public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
897bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee        final boolean startNestedScroll = (nestedScrollAxes & SCROLL_AXIS_VERTICAL) != 0;
898bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee        if (startNestedScroll) {
899bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee            mIsInNestedScroll = true;
90040ed60dab29e90e28f95a0d8a9c612fed7a253ceYorke Lee            mChildCannotConsumeScroll = true;
901bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee            mDragHelper.startNestedScroll(mSlideableView);
902bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee        }
9035c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        if (DEBUG) {
9045c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee            Log.d(TAG, "onStartNestedScroll: " + startNestedScroll);
9055c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        }
906bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee        return startNestedScroll;
907bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee    }
908bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee
909bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee    @Override
910bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee    public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
9115c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        if (dy == 0) {
9125c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee            // Nothing to do
9135c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee            return;
9145c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        }
9155c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        if (DEBUG) {
9165c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee            Log.d(TAG, "onNestedPreScroll: " + dy);
9175c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        }
91840ed60dab29e90e28f95a0d8a9c612fed7a253ceYorke Lee        mInNestedPreScrollDownwards =
91940ed60dab29e90e28f95a0d8a9c612fed7a253ceYorke Lee                mChildCannotConsumeScroll && dy > 0 && mSlideOffsetPx <= mIntermediateOffset;
920bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee        mDragHelper.processNestedScroll(mSlideableView, 0, dy, consumed);
921bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee    }
922bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee
923bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee    @Override
9245c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee    public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed,
9255c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee            int dyUnconsumed) {
9265c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        if (DEBUG) {
9275c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee            Log.d(TAG, "onNestedScroll: " + dyUnconsumed);
9285c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        }
92940ed60dab29e90e28f95a0d8a9c612fed7a253ceYorke Lee        mChildCannotConsumeScroll = false;
9305c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        mInNestedPreScrollDownwards = false;
9315c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        // We need to flip dyUnconsumed here, because its magnitude is reversed. b/14585990
9325c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        mDragHelper.processNestedScroll(mSlideableView, 0, -dyUnconsumed, null);
9335c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee    }
9345c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee
9355c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee    @Override
936bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee    public void onStopNestedScroll(View child) {
9375c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        if (DEBUG) {
9385c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee            Log.d(TAG, "onStopNestedScroll");
9395c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        }
9405c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        if (mIsInNestedScroll) {
9415c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee            mDragHelper.stopNestedScroll(mSlideableView);
9425c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee        }
943bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee        mIsInNestedScroll = false;
944bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee    }
945bd180af7f0b73b0dd79a7117fb0c14370ef4d12eYorke Lee
946e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    private class DragHelperCallback extends ViewDragHelper.Callback {
947e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
948e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        @Override
949e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public boolean tryCaptureView(View child, int pointerId) {
950e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            if (mIsUnableToDrag) {
951e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                return false;
952e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
953e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
954e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            return ((LayoutParams) child.getLayoutParams()).slideable;
955e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
956e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
957e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        @Override
958e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public void onViewDragStateChanged(int state) {
959e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            if (mDragHelper.getViewDragState() == ViewDragHelper.STATE_IDLE) {
960e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                if (mSlideOffset == 0) {
961e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    updateObscuredViewsVisibility(mSlideableView);
962e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    dispatchOnPanelClosed(mSlideableView);
963e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    mPreservedOpenState = false;
964e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                } else {
965e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    dispatchOnPanelOpened(mSlideableView);
966e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    mPreservedOpenState = true;
967e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                }
968e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
969e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
970e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
971e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        @Override
972e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public void onViewCaptured(View capturedChild, int activePointerId) {
973e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            // Make all child views visible in preparation for sliding things around
974e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            setAllChildrenVisible();
975e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
976e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
977e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        @Override
978e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
979e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            onPanelDragged(top);
980e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            invalidate();
981e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
982e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
983e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        @Override
984e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public void onViewReleased(View releasedChild, float xvel, float yvel) {
985e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final LayoutParams lp = (LayoutParams) releasedChild.getLayoutParams();
986e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
987e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            int top = getPaddingTop() + lp.topMargin;
9885c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee
9895c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee            if (mInNestedPreScrollDownwards) {
9905c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee                // Snap to the closest pinnable position based on the current slide offset
9915c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee                // (in pixels)   [0  -  mIntermediateoffset  - mSlideRange]
9925c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee                if (yvel > 0) {
9935c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee                    top += mSlideRange;
9945c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee                } else if (0 <= mSlideOffsetPx && mSlideOffsetPx <= mIntermediateOffset / 2) {
9955c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee                    // Offset is between 0 and mIntermediateOffset, but closer to 0
9965c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee                    // Leave top unchanged
9975c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee                } else if (mIntermediateOffset / 2 <= mSlideOffsetPx
9985c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee                        && mSlideOffsetPx <= (mIntermediateOffset + mSlideRange) / 2) {
9995c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee                    // Offset is closest to mIntermediateOffset
10005c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee                    top += mIntermediateOffset;
10015c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee                } else {
10025c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee                    // Offset is between mIntermediateOffset and mSlideRange, but closer to
10035c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee                    // mSlideRange
10045c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee                    top += mSlideRange;
10055c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee                }
10065c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee            } else if (yvel > 0 || (yvel == 0 && mSlideOffset > 0.5f)) {
1007e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                top += mSlideRange;
1008e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
1009e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1010e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            mDragHelper.settleCapturedViewAt(releasedChild.getLeft(), top);
1011e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            invalidate();
1012e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
1013e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1014e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        @Override
1015e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public int getViewVerticalDragRange(View child) {
1016e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            return mSlideRange;
1017e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
1018e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1019e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        @Override
1020e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public int clampViewPositionHorizontal(View child, int left, int dx) {
1021e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            // Make sure we never move views horizontally.
1022e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            return child.getLeft();
1023e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
1024e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1025e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        @Override
1026e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public int clampViewPositionVertical(View child, int top, int dy) {
1027e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final LayoutParams lp = (LayoutParams) mSlideableView.getLayoutParams();
1028e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1029e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final int newTop;
1030e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            int topBound = getPaddingTop() + lp.topMargin;
10315c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee            int bottomBound = topBound
10325c7e73087ccb1615c6e460beb6c9734e665c527fYorke Lee                    + (mInNestedPreScrollDownwards ? mIntermediateOffset : mSlideRange);
1033e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            newTop = Math.min(Math.max(top, topBound), bottomBound);
1034e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1035e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            return newTop;
1036e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
1037e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1038e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        @Override
1039e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public void onEdgeDragStarted(int edgeFlags, int pointerId) {
1040e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            mDragHelper.captureChildView(mSlideableView, pointerId);
1041e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
1042e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
1043e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1044e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    public static class LayoutParams extends ViewGroup.MarginLayoutParams {
1045e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        private static final int[] ATTRS = new int[] {
1046e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            android.R.attr.layout_weight
1047e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        };
1048e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1049e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        /**
1050e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         * The weighted proportion of how much of the leftover space
1051e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         * this child should consume after measurement.
1052e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         */
1053e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public float weight = 0;
1054e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1055e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        /**
1056e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         * True if this pane is the slideable pane in the layout.
1057e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         */
1058e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        boolean slideable;
1059e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1060e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public LayoutParams() {
1061e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            super(FILL_PARENT, FILL_PARENT);
1062e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
1063e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1064e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public LayoutParams(int width, int height) {
1065e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            super(width, height);
1066e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
1067e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1068e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public LayoutParams(android.view.ViewGroup.LayoutParams source) {
1069e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            super(source);
1070e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
1071e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1072e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public LayoutParams(MarginLayoutParams source) {
1073e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            super(source);
1074e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
1075e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1076e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public LayoutParams(LayoutParams source) {
1077e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            super(source);
1078e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            this.weight = source.weight;
1079e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
1080e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1081e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public LayoutParams(Context c, AttributeSet attrs) {
1082e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            super(c, attrs);
1083e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1084e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final TypedArray a = c.obtainStyledAttributes(attrs, ATTRS);
1085e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            this.weight = a.getFloat(0, 0);
1086e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            a.recycle();
1087e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
1088e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1089e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
1090e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1091e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    static class SavedState extends BaseSavedState {
1092e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        boolean isOpen;
1093e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1094e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        SavedState(Parcelable superState) {
1095e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            super(superState);
1096e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
1097e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1098e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        private SavedState(Parcel in) {
1099e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            super(in);
1100e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            isOpen = in.readInt() != 0;
1101e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
1102e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1103e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        @Override
1104e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public void writeToParcel(Parcel out, int flags) {
1105e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            super.writeToParcel(out, flags);
1106e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            out.writeInt(isOpen ? 1 : 0);
1107e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
1108e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1109e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public static final Parcelable.Creator<SavedState> CREATOR =
1110e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                new Parcelable.Creator<SavedState>() {
1111e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            public SavedState createFromParcel(Parcel in) {
1112e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                return new SavedState(in);
1113e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
1114e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1115e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            public SavedState[] newArray(int size) {
1116e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                return new SavedState[size];
1117e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
1118e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        };
1119e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
1120e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1121e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    class AccessibilityDelegate extends AccessibilityDelegateCompat {
1122e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        private final Rect mTmpRect = new Rect();
1123e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1124e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        @Override
1125e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
1126e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final AccessibilityNodeInfoCompat superNode = AccessibilityNodeInfoCompat.obtain(info);
1127e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            super.onInitializeAccessibilityNodeInfo(host, superNode);
1128e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            copyNodeInfoNoChildren(info, superNode);
1129e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            superNode.recycle();
1130e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1131e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            info.setClassName(OverlappingPaneLayout.class.getName());
1132e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            info.setSource(host);
1133e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1134e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final ViewParent parent = ViewCompat.getParentForAccessibility(host);
1135e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            if (parent instanceof View) {
1136e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                info.setParent((View) parent);
1137e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
1138e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1139e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            // This is a best-approximation of addChildrenForAccessibility()
1140e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            // that accounts for filtering.
1141e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final int childCount = getChildCount();
1142e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            for (int i = 0; i < childCount; i++) {
1143e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                final View child = getChildAt(i);
114410812203e52353f666cbb3ef02e423711dd64758Yorke Lee                if (child.getVisibility() == View.VISIBLE) {
1145e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    // Force importance to "yes" since we can't read the value.
1146e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    ViewCompat.setImportantForAccessibility(
1147e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                            child, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
1148e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                    info.addChild(child);
1149e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                }
1150e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            }
1151e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
1152e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1153e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        @Override
1154e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
1155e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            super.onInitializeAccessibilityEvent(host, event);
1156e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1157e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            event.setClassName(OverlappingPaneLayout.class.getName());
1158e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
1159e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1160e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        /**
1161e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         * This should really be in AccessibilityNodeInfoCompat, but there unfortunately
1162e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         * seem to be a few elements that are not easily cloneable using the underlying API.
1163e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         * Leave it private here as it's not general-purpose useful.
1164e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee         */
1165e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        private void copyNodeInfoNoChildren(AccessibilityNodeInfoCompat dest,
1166e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee                AccessibilityNodeInfoCompat src) {
1167e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            final Rect rect = mTmpRect;
1168e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1169e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            src.getBoundsInParent(rect);
1170e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            dest.setBoundsInParent(rect);
1171e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1172e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            src.getBoundsInScreen(rect);
1173e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            dest.setBoundsInScreen(rect);
1174e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1175e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            dest.setVisibleToUser(src.isVisibleToUser());
1176e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            dest.setPackageName(src.getPackageName());
1177e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            dest.setClassName(src.getClassName());
1178e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            dest.setContentDescription(src.getContentDescription());
1179e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1180e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            dest.setEnabled(src.isEnabled());
1181e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            dest.setClickable(src.isClickable());
1182e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            dest.setFocusable(src.isFocusable());
1183e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            dest.setFocused(src.isFocused());
1184e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            dest.setAccessibilityFocused(src.isAccessibilityFocused());
1185e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            dest.setSelected(src.isSelected());
1186e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            dest.setLongClickable(src.isLongClickable());
1187e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1188e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            dest.addAction(src.getActions());
1189e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee
1190e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee            dest.setMovementGranularities(src.getMovementGranularities());
1191e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee        }
1192e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee    }
1193e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee}
1194