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