OverlappingPaneLayout.java revision e709fd21eda44df07327f649e4e6a257918555a9
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.Bitmap; 22e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.graphics.Canvas; 23e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.graphics.Paint; 24e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.graphics.PixelFormat; 25e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.graphics.PorterDuff; 26e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.graphics.PorterDuffColorFilter; 27e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.graphics.Rect; 28e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.graphics.drawable.Drawable; 29e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.os.Build; 30e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.os.Parcel; 31e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.os.Parcelable; 32e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.support.v4.view.AccessibilityDelegateCompat; 33e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.support.v4.view.MotionEventCompat; 34e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.support.v4.view.ViewCompat; 35e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; 36e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.support.v4.widget.ViewDragHelper; 37e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.util.AttributeSet; 38e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.util.Log; 39e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.view.MotionEvent; 40e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.view.View; 41e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.view.ViewGroup; 42e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.view.ViewParent; 43e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport android.view.accessibility.AccessibilityEvent; 44e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 45e709fd21eda44df07327f649e4e6a257918555a9Yorke Leeimport java.util.ArrayList; 46e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 47e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee/** 48e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * A custom layout that aligns its child views vertically as two panes, and allows for the bottom 49e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * pane to be dragged upwards to overlap and hide the top pane. This layout is adapted from 50e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * {@link android.support.v4.widget.SlidingPaneLayout}. 51e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 52e709fd21eda44df07327f649e4e6a257918555a9Yorke Leepublic class OverlappingPaneLayout extends ViewGroup { 53e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private static final String TAG = "SlidingPaneLayout"; 54e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 55e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 56e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * Default size of the overhang for a pane in the open state. 57e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * At least this much of a sliding pane will remain visible. 58e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * This indicates that there is more content available and provides 59e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * a "physical" edge to grab to pull it closed. 60e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 61e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private static final int DEFAULT_OVERHANG_SIZE = 32; // dp; 62e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 63e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 64e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * If no fade color is given by default it will fade to 80% gray. 65e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 66e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private static final int DEFAULT_FADE_COLOR = 0xcccccccc; 67e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 68e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 69e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * The fade color used for the sliding panel. 0 = no fading. 70e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 71e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private int mSliderFadeColor = DEFAULT_FADE_COLOR; 72e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 73e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 74e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * Minimum velocity that will be detected as a fling 75e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 76e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private static final int MIN_FLING_VELOCITY = 400; // dips per second 77e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 78e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 79e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * The fade color used for the panel covered by the slider. 0 = no fading. 80e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 81e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private int mCoveredFadeColor; 82e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 83e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 84e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * The size of the overhang in pixels. 85e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * This is the minimum section of the sliding panel that will 86e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * be visible in the open state to allow for a closing drag. 87e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 88e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private final int mOverhangSize; 89e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 90e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 91e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * True if a panel can slide with the current measurements 92e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 93e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private boolean mCanSlide; 94e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 95e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 96e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * The child view that can slide, if any. 97e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 98e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private View mSlideableView; 99e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 100e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 101e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * The view that can be used to start the drag with. 102e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 103e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private View mCapturableView; 104e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 105e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 106e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * How far the panel is offset from its closed position. 107e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * range [0, 1] where 0 = closed, 1 = open. 108e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 109e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private float mSlideOffset; 110e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 111e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 112e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * How far in pixels the slideable panel may move. 113e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 114e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private int mSlideRange; 115e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 116e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 117e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * A panel view is locked into internal scrolling or another condition that 118e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * is preventing a drag. 119e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 120e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private boolean mIsUnableToDrag; 121e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 122e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private float mInitialMotionX; 123e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private float mInitialMotionY; 124e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 125e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private PanelSlideListener mPanelSlideListener; 126e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 127e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private final ViewDragHelper mDragHelper; 128e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 129e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 130e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * Stores whether or not the pane was open the last time it was slideable. 131e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * If open/close operations are invoked this state is modified. Used by 132e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * instance state save/restore. 133e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 134e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private boolean mPreservedOpenState; 135e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private boolean mFirstLayout = true; 136e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 137e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private final Rect mTmpRect = new Rect(); 138e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 139e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private final ArrayList<DisableLayerRunnable> mPostedRunnables = 140e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee new ArrayList<DisableLayerRunnable>(); 141e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 142e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 143e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * Listener for monitoring events about sliding panes. 144e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 145e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public interface PanelSlideListener { 146e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 147e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * Called when a sliding pane's position changes. 148e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * @param panel The child view that was moved 149e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * @param slideOffset The new offset of this sliding pane within its range, from 0-1 150e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 151e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public void onPanelSlide(View panel, float slideOffset); 152e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 153e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * Called when a sliding pane becomes slid completely open. The pane may or may not 154e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * be interactive at this point depending on how much of the pane is visible. 155e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * @param panel The child view that was slid to an open position, revealing other panes 156e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 157e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public void onPanelOpened(View panel); 158e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 159e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 160e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * Called when a sliding pane becomes slid completely closed. The pane is now guaranteed 161e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * to be interactive. It may now obscure other views in the layout. 162e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * @param panel The child view that was slid to a closed position 163e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 164e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public void onPanelClosed(View panel); 165e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 166e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 167e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public OverlappingPaneLayout(Context context) { 168e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee this(context, null); 169e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 170e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 171e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public OverlappingPaneLayout(Context context, AttributeSet attrs) { 172e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee this(context, attrs, 0); 173e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 174e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 175e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public OverlappingPaneLayout(Context context, AttributeSet attrs, int defStyle) { 176e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee super(context, attrs, defStyle); 177e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 178e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final float density = context.getResources().getDisplayMetrics().density; 179e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mOverhangSize = (int) (DEFAULT_OVERHANG_SIZE * density + 0.5f); 180e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 181e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee setWillNotDraw(false); 182e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 183e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee ViewCompat.setAccessibilityDelegate(this, new AccessibilityDelegate()); 184e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee ViewCompat.setImportantForAccessibility(this, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES); 185e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 186e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mDragHelper = ViewDragHelper.create(this, 0.5f, new DragHelperCallback()); 187e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mDragHelper.setMinVelocity(MIN_FLING_VELOCITY * density); 188e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 189e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 190e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 191e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * Set the view that can be used to start dragging the sliding pane. 192e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 193e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public void setCapturableView(View capturableView) { 194e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mCapturableView = capturableView; 195e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 196e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 197e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 198e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * Set the color used to fade the sliding pane out when it is slid most of the way offscreen. 199e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * 200e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * @param color An ARGB-packed color value 201e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 202e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public void setSliderFadeColor(int color) { 203e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mSliderFadeColor = color; 204e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 205e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 206e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 207e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * @return The ARGB-packed color value used to fade the sliding pane 208e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 209e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public int getSliderFadeColor() { 210e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return mSliderFadeColor; 211e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 212e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 213e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 214e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * Set the color used to fade the pane covered by the sliding pane out when the pane 215e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * will become fully covered in the closed state. 216e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * 217e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * @param color An ARGB-packed color value 218e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 219e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public void setCoveredFadeColor(int color) { 220e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mCoveredFadeColor = color; 221e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 222e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 223e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 224e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * @return The ARGB-packed color value used to fade the fixed pane 225e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 226e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public int getCoveredFadeColor() { 227e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return mCoveredFadeColor; 228e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 229e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 230e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public void setPanelSlideListener(PanelSlideListener listener) { 231e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mPanelSlideListener = listener; 232e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 233e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 234e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee void dispatchOnPanelSlide(View panel) { 235e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (mPanelSlideListener != null) { 236e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mPanelSlideListener.onPanelSlide(panel, mSlideOffset); 237e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 238e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 239e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 240e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee void dispatchOnPanelOpened(View panel) { 241e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (mPanelSlideListener != null) { 242e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mPanelSlideListener.onPanelOpened(panel); 243e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 244e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); 245e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 246e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 247e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee void dispatchOnPanelClosed(View panel) { 248e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (mPanelSlideListener != null) { 249e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mPanelSlideListener.onPanelClosed(panel); 250e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 251e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); 252e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 253e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 254e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee void updateObscuredViewsVisibility(View panel) { 255e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int startBound = getPaddingTop(); 256e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int endBound = getHeight() - getPaddingBottom(); 257e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 258e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int leftBound = getPaddingLeft(); 259e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int rightBound = getWidth() - getPaddingRight(); 260e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int left; 261e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int right; 262e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int top; 263e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int bottom; 264e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (panel != null && viewIsOpaque(panel)) { 265e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee left = panel.getLeft(); 266e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee right = panel.getRight(); 267e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee top = panel.getTop(); 268e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee bottom = panel.getBottom(); 269e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else { 270e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee left = right = top = bottom = 0; 271e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 272e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 273e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee for (int i = 0, childCount = getChildCount(); i < childCount; i++) { 274e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final View child = getChildAt(i); 275e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 276e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (child == panel) { 277e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // There are still more children above the panel but they won't be affected. 278e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee break; 279e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 280e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 281e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int clampedChildLeft = Math.max(leftBound, child.getLeft()); 282e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int clampedChildRight = Math.min(rightBound, child.getRight()); 283e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int clampedChildTop = Math.max(startBound, child.getTop()); 284e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int clampedChildBottom = Math.min(endBound, child.getBottom()); 285e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 286e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int vis; 287e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (clampedChildLeft >= left && clampedChildTop >= top && 288e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee clampedChildRight <= right && clampedChildBottom <= bottom) { 289e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee vis = INVISIBLE; 290e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else { 291e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee vis = VISIBLE; 292e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 293e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee child.setVisibility(vis); 294e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 295e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 296e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 297e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee void setAllChildrenVisible() { 298e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee for (int i = 0, childCount = getChildCount(); i < childCount; i++) { 299e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final View child = getChildAt(i); 300e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (child.getVisibility() == INVISIBLE) { 301e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee child.setVisibility(VISIBLE); 302e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 303e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 304e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 305e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 306e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private static boolean viewIsOpaque(View v) { 307e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (ViewCompat.isOpaque(v)) return true; 308e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 309e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final Drawable bg = v.getBackground(); 310e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (bg != null) { 311e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return bg.getOpacity() == PixelFormat.OPAQUE; 312e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 313e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return false; 314e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 315e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 316e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 317e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee protected void onAttachedToWindow() { 318e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee super.onAttachedToWindow(); 319e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mFirstLayout = true; 320e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 321e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 322e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 323e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee protected void onDetachedFromWindow() { 324e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee super.onDetachedFromWindow(); 325e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mFirstLayout = true; 326e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 327e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee for (int i = 0, count = mPostedRunnables.size(); i < count; i++) { 328e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final DisableLayerRunnable dlr = mPostedRunnables.get(i); 329e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dlr.run(); 330e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 331e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mPostedRunnables.clear(); 332e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 333e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 334e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 335e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 336e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 337e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int widthMode = MeasureSpec.getMode(widthMeasureSpec); 338e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int widthSize = MeasureSpec.getSize(widthMeasureSpec); 339e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int heightMode = MeasureSpec.getMode(heightMeasureSpec); 340e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int heightSize = MeasureSpec.getSize(heightMeasureSpec); 341e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 342e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (widthMode != MeasureSpec.EXACTLY) { 343e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (isInEditMode()) { 344e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // Don't crash the layout editor. Consume all of the space if specified 345e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // or pick a magic number from thin air otherwise. 346e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // TODO Better communication with tools of this bogus state. 347e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // It will crash on a real device. 348e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (widthMode == MeasureSpec.AT_MOST) { 349e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee widthMode = MeasureSpec.EXACTLY; 350e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else if (widthMode == MeasureSpec.UNSPECIFIED) { 351e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee widthMode = MeasureSpec.EXACTLY; 352e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee widthSize = 300; 353e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 354e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else { 355e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee throw new IllegalStateException("Width must have an exact value or MATCH_PARENT"); 356e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 357e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else if (heightMode == MeasureSpec.UNSPECIFIED) { 358e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (isInEditMode()) { 359e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // Don't crash the layout editor. Pick a magic number from thin air instead. 360e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // TODO Better communication with tools of this bogus state. 361e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // It will crash on a real device. 362e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (heightMode == MeasureSpec.UNSPECIFIED) { 363e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee heightMode = MeasureSpec.AT_MOST; 364e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee heightSize = 300; 365e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 366e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else { 367e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee throw new IllegalStateException("Height must not be UNSPECIFIED"); 368e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 369e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 370e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 371e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int layoutWidth = 0; 372e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int maxLayoutWidth = -1; 373e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee switch (widthMode) { 374e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee case MeasureSpec.EXACTLY: 375e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee layoutWidth = maxLayoutWidth = widthSize - getPaddingLeft() - getPaddingRight(); 376e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee break; 377e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee case MeasureSpec.AT_MOST: 378e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee maxLayoutWidth = widthSize - getPaddingLeft() - getPaddingRight(); 379e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee break; 380e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 381e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 382e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee float weightSum = 0; 383e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee boolean canSlide = false; 384e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int heightAvailable = heightSize - getPaddingTop() - getPaddingBottom(); 385e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int heightRemaining = heightAvailable; 386e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int childCount = getChildCount(); 387e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 388e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (childCount > 2) { 389e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee Log.e(TAG, "onMeasure: More than two child views are not supported."); 390e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 391e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 392e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // We'll find the current one below. 393e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mSlideableView = null; 394e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 395e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // First pass. Measure based on child LayoutParams width/height. 396e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // Weight will incur a second pass. 397e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee for (int i = 0; i < childCount; i++) { 398e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final View child = getChildAt(i); 399e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 400e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 401e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (child.getVisibility() == GONE) { 402e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee lp.dimWhenOffset = false; 403e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee continue; 404e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 405e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 406e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (lp.weight > 0) { 407e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee weightSum += lp.weight; 408e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 409e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // If we have no height, weight is the only contributor to the final size. 410e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // Measure this view on the weight pass only. 411e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (lp.height == 0) continue; 412e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 413e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 414e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int childHeightSpec; 415e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int verticalMargin = lp.topMargin + lp.bottomMargin; 416e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (lp.height == LayoutParams.WRAP_CONTENT) { 417e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee childHeightSpec = MeasureSpec.makeMeasureSpec(heightAvailable - verticalMargin, 418e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee MeasureSpec.AT_MOST); 419e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else if (lp.height == LayoutParams.MATCH_PARENT) { 420e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee childHeightSpec = MeasureSpec.makeMeasureSpec(heightAvailable - verticalMargin, 421e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee MeasureSpec.EXACTLY); 422e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else { 423e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee childHeightSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY); 424e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 425e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 426e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int childWidthSpec; 427e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (lp.width == LayoutParams.WRAP_CONTENT) { 428e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee childWidthSpec = MeasureSpec.makeMeasureSpec(maxLayoutWidth, MeasureSpec.AT_MOST); 429e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else if (lp.width == LayoutParams.MATCH_PARENT) { 430e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee childWidthSpec = MeasureSpec.makeMeasureSpec(maxLayoutWidth, MeasureSpec.EXACTLY); 431e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else { 432e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee childWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY); 433e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 434e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 435e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee child.measure(childWidthSpec, childHeightSpec); 436e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int childWidth = child.getMeasuredWidth(); 437e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int childHeight = child.getMeasuredHeight(); 438e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 439e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (widthMode == MeasureSpec.AT_MOST && childWidth > layoutWidth) { 440e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee layoutWidth = Math.min(childWidth, maxLayoutWidth); 441e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 442e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 443e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee heightRemaining -= childHeight; 444e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee canSlide |= lp.slideable = heightRemaining < 0; 445e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (lp.slideable) { 446e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mSlideableView = child; 447e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 448e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 449e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 450e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // Resolve weight and make sure non-sliding panels are smaller than the full screen. 451e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (canSlide || weightSum > 0) { 452e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int fixedPanelHeightLimit = heightAvailable - mOverhangSize; 453e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 454e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee for (int i = 0; i < childCount; i++) { 455e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final View child = getChildAt(i); 456e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 457e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (child.getVisibility() == GONE) { 458e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee continue; 459e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 460e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 461e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 462e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 463e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (child.getVisibility() == GONE) { 464e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee continue; 465e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 466e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 467e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final boolean skippedFirstPass = lp.height == 0 && lp.weight > 0; 468e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int measuredHeight = skippedFirstPass ? 0 : child.getMeasuredHeight(); 469e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (canSlide && child != mSlideableView) { 470e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (lp.height < 0 && (measuredHeight > fixedPanelHeightLimit || lp.weight > 0)) { 471e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // Fixed panels in a sliding configuration should 472e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // be clamped to the fixed panel limit. 473e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int childWidthSpec; 474e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (skippedFirstPass) { 475e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // Do initial width measurement if we skipped measuring this view 476e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // the first time around. 477e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (lp.width == LayoutParams.WRAP_CONTENT) { 478e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee childWidthSpec = MeasureSpec.makeMeasureSpec(maxLayoutWidth, 479e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee MeasureSpec.AT_MOST); 480e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else if (lp.height == LayoutParams.MATCH_PARENT) { 481e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee childWidthSpec = MeasureSpec.makeMeasureSpec(maxLayoutWidth, 482e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee MeasureSpec.EXACTLY); 483e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else { 484e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee childWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, 485e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee MeasureSpec.EXACTLY); 486e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 487e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else { 488e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee childWidthSpec = MeasureSpec.makeMeasureSpec( 489e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee child.getMeasuredWidth(), MeasureSpec.EXACTLY); 490e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 491e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int childHeightSpec = MeasureSpec.makeMeasureSpec( 492e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee fixedPanelHeightLimit, MeasureSpec.EXACTLY); 493e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee child.measure(childWidthSpec, childHeightSpec); 494e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 495e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else if (lp.weight > 0) { 496e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int childWidthSpec; 497e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (lp.height == 0) { 498e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // This was skipped the first time; figure out a real width spec. 499e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (lp.width == LayoutParams.WRAP_CONTENT) { 500e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee childWidthSpec = MeasureSpec.makeMeasureSpec(maxLayoutWidth, 501e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee MeasureSpec.AT_MOST); 502e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else if (lp.width == LayoutParams.MATCH_PARENT) { 503e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee childWidthSpec = MeasureSpec.makeMeasureSpec(maxLayoutWidth, 504e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee MeasureSpec.EXACTLY); 505e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else { 506e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee childWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, 507e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee MeasureSpec.EXACTLY); 508e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 509e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else { 510e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee childWidthSpec = MeasureSpec.makeMeasureSpec( 511e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee child.getMeasuredWidth(), MeasureSpec.EXACTLY); 512e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 513e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 514e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (canSlide) { 515e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // Consume available space 516e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int verticalMargin = lp.topMargin + lp.bottomMargin; 517e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int newHeight = heightAvailable - verticalMargin; 518e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int childHeightSpec = MeasureSpec.makeMeasureSpec( 519e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee newHeight, MeasureSpec.EXACTLY); 520e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (measuredHeight != newHeight) { 521e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee child.measure(childWidthSpec, childHeightSpec); 522e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 523e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else { 524e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // Distribute the extra width proportionally similar to LinearLayout 525e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int heightToDistribute = Math.max(0, heightRemaining); 526e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int addedHeight = (int) (lp.weight * heightToDistribute / weightSum); 527e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int childHeightSpec = MeasureSpec.makeMeasureSpec( 528e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee measuredHeight + addedHeight, MeasureSpec.EXACTLY); 529e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee child.measure(childWidthSpec, childHeightSpec); 530e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 531e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 532e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 533e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 534e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 535e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int measuredHeight = heightSize; 536e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int measuredWidth = layoutWidth + getPaddingLeft() + getPaddingRight(); 537e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 538e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee setMeasuredDimension(measuredWidth, measuredHeight); 539e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mCanSlide = canSlide; 540e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 541e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (mDragHelper.getViewDragState() != ViewDragHelper.STATE_IDLE && !canSlide) { 542e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // Cancel scrolling in progress, it's no longer relevant. 543e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mDragHelper.abort(); 544e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 545e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 546e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 547e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 548e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee protected void onLayout(boolean changed, int l, int t, int r, int b) { 549e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_TOP); 550e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 551e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int height = b - t; 552e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int paddingTop = getPaddingTop(); 553e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int paddingBottom = getPaddingBottom(); 554e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int paddingLeft = getPaddingLeft(); 555e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 556e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int childCount = getChildCount(); 557e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int yStart = paddingTop; 558e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int nextYStart = yStart; 559e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 560e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (mFirstLayout) { 561e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mSlideOffset = mCanSlide && mPreservedOpenState ? 1.f : 0.f; 562e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 563e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 564e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee for (int i = 0; i < childCount; i++) { 565e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final View child = getChildAt(i); 566e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 567e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (child.getVisibility() == GONE) { 568e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee continue; 569e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 570e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 571e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 572e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 573e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int childHeight = child.getMeasuredHeight(); 574e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 575e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (lp.slideable) { 576e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int margin = lp.topMargin + lp.bottomMargin; 577e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int range = Math.min(nextYStart, 578e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee height - paddingBottom - mOverhangSize) - yStart - margin; 579e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mSlideRange = range; 580e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int lpMargin = lp.topMargin; 581e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee lp.dimWhenOffset = yStart + lpMargin + range + childHeight / 2 > 582e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee height - paddingBottom; 583e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int pos = (int) (range * mSlideOffset); 584e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee yStart += pos + lpMargin; 585e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mSlideOffset = (float) pos / mSlideRange; 586e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else { 587e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee yStart = nextYStart; 588e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 589e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 590e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int childTop = yStart; 591e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int childBottom = childTop + childHeight; 592e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int childLeft = paddingLeft; 593e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int childRight = childLeft + child.getMeasuredWidth(); 594e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 595e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee child.layout(childLeft, childTop, childRight, childBottom); 596e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 597e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee nextYStart += child.getHeight(); 598e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 599e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 600e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (mFirstLayout) { 601e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (mCanSlide) { 602e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (((LayoutParams) mSlideableView.getLayoutParams()).dimWhenOffset) { 603e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dimChildView(mSlideableView, mSlideOffset, mSliderFadeColor); 604e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 605e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else { 606e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // Reset the dim level of all children; it's irrelevant when nothing moves. 607e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee for (int i = 0; i < childCount; i++) { 608e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dimChildView(getChildAt(i), 0, mSliderFadeColor); 609e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 610e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 611e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee updateObscuredViewsVisibility(mSlideableView); 612e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 613e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 614e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mFirstLayout = false; 615e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 616e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 617e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 618e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee protected void onSizeChanged(int w, int h, int oldw, int oldh) { 619e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee super.onSizeChanged(w, h, oldw, oldh); 620e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // Recalculate sliding panes and their details 621e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (h != oldh) { 622e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mFirstLayout = true; 623e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 624e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 625e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 626e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 627e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public void requestChildFocus(View child, View focused) { 628e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee super.requestChildFocus(child, focused); 629e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (!isInTouchMode() && !mCanSlide) { 630e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mPreservedOpenState = child == mSlideableView; 631e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 632e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 633e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 634e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 635e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public boolean onInterceptTouchEvent(MotionEvent ev) { 636e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int action = MotionEventCompat.getActionMasked(ev); 637e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 638e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // Preserve the open state based on the last view that was touched. 639e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (!mCanSlide && action == MotionEvent.ACTION_DOWN && getChildCount() > 1) { 640e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // After the first things will be slideable. 641e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final View secondChild = getChildAt(1); 642e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (secondChild != null) { 643e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mPreservedOpenState = !mDragHelper.isViewUnder(secondChild, 644e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee (int) ev.getX(), (int) ev.getY()); 645e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 646e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 647e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 648e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (!mCanSlide || (mIsUnableToDrag && action != MotionEvent.ACTION_DOWN)) { 649e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mDragHelper.cancel(); 650e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return super.onInterceptTouchEvent(ev); 651e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 652e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 653e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { 654e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mDragHelper.cancel(); 655e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return false; 656e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 657e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 658e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee boolean interceptTap = false; 659e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 660e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee switch (action) { 661e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee case MotionEvent.ACTION_DOWN: { 662e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mIsUnableToDrag = false; 663e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final float x = ev.getX(); 664e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final float y = ev.getY(); 665e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mInitialMotionX = x; 666e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mInitialMotionY = y; 667e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 668e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (mDragHelper.isViewUnder(mSlideableView, (int) x, (int) y) && 669e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee isDimmed(mSlideableView)) { 670e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee interceptTap = true; 671e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 672e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee break; 673e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 674e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 675e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee case MotionEvent.ACTION_MOVE: { 676e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final float x = ev.getX(); 677e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final float y = ev.getY(); 678e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final float adx = Math.abs(x - mInitialMotionX); 679e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final float ady = Math.abs(y - mInitialMotionY); 680e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int slop = mDragHelper.getTouchSlop(); 681e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (ady > slop && adx > ady || !isCapturableViewUnder((int) x, (int) y)) { 682e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mDragHelper.cancel(); 683e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mIsUnableToDrag = true; 684e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return false; 685e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 686e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 687e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 688e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 689e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final boolean interceptForDrag = mDragHelper.shouldInterceptTouchEvent(ev); 690e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 691e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return interceptForDrag || interceptTap; 692e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 693e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 694e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 695e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public boolean onTouchEvent(MotionEvent ev) { 696e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (!mCanSlide) { 697e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return super.onTouchEvent(ev); 698e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 699e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 700e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mDragHelper.processTouchEvent(ev); 701e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 702e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int action = ev.getAction(); 703e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee boolean wantTouchEvents = true; 704e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 705e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee switch (action & MotionEventCompat.ACTION_MASK) { 706e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee case MotionEvent.ACTION_DOWN: { 707e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final float x = ev.getX(); 708e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final float y = ev.getY(); 709e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mInitialMotionX = x; 710e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mInitialMotionY = y; 711e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee break; 712e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 713e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 714e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee case MotionEvent.ACTION_UP: { 715e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (isDimmed(mSlideableView)) { 716e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final float x = ev.getX(); 717e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final float y = ev.getY(); 718e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final float dx = x - mInitialMotionX; 719e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final float dy = y - mInitialMotionY; 720e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int slop = mDragHelper.getTouchSlop(); 721e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (dx * dx + dy * dy < slop * slop && 722e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mDragHelper.isViewUnder(mSlideableView, (int) x, (int) y)) { 723e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // Taps close a dimmed open pane. 724e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee closePane(mSlideableView, 0); 725e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee break; 726e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 727e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 728e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee break; 729e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 730e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 731e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 732e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return wantTouchEvents; 733e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 734e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 735e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private boolean closePane(View pane, int initialVelocity) { 736e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (mFirstLayout || smoothSlideTo(0.f, initialVelocity)) { 737e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mPreservedOpenState = false; 738e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return true; 739e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 740e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return false; 741e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 742e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 743e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private boolean openPane(View pane, int initialVelocity) { 744e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (mFirstLayout || smoothSlideTo(1.f, initialVelocity)) { 745e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mPreservedOpenState = true; 746e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return true; 747e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 748e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return false; 749e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 750e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 751e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 752e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * Open the sliding pane if it is currently slideable. If first layout 753e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * has already completed this will animate. 754e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * 755e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * @return true if the pane was slideable and is now open/in the process of opening 756e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 757e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public boolean openPane() { 758e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return openPane(mSlideableView, 0); 759e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 760e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 761e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 762e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * Close the sliding pane if it is currently slideable. If first layout 763e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * has already completed this will animate. 764e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * 765e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * @return true if the pane was slideable and is now closed/in the process of closing 766e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 767e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public boolean closePane() { 768e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return closePane(mSlideableView, 0); 769e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 770e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 771e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 772e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * Check if the layout is completely open. It can be open either because the slider 773e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * itself is open revealing the left pane, or if all content fits without sliding. 774e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * 775e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * @return true if sliding panels are completely open 776e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 777e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public boolean isOpen() { 778e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return !mCanSlide || mSlideOffset == 1; 779e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 780e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 781e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 782e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * Check if the content in this layout cannot fully fit side by side and therefore 783e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * the content pane can be slid back and forth. 784e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * 785e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * @return true if content in this layout can be slid open and closed 786e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 787e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public boolean isSlideable() { 788e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return mCanSlide; 789e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 790e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 791e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private void onPanelDragged(int newTop) { 792e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (mSlideableView == null) { 793e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // This can happen if we're aborting motion during layout because everything now fits. 794e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mSlideOffset = 0; 795e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return; 796e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 797e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final LayoutParams lp = (LayoutParams) mSlideableView.getLayoutParams(); 798e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 799e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int lpMargin = lp.topMargin; 800e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int topBound = getPaddingTop() + lpMargin; 801e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 802e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mSlideOffset = (float) (newTop - topBound) / mSlideRange; 803e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 804e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (lp.dimWhenOffset) { 805e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dimChildView(mSlideableView, mSlideOffset, mSliderFadeColor); 806e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 807e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dispatchOnPanelSlide(mSlideableView); 808e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 809e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 810e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private void dimChildView(View v, float mag, int fadeColor) { 811e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final LayoutParams lp = (LayoutParams) v.getLayoutParams(); 812e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 813e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (mag > 0 && fadeColor != 0) { 814e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int baseAlpha = (fadeColor & 0xff000000) >>> 24; 815e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int imag = (int) (baseAlpha * mag); 816e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int color = imag << 24 | (fadeColor & 0xffffff); 817e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (lp.dimPaint == null) { 818e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee lp.dimPaint = new Paint(); 819e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 820e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee lp.dimPaint.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_OVER)); 821e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (ViewCompat.getLayerType(v) != ViewCompat.LAYER_TYPE_HARDWARE) { 822e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee ViewCompat.setLayerType(v, ViewCompat.LAYER_TYPE_HARDWARE, lp.dimPaint); 823e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 824e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee invalidateChildRegion(v); 825e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else if (ViewCompat.getLayerType(v) != ViewCompat.LAYER_TYPE_NONE) { 826e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (lp.dimPaint != null) { 827e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee lp.dimPaint.setColorFilter(null); 828e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 829e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final DisableLayerRunnable dlr = new DisableLayerRunnable(v); 830e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mPostedRunnables.add(dlr); 831e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee ViewCompat.postOnAnimation(this, dlr); 832e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 833e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 834e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 835e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 836e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee protected boolean drawChild(Canvas canvas, View child, long drawingTime) { 837e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 838e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee boolean result; 839e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int save = canvas.save(Canvas.CLIP_SAVE_FLAG); 840e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 841e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (mCanSlide && !lp.slideable && mSlideableView != null) { 842e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // Clip against the slider; no sense drawing what will immediately be covered. 843e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee canvas.getClipBounds(mTmpRect); 844e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 845e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mTmpRect.bottom = Math.min(mTmpRect.bottom, mSlideableView.getTop()); 846e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee canvas.clipRect(mTmpRect); 847e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 848e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 849e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (Build.VERSION.SDK_INT >= 11) { // HC 850e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee result = super.drawChild(canvas, child, drawingTime); 851e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else { 852e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (lp.dimWhenOffset && mSlideOffset > 0) { 853e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (!child.isDrawingCacheEnabled()) { 854e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee child.setDrawingCacheEnabled(true); 855e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 856e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final Bitmap cache = child.getDrawingCache(); 857e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (cache != null) { 858e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee canvas.drawBitmap(cache, child.getLeft(), child.getTop(), lp.dimPaint); 859e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee result = false; 860e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else { 861e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee Log.e(TAG, "drawChild: child view " + child + " returned null drawing cache"); 862e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee result = super.drawChild(canvas, child, drawingTime); 863e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 864e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else { 865e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (child.isDrawingCacheEnabled()) { 866e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee child.setDrawingCacheEnabled(false); 867e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 868e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee result = super.drawChild(canvas, child, drawingTime); 869e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 870e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 871e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 872e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee canvas.restoreToCount(save); 873e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 874e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return result; 875e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 876e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 877e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private void invalidateChildRegion(View v) { 878e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee ViewCompat.setLayerPaint(v, ((LayoutParams) v.getLayoutParams()).dimPaint); 879e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 880e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 881e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 882e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * Smoothly animate mDraggingPane to the target X position within its range. 883e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * 884e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * @param slideOffset position to animate to 885e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * @param velocity initial velocity in case of fling, or 0. 886e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 887e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee boolean smoothSlideTo(float slideOffset, int velocity) { 888e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (!mCanSlide) { 889e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // Nothing to do. 890e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return false; 891e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 892e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 893e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final LayoutParams lp = (LayoutParams) mSlideableView.getLayoutParams(); 894e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 895e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int y; 896e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int topBound = getPaddingTop() + lp.topMargin; 897e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee y = (int) (topBound + slideOffset * mSlideRange); 898e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 899e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (mDragHelper.smoothSlideViewTo(mSlideableView, mSlideableView.getLeft(), y)) { 900e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee setAllChildrenVisible(); 901e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee ViewCompat.postInvalidateOnAnimation(this); 902e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return true; 903e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 904e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return false; 905e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 906e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 907e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 908e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public void computeScroll() { 909e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (mDragHelper.continueSettling(true)) { 910e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (!mCanSlide) { 911e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mDragHelper.abort(); 912e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return; 913e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 914e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 915e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee ViewCompat.postInvalidateOnAnimation(this); 916e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 917e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 918e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 919e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private boolean isCapturableViewUnder(int x, int y) { 920e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee View capturableView = mCapturableView != null ? mCapturableView : mSlideableView; 921e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (capturableView == null) { 922e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return false; 923e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 924e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int[] viewLocation = new int[2]; 925e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee capturableView.getLocationOnScreen(viewLocation); 926e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int[] parentLocation = new int[2]; 927e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee this.getLocationOnScreen(parentLocation); 928e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int screenX = parentLocation[0] + x; 929e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int screenY = parentLocation[1] + y; 930e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return screenX >= viewLocation[0] 931e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee && screenX < viewLocation[0] + capturableView.getWidth() 932e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee && screenY >= viewLocation[1] 933e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee && screenY < viewLocation[1] + capturableView.getHeight(); 934e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 935e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 936e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee boolean isDimmed(View child) { 937e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (child == null) { 938e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return false; 939e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 940e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 941e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return mCanSlide && lp.dimWhenOffset && mSlideOffset > 0; 942e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 943e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 944e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 945e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee protected ViewGroup.LayoutParams generateDefaultLayoutParams() { 946e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return new LayoutParams(); 947e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 948e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 949e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 950e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 951e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return p instanceof MarginLayoutParams 952e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee ? new LayoutParams((MarginLayoutParams) p) 953e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee : new LayoutParams(p); 954e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 955e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 956e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 957e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 958e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return p instanceof LayoutParams && super.checkLayoutParams(p); 959e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 960e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 961e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 962e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { 963e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return new LayoutParams(getContext(), attrs); 964e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 965e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 966e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 967e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee protected Parcelable onSaveInstanceState() { 968e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee Parcelable superState = super.onSaveInstanceState(); 969e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 970e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee SavedState ss = new SavedState(superState); 971e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee ss.isOpen = isSlideable() ? isOpen() : mPreservedOpenState; 972e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 973e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return ss; 974e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 975e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 976e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 977e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee protected void onRestoreInstanceState(Parcelable state) { 978e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee SavedState ss = (SavedState) state; 979e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee super.onRestoreInstanceState(ss.getSuperState()); 980e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 981e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (ss.isOpen) { 982e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee openPane(); 983e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else { 984e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee closePane(); 985e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 986e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mPreservedOpenState = ss.isOpen; 987e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 988e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 989e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private class DragHelperCallback extends ViewDragHelper.Callback { 990e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 991e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 992e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public boolean tryCaptureView(View child, int pointerId) { 993e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (mIsUnableToDrag) { 994e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return false; 995e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 996e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 997e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return ((LayoutParams) child.getLayoutParams()).slideable; 998e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 999e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1000e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 1001e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public void onViewDragStateChanged(int state) { 1002e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (mDragHelper.getViewDragState() == ViewDragHelper.STATE_IDLE) { 1003e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (mSlideOffset == 0) { 1004e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee updateObscuredViewsVisibility(mSlideableView); 1005e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dispatchOnPanelClosed(mSlideableView); 1006e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mPreservedOpenState = false; 1007e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } else { 1008e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dispatchOnPanelOpened(mSlideableView); 1009e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mPreservedOpenState = true; 1010e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1011e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1012e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1013e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1014e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 1015e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public void onViewCaptured(View capturedChild, int activePointerId) { 1016e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // Make all child views visible in preparation for sliding things around 1017e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee setAllChildrenVisible(); 1018e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1019e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1020e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 1021e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { 1022e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee onPanelDragged(top); 1023e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee invalidate(); 1024e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1025e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1026e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 1027e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public void onViewReleased(View releasedChild, float xvel, float yvel) { 1028e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final LayoutParams lp = (LayoutParams) releasedChild.getLayoutParams(); 1029e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1030e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int top = getPaddingTop() + lp.topMargin; 1031e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (yvel > 0 || (yvel == 0 && mSlideOffset > 0.5f)) { 1032e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee top += mSlideRange; 1033e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1034e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1035e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int left; 1036e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mDragHelper.settleCapturedViewAt(releasedChild.getLeft(), top); 1037e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee invalidate(); 1038e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1039e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1040e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 1041e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public int getViewVerticalDragRange(View child) { 1042e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return mSlideRange; 1043e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1044e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1045e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 1046e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public int clampViewPositionHorizontal(View child, int left, int dx) { 1047e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // Make sure we never move views horizontally. 1048e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return child.getLeft(); 1049e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1050e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1051e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 1052e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public int clampViewPositionVertical(View child, int top, int dy) { 1053e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final LayoutParams lp = (LayoutParams) mSlideableView.getLayoutParams(); 1054e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1055e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int newTop; 1056e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int topBound = getPaddingTop() + lp.topMargin; 1057e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee int bottomBound = topBound + mSlideRange; 1058e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee newTop = Math.min(Math.max(top, topBound), bottomBound); 1059e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1060e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return newTop; 1061e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1062e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1063e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 1064e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public void onEdgeDragStarted(int edgeFlags, int pointerId) { 1065e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mDragHelper.captureChildView(mSlideableView, pointerId); 1066e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1067e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1068e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1069e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public static class LayoutParams extends ViewGroup.MarginLayoutParams { 1070e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private static final int[] ATTRS = new int[] { 1071e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee android.R.attr.layout_weight 1072e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee }; 1073e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1074e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 1075e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * The weighted proportion of how much of the leftover space 1076e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * this child should consume after measurement. 1077e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 1078e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public float weight = 0; 1079e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1080e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 1081e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * True if this pane is the slideable pane in the layout. 1082e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 1083e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee boolean slideable; 1084e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1085e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 1086e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * True if this view should be drawn dimmed 1087e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * when it's been offset from its default position. 1088e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 1089e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee boolean dimWhenOffset; 1090e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1091e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee Paint dimPaint; 1092e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1093e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public LayoutParams() { 1094e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee super(FILL_PARENT, FILL_PARENT); 1095e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1096e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1097e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public LayoutParams(int width, int height) { 1098e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee super(width, height); 1099e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1100e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1101e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public LayoutParams(android.view.ViewGroup.LayoutParams source) { 1102e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee super(source); 1103e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1104e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1105e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public LayoutParams(MarginLayoutParams source) { 1106e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee super(source); 1107e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1108e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1109e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public LayoutParams(LayoutParams source) { 1110e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee super(source); 1111e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee this.weight = source.weight; 1112e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1113e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1114e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public LayoutParams(Context c, AttributeSet attrs) { 1115e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee super(c, attrs); 1116e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1117e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final TypedArray a = c.obtainStyledAttributes(attrs, ATTRS); 1118e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee this.weight = a.getFloat(0, 0); 1119e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee a.recycle(); 1120e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1121e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1122e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1123e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1124e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee static class SavedState extends BaseSavedState { 1125e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee boolean isOpen; 1126e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1127e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee SavedState(Parcelable superState) { 1128e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee super(superState); 1129e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1130e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1131e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private SavedState(Parcel in) { 1132e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee super(in); 1133e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee isOpen = in.readInt() != 0; 1134e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1135e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1136e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 1137e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public void writeToParcel(Parcel out, int flags) { 1138e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee super.writeToParcel(out, flags); 1139e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee out.writeInt(isOpen ? 1 : 0); 1140e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1141e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1142e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public static final Parcelable.Creator<SavedState> CREATOR = 1143e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee new Parcelable.Creator<SavedState>() { 1144e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public SavedState createFromParcel(Parcel in) { 1145e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return new SavedState(in); 1146e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1147e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1148e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public SavedState[] newArray(int size) { 1149e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return new SavedState[size]; 1150e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1151e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee }; 1152e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1153e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1154e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee class AccessibilityDelegate extends AccessibilityDelegateCompat { 1155e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private final Rect mTmpRect = new Rect(); 1156e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1157e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 1158e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { 1159e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final AccessibilityNodeInfoCompat superNode = AccessibilityNodeInfoCompat.obtain(info); 1160e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee super.onInitializeAccessibilityNodeInfo(host, superNode); 1161e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee copyNodeInfoNoChildren(info, superNode); 1162e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee superNode.recycle(); 1163e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1164e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee info.setClassName(OverlappingPaneLayout.class.getName()); 1165e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee info.setSource(host); 1166e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1167e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final ViewParent parent = ViewCompat.getParentForAccessibility(host); 1168e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (parent instanceof View) { 1169e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee info.setParent((View) parent); 1170e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1171e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1172e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // This is a best-approximation of addChildrenForAccessibility() 1173e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // that accounts for filtering. 1174e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final int childCount = getChildCount(); 1175e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee for (int i = 0; i < childCount; i++) { 1176e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final View child = getChildAt(i); 1177e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (!filter(child) && (child.getVisibility() == View.VISIBLE)) { 1178e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee // Force importance to "yes" since we can't read the value. 1179e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee ViewCompat.setImportantForAccessibility( 1180e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee child, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES); 1181e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee info.addChild(child); 1182e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1183e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1184e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1185e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1186e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 1187e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { 1188e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee super.onInitializeAccessibilityEvent(host, event); 1189e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1190e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee event.setClassName(OverlappingPaneLayout.class.getName()); 1191e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1192e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1193e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 1194e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, 1195e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee AccessibilityEvent event) { 1196e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (!filter(child)) { 1197e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return super.onRequestSendAccessibilityEvent(host, child, event); 1198e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1199e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return false; 1200e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1201e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1202e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public boolean filter(View child) { 1203e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee return isDimmed(child); 1204e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1205e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1206e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee /** 1207e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * This should really be in AccessibilityNodeInfoCompat, but there unfortunately 1208e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * seem to be a few elements that are not easily cloneable using the underlying API. 1209e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee * Leave it private here as it's not general-purpose useful. 1210e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee */ 1211e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private void copyNodeInfoNoChildren(AccessibilityNodeInfoCompat dest, 1212e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee AccessibilityNodeInfoCompat src) { 1213e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final Rect rect = mTmpRect; 1214e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1215e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee src.getBoundsInParent(rect); 1216e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dest.setBoundsInParent(rect); 1217e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1218e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee src.getBoundsInScreen(rect); 1219e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dest.setBoundsInScreen(rect); 1220e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1221e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dest.setVisibleToUser(src.isVisibleToUser()); 1222e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dest.setPackageName(src.getPackageName()); 1223e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dest.setClassName(src.getClassName()); 1224e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dest.setContentDescription(src.getContentDescription()); 1225e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1226e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dest.setEnabled(src.isEnabled()); 1227e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dest.setClickable(src.isClickable()); 1228e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dest.setFocusable(src.isFocusable()); 1229e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dest.setFocused(src.isFocused()); 1230e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dest.setAccessibilityFocused(src.isAccessibilityFocused()); 1231e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dest.setSelected(src.isSelected()); 1232e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dest.setLongClickable(src.isLongClickable()); 1233e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1234e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dest.addAction(src.getActions()); 1235e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1236e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee dest.setMovementGranularities(src.getMovementGranularities()); 1237e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1238e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1239e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1240e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee private class DisableLayerRunnable implements Runnable { 1241e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee final View mChildView; 1242e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1243e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee DisableLayerRunnable(View childView) { 1244e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mChildView = childView; 1245e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1246e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee 1247e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee @Override 1248e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee public void run() { 1249e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee if (mChildView.getParent() == OverlappingPaneLayout.this) { 1250e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee ViewCompat.setLayerType(mChildView, ViewCompat.LAYER_TYPE_NONE, null); 1251e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee invalidateChildRegion(mChildView); 1252e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1253e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee mPostedRunnables.remove(this); 1254e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1255e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee } 1256e709fd21eda44df07327f649e4e6a257918555a9Yorke Lee} 1257