ViewPager.java revision 23f32662b0e412510094d59c478f1d5370a15244
1d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn/* 2d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * Copyright (C) 2011 The Android Open Source Project 3d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * 4d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License"); 5d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * you may not use this file except in compliance with the License. 6d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * You may obtain a copy of the License at 7d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * 8d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * http://www.apache.org/licenses/LICENSE-2.0 9d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * 10d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * Unless required by applicable law or agreed to in writing, software 11d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS, 12d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * See the License for the specific language governing permissions and 14d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * limitations under the License. 15d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn */ 16d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 175c1637087453de15e31861f073eae5133c4e9f7bDianne Hackbornpackage android.support.v4.view; 18d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 19481243c175651c5de0741ab9390eb10f5b024d98Adam Powellimport android.content.Context; 20199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powellimport android.content.res.Resources; 218fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powellimport android.content.res.TypedArray; 228fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powellimport android.database.DataSetObserver; 23560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powellimport android.graphics.Canvas; 24481243c175651c5de0741ab9390eb10f5b024d98Adam Powellimport android.graphics.Rect; 25329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powellimport android.graphics.drawable.Drawable; 265de8804b248eebaf7c29113ec80a0dff3a03c97aAdam Powellimport android.os.Build; 2725121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganovimport android.os.Bundle; 28d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackbornimport android.os.Parcel; 29d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackbornimport android.os.Parcelable; 3069b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powellimport android.os.SystemClock; 315c1637087453de15e31861f073eae5133c4e9f7bDianne Hackbornimport android.support.v4.os.ParcelableCompat; 325c1637087453de15e31861f073eae5133c4e9f7bDianne Hackbornimport android.support.v4.os.ParcelableCompatCreatorCallbacks; 3325121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganovimport android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; 34560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powellimport android.support.v4.widget.EdgeEffectCompat; 35d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackbornimport android.util.AttributeSet; 36d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackbornimport android.util.Log; 372a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackbornimport android.view.FocusFinder; 388fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powellimport android.view.Gravity; 392a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackbornimport android.view.KeyEvent; 40d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackbornimport android.view.MotionEvent; 412a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackbornimport android.view.SoundEffectConstants; 42d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackbornimport android.view.VelocityTracker; 43d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackbornimport android.view.View; 44d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackbornimport android.view.ViewConfiguration; 45d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackbornimport android.view.ViewGroup; 46218c1e661578e2a17928f7dbb590b43d1c79aeb7Dianne Hackbornimport android.view.ViewParent; 47481243c175651c5de0741ab9390eb10f5b024d98Adam Powellimport android.view.accessibility.AccessibilityEvent; 481cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powellimport android.view.animation.Interpolator; 49d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackbornimport android.widget.Scroller; 50d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 518a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powellimport java.lang.reflect.Method; 52d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackbornimport java.util.ArrayList; 5366c0e6a0a5fd20c66b6c86133b8bd91fe303e430Minh Phamimport java.util.Collections; 5466c0e6a0a5fd20c66b6c86133b8bd91fe303e430Minh Phamimport java.util.Comparator; 55d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 56d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn/** 57d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * Layout manager that allows the user to flip left and right 585c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn * through pages of data. You supply an implementation of a 595c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn * {@link PagerAdapter} to generate the pages that the view shows. 605c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn * 615c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn * <p>Note this class is currently under early design and 625c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn * development. The API will likely change in later updates of 635c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn * the compatibility library, requiring changes to the source code 645c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn * of apps when they are compiled against the newer version.</p> 657dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * 667dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * <p>ViewPager is most often used in conjunction with {@link android.app.Fragment}, 677dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * which is a convenient way to supply and manage the lifecycle of each page. 687dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * There are standard adapters implemented for using fragments with the ViewPager, 697dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * which cover the most common use cases. These are 7033586fb4d8b42d7c65240ffcc269fe10e682b309Scott Main * {@link android.support.v4.app.FragmentPagerAdapter} and 7133586fb4d8b42d7c65240ffcc269fe10e682b309Scott Main * {@link android.support.v4.app.FragmentStatePagerAdapter}; each of these 727dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * classes have simple code showing how to build a full user interface 737dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * with them. 747dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * 757dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * <p>Here is a more complicated example of ViewPager, using it in conjuction 767dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * with {@link android.app.ActionBar} tabs. You can find other examples of using 777dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * ViewPager in the API 4+ Support Demos and API 13+ Support Demos sample code. 787dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * 797dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * {@sample development/samples/Support13Demos/src/com/example/android/supportv13/app/ActionBarTabsPager.java 807dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * complete} 81d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn */ 82ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackbornpublic class ViewPager extends ViewGroup { 833661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell private static final String TAG = "ViewPager"; 84d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private static final boolean DEBUG = false; 85d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 86d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private static final boolean USE_CACHE = false; 87d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 8829a6184d74279156a9297dc67398712fb047fdc0Adam Powell private static final int DEFAULT_OFFSCREEN_PAGES = 1; 891cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell private static final int MAX_SETTLE_DURATION = 600; // ms 90035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell private static final int MIN_DISTANCE_FOR_FLING = 25; // dips 9129a6184d74279156a9297dc67398712fb047fdc0Adam Powell 928f19b17dbc34bfc7e5caacbf83a7099e5cb5a47cAdam Powell private static final int DEFAULT_GUTTER_SIZE = 16; // dips 938f19b17dbc34bfc7e5caacbf83a7099e5cb5a47cAdam Powell 9416991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell private static final int MIN_FLING_VELOCITY = 400; // dips 9516991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell 968fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private static final int[] LAYOUT_ATTRS = new int[] { 978fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell android.R.attr.layout_gravity 988fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell }; 998fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 100199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell /** 101199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell * Used to track what the expected number of items in the adapter should be. 102199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell * If the app changes this when we don't expect it, we'll throw a big obnoxious exception. 103199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell */ 104199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell private int mExpectedAdapterCount; 105199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell 106d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn static class ItemInfo { 107ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn Object object; 108d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn int position; 1094c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn boolean scrolling; 110a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell float widthFactor; 111a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell float offset; 112d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 113d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 11466c0e6a0a5fd20c66b6c86133b8bd91fe303e430Minh Pham private static final Comparator<ItemInfo> COMPARATOR = new Comparator<ItemInfo>(){ 11566c0e6a0a5fd20c66b6c86133b8bd91fe303e430Minh Pham @Override 11666c0e6a0a5fd20c66b6c86133b8bd91fe303e430Minh Pham public int compare(ItemInfo lhs, ItemInfo rhs) { 11766c0e6a0a5fd20c66b6c86133b8bd91fe303e430Minh Pham return lhs.position - rhs.position; 118a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 119a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell }; 12066c0e6a0a5fd20c66b6c86133b8bd91fe303e430Minh Pham 1211cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell private static final Interpolator sInterpolator = new Interpolator() { 1221cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell public float getInterpolation(float t) { 1231cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell t -= 1.0f; 124035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell return t * t * t * t * t + 1.0f; 1251cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell } 1261cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell }; 1271cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell 128d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>(); 129a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell private final ItemInfo mTempItem = new ItemInfo(); 130d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 131dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell private final Rect mTempRect = new Rect(); 132dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell 133ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn private PagerAdapter mAdapter; 1343661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell private int mCurItem; // Index of currently displayed page. 135d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private int mRestoredCurItem = -1; 136ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn private Parcelable mRestoredAdapterState = null; 1375c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn private ClassLoader mRestoredClassLoader = null; 138d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private Scroller mScroller; 1398fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private PagerObserver mObserver; 140d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 141329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell private int mPageMargin; 142329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell private Drawable mMarginDrawable; 1438fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private int mTopPageBounds; 1448fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private int mBottomPageBounds; 145329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell 146a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // Offsets of the first and last items, if known. 147a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // Set during population, used to determine if we are at the beginning 148a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // or end of the pager data set during touch scrolling. 149a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell private float mFirstOffset = -Float.MAX_VALUE; 150a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell private float mLastOffset = Float.MAX_VALUE; 151a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 152d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private int mChildWidthMeasureSpec; 153d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private int mChildHeightMeasureSpec; 154d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private boolean mInLayout; 155d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 156d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private boolean mScrollingCacheEnabled; 157d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 158d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private boolean mPopulatePending; 15929a6184d74279156a9297dc67398712fb047fdc0Adam Powell private int mOffscreenPageLimit = DEFAULT_OFFSCREEN_PAGES; 160d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 161d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private boolean mIsBeingDragged; 162d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private boolean mIsUnableToDrag; 1638f19b17dbc34bfc7e5caacbf83a7099e5cb5a47cAdam Powell private boolean mIgnoreGutter; 1648f19b17dbc34bfc7e5caacbf83a7099e5cb5a47cAdam Powell private int mDefaultGutterSize; 1658f19b17dbc34bfc7e5caacbf83a7099e5cb5a47cAdam Powell private int mGutterSize; 166d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private int mTouchSlop; 167d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn /** 168d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * Position of the last motion event. 169d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn */ 170d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private float mLastMotionX; 171d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private float mLastMotionY; 17216991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell private float mInitialMotionX; 17316991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell private float mInitialMotionY; 174d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn /** 175d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * ID of the active pointer. This is used to retain consistency during 176d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * drags/flings if multiple pointers are used. 177d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn */ 178d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private int mActivePointerId = INVALID_POINTER; 179d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn /** 180d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * Sentinel value for no current active pointer. 181d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * Used by {@link #mActivePointerId}. 182d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn */ 183d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private static final int INVALID_POINTER = -1; 184d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 185d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn /** 186d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * Determines speed during touch scrolling 187d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn */ 188d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private VelocityTracker mVelocityTracker; 189d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private int mMinimumVelocity; 190d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private int mMaximumVelocity; 191035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell private int mFlingDistance; 192b469af6dc2f8cda4020a78fb4582c1483089fd6eAdam Powell private int mCloseEnough; 193b469af6dc2f8cda4020a78fb4582c1483089fd6eAdam Powell 194b469af6dc2f8cda4020a78fb4582c1483089fd6eAdam Powell // If the pager is at least this close to its final position, complete the scroll 195b469af6dc2f8cda4020a78fb4582c1483089fd6eAdam Powell // on touch down and let the user interact with the content inside instead of 196b469af6dc2f8cda4020a78fb4582c1483089fd6eAdam Powell // "catching" the flinging pager. 197b469af6dc2f8cda4020a78fb4582c1483089fd6eAdam Powell private static final int CLOSE_ENOUGH = 2; // dp 198d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 19969b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell private boolean mFakeDragging; 20069b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell private long mFakeDragBeginTime; 20169b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell 202560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell private EdgeEffectCompat mLeftEdge; 203560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell private EdgeEffectCompat mRightEdge; 204560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 20597d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell private boolean mFirstLayout = true; 206a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell private boolean mNeedCalculatePageOffsets = false; 2078fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private boolean mCalledSuper; 2088fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private int mDecorChildCount; 20997d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell 2103661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell private OnPageChangeListener mOnPageChangeListener; 2118fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private OnPageChangeListener mInternalPageChangeListener; 2128fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private OnAdapterChangeListener mAdapterChangeListener; 2138a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell private PageTransformer mPageTransformer; 2148a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell private Method mSetChildrenDrawingOrderEnabled; 2153661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 2167e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell private static final int DRAW_ORDER_DEFAULT = 0; 2177e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell private static final int DRAW_ORDER_FORWARD = 1; 2187e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell private static final int DRAW_ORDER_REVERSE = 2; 2197e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell private int mDrawingOrder; 2207e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell private ArrayList<View> mDrawingOrderedChildren; 2217e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell private static final ViewPositionComparator sPositionComparator = new ViewPositionComparator(); 2227e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell 2233661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell /** 22447dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell * Indicates that the pager is in an idle, settled state. The current page 22547dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell * is fully in view and no animation is in progress. 22647dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell */ 22747dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell public static final int SCROLL_STATE_IDLE = 0; 22847dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell 22947dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell /** 23047dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell * Indicates that the pager is currently being dragged by the user. 23147dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell */ 23247dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell public static final int SCROLL_STATE_DRAGGING = 1; 23347dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell 23447dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell /** 23547dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell * Indicates that the pager is in the process of settling to a final position. 23647dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell */ 23747dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell public static final int SCROLL_STATE_SETTLING = 2; 23847dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell 23971d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio private final Runnable mEndScrollRunnable = new Runnable() { 24071d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio public void run() { 24171d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio setScrollState(SCROLL_STATE_IDLE); 24271d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio populate(); 24371d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio } 24471d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio }; 24571d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio 24647dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell private int mScrollState = SCROLL_STATE_IDLE; 24747dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell 24847dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell /** 2493661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell * Callback interface for responding to changing state of the selected page. 2503661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell */ 2513661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell public interface OnPageChangeListener { 25247dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell 2533661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell /** 2543661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell * This method will be invoked when the current page is scrolled, either as part 2553661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell * of a programmatically initiated smooth scroll or a user initiated touch scroll. 2563661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell * 2573661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell * @param position Position index of the first page currently being displayed. 2583661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell * Page position+1 will be visible if positionOffset is nonzero. 2593661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell * @param positionOffset Value from [0, 1) indicating the offset from the page at position. 2603661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell * @param positionOffsetPixels Value in pixels indicating the offset from position. 2613661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell */ 2623661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels); 2633661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 2643661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell /** 26547dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell * This method will be invoked when a new page becomes selected. Animation is not 26647dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell * necessarily complete. 2673661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell * 2683661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell * @param position Position index of the new selected page. 2693661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell */ 2703661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell public void onPageSelected(int position); 27147dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell 27247dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell /** 27347dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell * Called when the scroll state changes. Useful for discovering when the user 27447dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell * begins dragging, when the pager is automatically settling to the current page, 27547dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell * or when it is fully stopped/idle. 27647dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell * 27747dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell * @param state The new scroll state. 27847dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell * @see ViewPager#SCROLL_STATE_IDLE 27947dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell * @see ViewPager#SCROLL_STATE_DRAGGING 28047dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell * @see ViewPager#SCROLL_STATE_SETTLING 28147dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell */ 28247dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell public void onPageScrollStateChanged(int state); 2833661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 2843661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 2853661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell /** 2863661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell * Simple implementation of the {@link OnPageChangeListener} interface with stub 2873661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell * implementations of each method. Extend this if you do not intend to override 2883661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell * every method of {@link OnPageChangeListener}. 2893661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell */ 2903661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell public static class SimpleOnPageChangeListener implements OnPageChangeListener { 2913661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell @Override 2923661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 2933661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell // This space for rent 2943661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 2953661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 2963661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell @Override 2973661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell public void onPageSelected(int position) { 2983661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell // This space for rent 2993661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 30047dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell 30147dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell @Override 30247dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell public void onPageScrollStateChanged(int state) { 30347dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell // This space for rent 30447dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell } 3053661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 3063661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 3078fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell /** 3088a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * A PageTransformer is invoked whenever a visible/attached page is scrolled. 3098a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * This offers an opportunity for the application to apply a custom transformation 3108a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * to the page views using animation properties. 3118a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * 3128a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * <p>As property animation is only supported as of Android 3.0 and forward, 3138a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * setting a PageTransformer on a ViewPager on earlier platform versions will 3148a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * be ignored.</p> 3158a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell */ 3168a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell public interface PageTransformer { 3178a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell /** 3188a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * Apply a property transformation to the given page. 3198a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * 3208a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * @param page Apply the transformation to this page 3218a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * @param position Position of page relative to the current front-and-center 3228a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * position of the pager. 0 is front and center. 1 is one full 3238a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * page position to the right, and -1 is one page position to the left. 3248a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell */ 3258a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell public void transformPage(View page, float position); 3268a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell } 3278a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell 3288a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell /** 3298fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * Used internally to monitor when adapters are switched. 3308fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell */ 3318fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell interface OnAdapterChangeListener { 3328fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell public void onAdapterChanged(PagerAdapter oldAdapter, PagerAdapter newAdapter); 3338fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 3348fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 3351ccb8bcb79557d861de7f271c13e2fd8e54e012aAdam Powell /** 3361ccb8bcb79557d861de7f271c13e2fd8e54e012aAdam Powell * Used internally to tag special types of child views that should be added as 3371ccb8bcb79557d861de7f271c13e2fd8e54e012aAdam Powell * pager decorations by default. 3381ccb8bcb79557d861de7f271c13e2fd8e54e012aAdam Powell */ 3391ccb8bcb79557d861de7f271c13e2fd8e54e012aAdam Powell interface Decor {} 3401ccb8bcb79557d861de7f271c13e2fd8e54e012aAdam Powell 341ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn public ViewPager(Context context) { 342d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn super(context); 34347dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell initViewPager(); 344d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 345d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 346ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn public ViewPager(Context context, AttributeSet attrs) { 347d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn super(context, attrs); 34847dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell initViewPager(); 349d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 350d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 35147dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell void initViewPager() { 352d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn setWillNotDraw(false); 3532a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); 3542a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn setFocusable(true); 355560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell final Context context = getContext(); 3561cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell mScroller = new Scroller(context, sInterpolator); 3571cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell final ViewConfiguration configuration = ViewConfiguration.get(context); 35816991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell final float density = context.getResources().getDisplayMetrics().density; 35916991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell 360d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); 36116991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell mMinimumVelocity = (int) (MIN_FLING_VELOCITY * density); 362d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); 363560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell mLeftEdge = new EdgeEffectCompat(context); 364560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell mRightEdge = new EdgeEffectCompat(context); 3651cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell 366035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell mFlingDistance = (int) (MIN_DISTANCE_FOR_FLING * density); 367b469af6dc2f8cda4020a78fb4582c1483089fd6eAdam Powell mCloseEnough = (int) (CLOSE_ENOUGH * density); 3688f19b17dbc34bfc7e5caacbf83a7099e5cb5a47cAdam Powell mDefaultGutterSize = (int) (DEFAULT_GUTTER_SIZE * density); 36925121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov 37025121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov ViewCompat.setAccessibilityDelegate(this, new MyAccessibilityDelegate()); 37125121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov 37225121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov if (ViewCompat.getImportantForAccessibility(this) 37325121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov == ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO) { 37425121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov ViewCompat.setImportantForAccessibility(this, 37525121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES); 37625121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov } 377d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 378d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 37971d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio @Override 38071d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio protected void onDetachedFromWindow() { 38171d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio removeCallbacks(mEndScrollRunnable); 38271d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio super.onDetachedFromWindow(); 38371d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio } 38471d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio 38547dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell private void setScrollState(int newState) { 38647dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell if (mScrollState == newState) { 38747dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell return; 38847dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell } 38947dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell 39047dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell mScrollState = newState; 3918a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell if (mPageTransformer != null) { 3928a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell // PageTransformers can do complex things that benefit from hardware layers. 3938a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell enableLayers(newState != SCROLL_STATE_IDLE); 3948a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell } 39547dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell if (mOnPageChangeListener != null) { 39647dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell mOnPageChangeListener.onPageScrollStateChanged(newState); 39747dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell } 39847dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell } 39947dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell 4008fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell /** 4018fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * Set a PagerAdapter that will supply views for this pager as needed. 4028fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * 4038fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * @param adapter Adapter to use 4048fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell */ 405ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn public void setAdapter(PagerAdapter adapter) { 4063661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell if (mAdapter != null) { 4078fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mAdapter.unregisterDataSetObserver(mObserver); 4080d6d2990ddacd3f419879149137f09a30c061436Minh Pham mAdapter.startUpdate(this); 4090d6d2990ddacd3f419879149137f09a30c061436Minh Pham for (int i = 0; i < mItems.size(); i++) { 4100d6d2990ddacd3f419879149137f09a30c061436Minh Pham final ItemInfo ii = mItems.get(i); 4110d6d2990ddacd3f419879149137f09a30c061436Minh Pham mAdapter.destroyItem(this, ii.position, ii.object); 4120d6d2990ddacd3f419879149137f09a30c061436Minh Pham } 4130d6d2990ddacd3f419879149137f09a30c061436Minh Pham mAdapter.finishUpdate(this); 4140d6d2990ddacd3f419879149137f09a30c061436Minh Pham mItems.clear(); 415a7aea206661d601755bfac4165092d9130cba2bcAdam Powell removeNonDecorViews(); 4160d6d2990ddacd3f419879149137f09a30c061436Minh Pham mCurItem = 0; 417871a68b5daafd810623d680207652f87eb2d11ccMinh Pham scrollTo(0, 0); 4183661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 4193661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 4208fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final PagerAdapter oldAdapter = mAdapter; 421d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mAdapter = adapter; 422199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell mExpectedAdapterCount = 0; 423d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 424d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (mAdapter != null) { 4253661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell if (mObserver == null) { 4268fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mObserver = new PagerObserver(); 4273661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 4288fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mAdapter.registerDataSetObserver(mObserver); 429d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mPopulatePending = false; 430fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell final boolean wasFirstLayout = mFirstLayout; 43191eec7fd0b6ffdbb44cd13777950552f74f654e6Adam Powell mFirstLayout = true; 432199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell mExpectedAdapterCount = mAdapter.getCount(); 433d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (mRestoredCurItem >= 0) { 4345c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn mAdapter.restoreState(mRestoredAdapterState, mRestoredClassLoader); 435d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn setCurrentItemInternal(mRestoredCurItem, false, true); 436d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mRestoredCurItem = -1; 437ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn mRestoredAdapterState = null; 4385c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn mRestoredClassLoader = null; 439fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell } else if (!wasFirstLayout) { 440d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn populate(); 441fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell } else { 442fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell requestLayout(); 443d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 444d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 4458fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 4468fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (mAdapterChangeListener != null && oldAdapter != adapter) { 4478fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mAdapterChangeListener.onAdapterChanged(oldAdapter, adapter); 4488fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 449d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 450d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 451a7aea206661d601755bfac4165092d9130cba2bcAdam Powell private void removeNonDecorViews() { 452a7aea206661d601755bfac4165092d9130cba2bcAdam Powell for (int i = 0; i < getChildCount(); i++) { 453a7aea206661d601755bfac4165092d9130cba2bcAdam Powell final View child = getChildAt(i); 454a7aea206661d601755bfac4165092d9130cba2bcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 455a7aea206661d601755bfac4165092d9130cba2bcAdam Powell if (!lp.isDecor) { 456a7aea206661d601755bfac4165092d9130cba2bcAdam Powell removeViewAt(i); 457a7aea206661d601755bfac4165092d9130cba2bcAdam Powell i--; 458a7aea206661d601755bfac4165092d9130cba2bcAdam Powell } 459a7aea206661d601755bfac4165092d9130cba2bcAdam Powell } 460a7aea206661d601755bfac4165092d9130cba2bcAdam Powell } 461a7aea206661d601755bfac4165092d9130cba2bcAdam Powell 4628fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell /** 4638fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * Retrieve the current adapter supplying pages. 4648fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * 4658fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * @return The currently registered PagerAdapter 4668fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell */ 467ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn public PagerAdapter getAdapter() { 468d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn return mAdapter; 469d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 470d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 4718fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell void setOnAdapterChangeListener(OnAdapterChangeListener listener) { 4728fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mAdapterChangeListener = listener; 4738fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 4748fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 475becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu private int getClientWidth() { 476fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell return getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); 477becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu } 478becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu 47997d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell /** 48097d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell * Set the currently selected page. If the ViewPager has already been through its first 48191eec7fd0b6ffdbb44cd13777950552f74f654e6Adam Powell * layout with its current adapter there will be a smooth animated transition between 48291eec7fd0b6ffdbb44cd13777950552f74f654e6Adam Powell * the current item and the specified item. 48397d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell * 48497d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell * @param item Item index to select 48597d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell */ 486d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn public void setCurrentItem(int item) { 487d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mPopulatePending = false; 48897d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell setCurrentItemInternal(item, !mFirstLayout, false); 48997d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell } 49097d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell 49197d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell /** 49297d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell * Set the currently selected page. 49397d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell * 49497d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell * @param item Item index to select 49597d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell * @param smoothScroll True to smoothly scroll to the new item, false to transition immediately 49697d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell */ 49797d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell public void setCurrentItem(int item, boolean smoothScroll) { 49897d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell mPopulatePending = false; 49997d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell setCurrentItemInternal(item, smoothScroll, false); 500d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 501d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 502bd4398ce660db91dabde5db1e87890d5df0b0823Makoto Onuki public int getCurrentItem() { 503bd4398ce660db91dabde5db1e87890d5df0b0823Makoto Onuki return mCurItem; 504bd4398ce660db91dabde5db1e87890d5df0b0823Makoto Onuki } 505bd4398ce660db91dabde5db1e87890d5df0b0823Makoto Onuki 506d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) { 5071cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell setCurrentItemInternal(item, smoothScroll, always, 0); 5081cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell } 5091cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell 5101cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) { 511d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (mAdapter == null || mAdapter.getCount() <= 0) { 512d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn setScrollingCacheEnabled(false); 513d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn return; 514d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 515d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (!always && mCurItem == item && mItems.size() != 0) { 516d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn setScrollingCacheEnabled(false); 517d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn return; 518d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 5198d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell 520d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (item < 0) { 521d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn item = 0; 522d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } else if (item >= mAdapter.getCount()) { 523d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn item = mAdapter.getCount() - 1; 524d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 52529a6184d74279156a9297dc67398712fb047fdc0Adam Powell final int pageLimit = mOffscreenPageLimit; 52629a6184d74279156a9297dc67398712fb047fdc0Adam Powell if (item > (mCurItem + pageLimit) || item < (mCurItem - pageLimit)) { 5274c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn // We are doing a jump by more than one page. To avoid 5284c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn // glitches, we want to keep all current pages in the view 5294c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn // until the scroll ends. 5304c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn for (int i=0; i<mItems.size(); i++) { 5314c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn mItems.get(i).scrolling = true; 5324c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn } 5334c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn } 53447dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell final boolean dispatchSelected = mCurItem != item; 535fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell 536fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell if (mFirstLayout) { 537fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell // We don't have any idea how big we are yet and shouldn't have any pages either. 538fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell // Just set things up and let the pending layout handle things. 539fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell mCurItem = item; 540fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell if (dispatchSelected && mOnPageChangeListener != null) { 541fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell mOnPageChangeListener.onPageSelected(item); 542fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell } 543fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell if (dispatchSelected && mInternalPageChangeListener != null) { 544fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell mInternalPageChangeListener.onPageSelected(item); 545fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell } 546fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell requestLayout(); 547fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell } else { 548fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell populate(item); 549fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell scrollToItem(item, smoothScroll, velocity, dispatchSelected); 550fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell } 551a862399a9f738aa7e14012bc30491627f9dc6befPhilip Milne } 552a862399a9f738aa7e14012bc30491627f9dc6befPhilip Milne 553a862399a9f738aa7e14012bc30491627f9dc6befPhilip Milne private void scrollToItem(int item, boolean smoothScroll, int velocity, 554a862399a9f738aa7e14012bc30491627f9dc6befPhilip Milne boolean dispatchSelected) { 555a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final ItemInfo curInfo = infoForPosition(item); 55631bb17f88734747206586eeb3eb57123e3cc2434Adam Powell int destX = 0; 55731bb17f88734747206586eeb3eb57123e3cc2434Adam Powell if (curInfo != null) { 558becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu final int width = getClientWidth(); 55931bb17f88734747206586eeb3eb57123e3cc2434Adam Powell destX = (int) (width * Math.max(mFirstOffset, 56031bb17f88734747206586eeb3eb57123e3cc2434Adam Powell Math.min(curInfo.offset, mLastOffset))); 56131bb17f88734747206586eeb3eb57123e3cc2434Adam Powell } 562d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (smoothScroll) { 5631cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell smoothScrollTo(destX, 0, velocity); 56447dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell if (dispatchSelected && mOnPageChangeListener != null) { 56547dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell mOnPageChangeListener.onPageSelected(item); 56647dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell } 5678fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (dispatchSelected && mInternalPageChangeListener != null) { 5688fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mInternalPageChangeListener.onPageSelected(item); 5698fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 570d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } else { 57147dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell if (dispatchSelected && mOnPageChangeListener != null) { 5723661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell mOnPageChangeListener.onPageSelected(item); 5733661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 5748fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (dispatchSelected && mInternalPageChangeListener != null) { 5758fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mInternalPageChangeListener.onPageSelected(item); 5768fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 57771d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio completeScroll(false); 578329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell scrollTo(destX, 0); 579d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 580d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 581d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 5828fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell /** 5838fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * Set a listener that will be invoked whenever the page changes or is incrementally 5848fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * scrolled. See {@link OnPageChangeListener}. 5858fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * 5868fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * @param listener Listener to set 5878fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell */ 5883661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell public void setOnPageChangeListener(OnPageChangeListener listener) { 5893661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell mOnPageChangeListener = listener; 5903661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 5913661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 592d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn /** 5938a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * Set a {@link PageTransformer} that will be called for each attached page whenever 5948a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * the scroll position is changed. This allows the application to apply custom property 5958a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * transformations to each page, overriding the default sliding look and feel. 5968a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * 5978a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * <p><em>Note:</em> Prior to Android 3.0 the property animation APIs did not exist. 5988a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * As a result, setting a PageTransformer prior to Android 3.0 (API 11) will have no effect.</p> 5998a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * 6008a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * @param reverseDrawingOrder true if the supplied PageTransformer requires page views 6018a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * to be drawn from last to first instead of first to last. 6028a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell * @param transformer PageTransformer that will modify each page's animation properties 6038a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell */ 6048a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell public void setPageTransformer(boolean reverseDrawingOrder, PageTransformer transformer) { 6058a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell if (Build.VERSION.SDK_INT >= 11) { 6067e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell final boolean hasTransformer = transformer != null; 6077e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell final boolean needsPopulate = hasTransformer != (mPageTransformer != null); 6088a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell mPageTransformer = transformer; 6097e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell setChildrenDrawingOrderEnabledCompat(hasTransformer); 6107e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell if (hasTransformer) { 6117e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell mDrawingOrder = reverseDrawingOrder ? DRAW_ORDER_REVERSE : DRAW_ORDER_FORWARD; 6127e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell } else { 6137e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell mDrawingOrder = DRAW_ORDER_DEFAULT; 6147e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell } 6157e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell if (needsPopulate) populate(); 6168a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell } 6178a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell } 6188a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell 6198a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell void setChildrenDrawingOrderEnabledCompat(boolean enable) { 620f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell if (Build.VERSION.SDK_INT >= 7) { 621f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell if (mSetChildrenDrawingOrderEnabled == null) { 622f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell try { 623f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell mSetChildrenDrawingOrderEnabled = ViewGroup.class.getDeclaredMethod( 624f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell "setChildrenDrawingOrderEnabled", new Class[] { Boolean.TYPE }); 625f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell } catch (NoSuchMethodException e) { 626f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell Log.e(TAG, "Can't find setChildrenDrawingOrderEnabled", e); 627f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell } 628f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell } 6298a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell try { 630f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell mSetChildrenDrawingOrderEnabled.invoke(this, enable); 631f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell } catch (Exception e) { 632f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell Log.e(TAG, "Error changing children drawing order", e); 6338a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell } 6348a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell } 6358a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell } 6368a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell 6378a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell @Override 6388a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell protected int getChildDrawingOrder(int childCount, int i) { 6397e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell final int index = mDrawingOrder == DRAW_ORDER_REVERSE ? childCount - 1 - i : i; 6407e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell final int result = ((LayoutParams) mDrawingOrderedChildren.get(index).getLayoutParams()).childIndex; 6417e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell return result; 6428a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell } 6438a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell 6448a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell /** 6458fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * Set a separate OnPageChangeListener for internal use by the support library. 6468fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * 6478fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * @param listener Listener to set 6488fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * @return The old listener that was set, if any. 6498fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell */ 6508fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell OnPageChangeListener setInternalPageChangeListener(OnPageChangeListener listener) { 6518fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell OnPageChangeListener oldListener = mInternalPageChangeListener; 6528fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mInternalPageChangeListener = listener; 6538fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell return oldListener; 6548fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 6558fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 6568fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell /** 65729a6184d74279156a9297dc67398712fb047fdc0Adam Powell * Returns the number of pages that will be retained to either side of the 65829a6184d74279156a9297dc67398712fb047fdc0Adam Powell * current page in the view hierarchy in an idle state. Defaults to 1. 65929a6184d74279156a9297dc67398712fb047fdc0Adam Powell * 66029a6184d74279156a9297dc67398712fb047fdc0Adam Powell * @return How many pages will be kept offscreen on either side 66129a6184d74279156a9297dc67398712fb047fdc0Adam Powell * @see #setOffscreenPageLimit(int) 66229a6184d74279156a9297dc67398712fb047fdc0Adam Powell */ 66329a6184d74279156a9297dc67398712fb047fdc0Adam Powell public int getOffscreenPageLimit() { 66429a6184d74279156a9297dc67398712fb047fdc0Adam Powell return mOffscreenPageLimit; 66529a6184d74279156a9297dc67398712fb047fdc0Adam Powell } 66629a6184d74279156a9297dc67398712fb047fdc0Adam Powell 66729a6184d74279156a9297dc67398712fb047fdc0Adam Powell /** 66829a6184d74279156a9297dc67398712fb047fdc0Adam Powell * Set the number of pages that should be retained to either side of the 66929a6184d74279156a9297dc67398712fb047fdc0Adam Powell * current page in the view hierarchy in an idle state. Pages beyond this 67029a6184d74279156a9297dc67398712fb047fdc0Adam Powell * limit will be recreated from the adapter when needed. 67129a6184d74279156a9297dc67398712fb047fdc0Adam Powell * 67229a6184d74279156a9297dc67398712fb047fdc0Adam Powell * <p>This is offered as an optimization. If you know in advance the number 67329a6184d74279156a9297dc67398712fb047fdc0Adam Powell * of pages you will need to support or have lazy-loading mechanisms in place 67429a6184d74279156a9297dc67398712fb047fdc0Adam Powell * on your pages, tweaking this setting can have benefits in perceived smoothness 67529a6184d74279156a9297dc67398712fb047fdc0Adam Powell * of paging animations and interaction. If you have a small number of pages (3-4) 67629a6184d74279156a9297dc67398712fb047fdc0Adam Powell * that you can keep active all at once, less time will be spent in layout for 67729a6184d74279156a9297dc67398712fb047fdc0Adam Powell * newly created view subtrees as the user pages back and forth.</p> 67829a6184d74279156a9297dc67398712fb047fdc0Adam Powell * 67929a6184d74279156a9297dc67398712fb047fdc0Adam Powell * <p>You should keep this limit low, especially if your pages have complex layouts. 68029a6184d74279156a9297dc67398712fb047fdc0Adam Powell * This setting defaults to 1.</p> 68129a6184d74279156a9297dc67398712fb047fdc0Adam Powell * 68229a6184d74279156a9297dc67398712fb047fdc0Adam Powell * @param limit How many pages will be kept offscreen in an idle state. 68329a6184d74279156a9297dc67398712fb047fdc0Adam Powell */ 68429a6184d74279156a9297dc67398712fb047fdc0Adam Powell public void setOffscreenPageLimit(int limit) { 68529a6184d74279156a9297dc67398712fb047fdc0Adam Powell if (limit < DEFAULT_OFFSCREEN_PAGES) { 68629a6184d74279156a9297dc67398712fb047fdc0Adam Powell Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " + 68729a6184d74279156a9297dc67398712fb047fdc0Adam Powell DEFAULT_OFFSCREEN_PAGES); 68829a6184d74279156a9297dc67398712fb047fdc0Adam Powell limit = DEFAULT_OFFSCREEN_PAGES; 68929a6184d74279156a9297dc67398712fb047fdc0Adam Powell } 69029a6184d74279156a9297dc67398712fb047fdc0Adam Powell if (limit != mOffscreenPageLimit) { 69129a6184d74279156a9297dc67398712fb047fdc0Adam Powell mOffscreenPageLimit = limit; 69229a6184d74279156a9297dc67398712fb047fdc0Adam Powell populate(); 69329a6184d74279156a9297dc67398712fb047fdc0Adam Powell } 69429a6184d74279156a9297dc67398712fb047fdc0Adam Powell } 69529a6184d74279156a9297dc67398712fb047fdc0Adam Powell 69629a6184d74279156a9297dc67398712fb047fdc0Adam Powell /** 697329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell * Set the margin between pages. 698329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell * 699329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell * @param marginPixels Distance between adjacent pages in pixels 700329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell * @see #getPageMargin() 701329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell * @see #setPageMarginDrawable(Drawable) 702329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell * @see #setPageMarginDrawable(int) 703329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell */ 704329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell public void setPageMargin(int marginPixels) { 705329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell final int oldMargin = mPageMargin; 706329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell mPageMargin = marginPixels; 707329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell 708329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell final int width = getWidth(); 709329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell recomputeScrollPosition(width, width, marginPixels, oldMargin); 710329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell 711329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell requestLayout(); 712329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell } 713329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell 714329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell /** 715329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell * Return the margin between pages. 716329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell * 717329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell * @return The size of the margin in pixels 718329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell */ 719329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell public int getPageMargin() { 720329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell return mPageMargin; 721329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell } 722329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell 723329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell /** 724329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell * Set a drawable that will be used to fill the margin between pages. 725329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell * 726329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell * @param d Drawable to display between pages 727329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell */ 728329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell public void setPageMarginDrawable(Drawable d) { 729329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell mMarginDrawable = d; 730329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell if (d != null) refreshDrawableState(); 731329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell setWillNotDraw(d == null); 732329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell invalidate(); 733329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell } 734329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell 735329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell /** 736329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell * Set a drawable that will be used to fill the margin between pages. 737329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell * 738329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell * @param resId Resource ID of a drawable to display between pages 739329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell */ 740329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell public void setPageMarginDrawable(int resId) { 741329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell setPageMarginDrawable(getContext().getResources().getDrawable(resId)); 742329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell } 743329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell 744329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell @Override 745329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell protected boolean verifyDrawable(Drawable who) { 746329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell return super.verifyDrawable(who) || who == mMarginDrawable; 747329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell } 748329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell 749329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell @Override 750329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell protected void drawableStateChanged() { 751329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell super.drawableStateChanged(); 752329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell final Drawable d = mMarginDrawable; 753329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell if (d != null && d.isStateful()) { 754329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell d.setState(getDrawableState()); 755329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell } 756329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell } 757329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell 7581cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell // We want the duration of the page snap animation to be influenced by the distance that 7591cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell // the screen has to travel, however, we don't want this duration to be effected in a 7601cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell // purely linear fashion. Instead, we use this method to moderate the effect that the distance 7611cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell // of travel has on the overall snap duration. 7621cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell float distanceInfluenceForSnapDuration(float f) { 7631cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell f -= 0.5f; // center the values about 0. 7641cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell f *= 0.3f * Math.PI / 2.0f; 7651cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell return (float) Math.sin(f); 7661cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell } 7671cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell 768329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell /** 769d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. 770d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * 771cf2312ee850d26c9d1a2413c996d41397e816fb5Minh Pham * @param x the number of pixels to scroll by on the X axis 772cf2312ee850d26c9d1a2413c996d41397e816fb5Minh Pham * @param y the number of pixels to scroll by on the Y axis 773d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn */ 774d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn void smoothScrollTo(int x, int y) { 7751cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell smoothScrollTo(x, y, 0); 7761cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell } 7771cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell 7781cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell /** 7791cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. 7801cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell * 7811cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell * @param x the number of pixels to scroll by on the X axis 7821cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell * @param y the number of pixels to scroll by on the Y axis 7831cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell * @param velocity the velocity associated with a fling, if applicable. (0 otherwise) 7841cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell */ 7851cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell void smoothScrollTo(int x, int y, int velocity) { 786d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (getChildCount() == 0) { 787d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // Nothing to do. 788d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn setScrollingCacheEnabled(false); 789d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn return; 790d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 791d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn int sx = getScrollX(); 792d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn int sy = getScrollY(); 7933661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell int dx = x - sx; 7943661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell int dy = y - sy; 7953661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell if (dx == 0 && dy == 0) { 79671d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio completeScroll(false); 79731bb17f88734747206586eeb3eb57123e3cc2434Adam Powell populate(); 7983040c142491acd4a09e7d0add073be0067aec2d5Adam Powell setScrollState(SCROLL_STATE_IDLE); 7993661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell return; 8003661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 8013661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 8023661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell setScrollingCacheEnabled(true); 80347dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell setScrollState(SCROLL_STATE_SETTLING); 8041cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell 805becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu final int width = getClientWidth(); 806035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell final int halfWidth = width / 2; 807035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell final float distanceRatio = Math.min(1f, 1.0f * Math.abs(dx) / width); 808035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell final float distance = halfWidth + halfWidth * 809035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell distanceInfluenceForSnapDuration(distanceRatio); 8101cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell 811035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell int duration = 0; 8121cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell velocity = Math.abs(velocity); 8131cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell if (velocity > 0) { 814035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell duration = 4 * Math.round(1000 * Math.abs(distance / velocity)); 8151cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell } else { 816a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final float pageWidth = width * mAdapter.getPageWidth(mCurItem); 817a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final float pageDelta = (float) Math.abs(dx) / (pageWidth + mPageMargin); 818035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell duration = (int) ((pageDelta + 1) * 100); 8191cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell } 8201cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell duration = Math.min(duration, MAX_SETTLE_DURATION); 8211cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell 8221cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell mScroller.startScroll(sx, sy, dx, dy, duration); 823b469af6dc2f8cda4020a78fb4582c1483089fd6eAdam Powell ViewCompat.postInvalidateOnAnimation(this); 824d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 825d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 826a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ItemInfo addNewItem(int position, int index) { 827d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn ItemInfo ii = new ItemInfo(); 828d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn ii.position = position; 8295c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn ii.object = mAdapter.instantiateItem(this, position); 830a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii.widthFactor = mAdapter.getPageWidth(position); 831a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (index < 0 || index >= mItems.size()) { 832d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mItems.add(ii); 833d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } else { 834d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mItems.add(index, ii); 835d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 836a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell return ii; 837d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 838d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 8393661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell void dataSetChanged() { 8403661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell // This method only gets called if our observer is attached, so mAdapter is non-null. 8413661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 842199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell final int adapterCount = mAdapter.getCount(); 843199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell mExpectedAdapterCount = adapterCount; 8441a1c2acbc15f8bc9dba05d09dcb18e340474e1c6Adam Powell boolean needPopulate = mItems.size() < mOffscreenPageLimit * 2 + 1 && 845199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell mItems.size() < adapterCount; 8461e300b0aca2f34bfe65885c5405044cfe5585224Adam Powell int newCurrItem = mCurItem; 8473661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 8489508e3e642f5093e3181b4d5a3777bd84eedbcc6Adam Powell boolean isUpdating = false; 8493661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell for (int i = 0; i < mItems.size(); i++) { 8503661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell final ItemInfo ii = mItems.get(i); 8513661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell final int newPos = mAdapter.getItemPosition(ii.object); 8523661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 8533661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell if (newPos == PagerAdapter.POSITION_UNCHANGED) { 8543661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell continue; 8553661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 8563661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 8573661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell if (newPos == PagerAdapter.POSITION_NONE) { 8583661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell mItems.remove(i); 8593661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell i--; 8609508e3e642f5093e3181b4d5a3777bd84eedbcc6Adam Powell 8619508e3e642f5093e3181b4d5a3777bd84eedbcc6Adam Powell if (!isUpdating) { 8629508e3e642f5093e3181b4d5a3777bd84eedbcc6Adam Powell mAdapter.startUpdate(this); 8639508e3e642f5093e3181b4d5a3777bd84eedbcc6Adam Powell isUpdating = true; 8649508e3e642f5093e3181b4d5a3777bd84eedbcc6Adam Powell } 8659508e3e642f5093e3181b4d5a3777bd84eedbcc6Adam Powell 8663661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell mAdapter.destroyItem(this, ii.position, ii.object); 8673661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell needPopulate = true; 8683661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 8693661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell if (mCurItem == ii.position) { 8703661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell // Keep the current item in the valid range 871199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell newCurrItem = Math.max(0, Math.min(mCurItem, adapterCount - 1)); 8721a1c2acbc15f8bc9dba05d09dcb18e340474e1c6Adam Powell needPopulate = true; 8733661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 8743661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell continue; 8753661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 8763661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 8773661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell if (ii.position != newPos) { 8783661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell if (ii.position == mCurItem) { 8793661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell // Our current item changed position. Follow it. 8803661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell newCurrItem = newPos; 8813661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 8823661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 8833661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell ii.position = newPos; 8843661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell needPopulate = true; 8853661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 8863661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 8873661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 8889508e3e642f5093e3181b4d5a3777bd84eedbcc6Adam Powell if (isUpdating) { 8899508e3e642f5093e3181b4d5a3777bd84eedbcc6Adam Powell mAdapter.finishUpdate(this); 8909508e3e642f5093e3181b4d5a3777bd84eedbcc6Adam Powell } 8919508e3e642f5093e3181b4d5a3777bd84eedbcc6Adam Powell 89266c0e6a0a5fd20c66b6c86133b8bd91fe303e430Minh Pham Collections.sort(mItems, COMPARATOR); 89366c0e6a0a5fd20c66b6c86133b8bd91fe303e430Minh Pham 894a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (needPopulate) { 895a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // Reset our known page widths; populate will recompute them. 896a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int childCount = getChildCount(); 897a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell for (int i = 0; i < childCount; i++) { 898a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final View child = getChildAt(i); 899a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 900a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (!lp.isDecor) { 901a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell lp.widthFactor = 0.f; 902a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 903a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 904a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 905d84ef6c972b75c0ddeee88db2d66d40fff7519a8Adam Powell setCurrentItemInternal(newCurrItem, false, true); 9063661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell requestLayout(); 9073661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 9083661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 9093661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 910d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn void populate() { 911a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell populate(mCurItem); 912a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 913a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 914a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell void populate(int newCurrentItem) { 915a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ItemInfo oldCurInfo = null; 916860155ee7a4c7968f3cbe1d8dbb0c8a35f9fec2dDake Gu int focusDirection = View.FOCUS_FORWARD; 917a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (mCurItem != newCurrentItem) { 918860155ee7a4c7968f3cbe1d8dbb0c8a35f9fec2dDake Gu focusDirection = mCurItem < newCurrentItem ? View.FOCUS_RIGHT : View.FOCUS_LEFT; 919a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell oldCurInfo = infoForPosition(mCurItem); 920a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mCurItem = newCurrentItem; 921a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 922a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 923d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (mAdapter == null) { 924f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell sortChildDrawingOrder(); 925d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn return; 926d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 927d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 928d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // Bail now if we are waiting to populate. This is to hold off 929d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // on creating views from the time the user releases their finger to 930d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // fling to a new position until we have finished the scroll to 931d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // that position, avoiding glitches from happening at that point. 932d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (mPopulatePending) { 9333661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell if (DEBUG) Log.i(TAG, "populate is pending, skipping for now..."); 934f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell sortChildDrawingOrder(); 935d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn return; 936d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 937d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 938ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn // Also, don't populate until we are attached to a window. This is to 939ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn // avoid trying to populate before we have restored our view hierarchy 940ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn // state and conflicting with what is restored. 941ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn if (getWindowToken() == null) { 942ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn return; 943ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn } 944ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn 9455c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn mAdapter.startUpdate(this); 946d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 94729a6184d74279156a9297dc67398712fb047fdc0Adam Powell final int pageLimit = mOffscreenPageLimit; 94829a6184d74279156a9297dc67398712fb047fdc0Adam Powell final int startPos = Math.max(0, mCurItem - pageLimit); 9494c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn final int N = mAdapter.getCount(); 95029a6184d74279156a9297dc67398712fb047fdc0Adam Powell final int endPos = Math.min(N-1, mCurItem + pageLimit); 951d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 952199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell if (N != mExpectedAdapterCount) { 953199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell String resName; 954199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell try { 955199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell resName = getResources().getResourceName(getId()); 956199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell } catch (Resources.NotFoundException e) { 957199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell resName = Integer.toHexString(getId()); 958199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell } 959199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell throw new IllegalStateException("The application's PagerAdapter changed the adapter's" + 960199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell " contents without calling PagerAdapter#notifyDataSetChanged!" + 961199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell " Expected adapter item count: " + mExpectedAdapterCount + ", found: " + N + 962199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell " Pager id: " + resName + 963199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell " Pager class: " + getClass() + 964199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell " Problematic adapter: " + mAdapter.getClass()); 965199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell } 966199a13cf79b43494ea381a91ee67f0da1f1d10deAdam Powell 967a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // Locate the currently focused item or add it if needed. 968a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell int curIndex = -1; 969a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ItemInfo curItem = null; 970a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell for (curIndex = 0; curIndex < mItems.size(); curIndex++) { 971a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final ItemInfo ii = mItems.get(curIndex); 972a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (ii.position >= mCurItem) { 973a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (ii.position == mCurItem) curItem = ii; 974a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell break; 975a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 976a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 977d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 978a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (curItem == null && N > 0) { 979a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell curItem = addNewItem(mCurItem, curIndex); 980a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 981a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 982a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // Fill 3x the available width or up to the number of offscreen 983a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // pages requested to either side, whichever is larger. 984a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // If we have no current item we have no work to do. 985a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (curItem != null) { 986a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell float extraWidthLeft = 0.f; 987a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell int itemIndex = curIndex - 1; 988a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ItemInfo ii = itemIndex >= 0 ? mItems.get(itemIndex) : null; 989becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu final float leftWidthNeeded = 2.f - curItem.widthFactor + 990becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu (float) getPaddingLeft() / (float) getClientWidth(); 991a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell for (int pos = mCurItem - 1; pos >= 0; pos--) { 99231bb17f88734747206586eeb3eb57123e3cc2434Adam Powell if (extraWidthLeft >= leftWidthNeeded && pos < startPos) { 993a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (ii == null) { 994a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell break; 995a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 996a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (pos == ii.position && !ii.scrolling) { 997a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mItems.remove(itemIndex); 998a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mAdapter.destroyItem(this, pos, ii.object); 99971d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio if (DEBUG) { 100071d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio Log.i(TAG, "populate() - destroyItem() with pos: " + pos + 100171d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio " view: " + ((View) ii.object)); 100271d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio } 1003a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell itemIndex--; 1004a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell curIndex--; 1005a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii = itemIndex >= 0 ? mItems.get(itemIndex) : null; 1006a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1007a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } else if (ii != null && pos == ii.position) { 1008a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell extraWidthLeft += ii.widthFactor; 1009a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell itemIndex--; 1010a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii = itemIndex >= 0 ? mItems.get(itemIndex) : null; 1011a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } else { 1012a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii = addNewItem(pos, itemIndex + 1); 1013a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell extraWidthLeft += ii.widthFactor; 1014a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell curIndex++; 1015a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii = itemIndex >= 0 ? mItems.get(itemIndex) : null; 10164c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn } 1017d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1018d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1019a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell float extraWidthRight = curItem.widthFactor; 1020a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell itemIndex = curIndex + 1; 1021a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (extraWidthRight < 2.f) { 1022a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii = itemIndex < mItems.size() ? mItems.get(itemIndex) : null; 1023becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu final float rightWidthNeeded = (float) getPaddingRight() / (float) getClientWidth() 1024becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu + 2.f; 1025a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell for (int pos = mCurItem + 1; pos < N; pos++) { 1026becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu if (extraWidthRight >= rightWidthNeeded && pos > endPos) { 1027a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (ii == null) { 1028a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell break; 1029a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1030a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (pos == ii.position && !ii.scrolling) { 1031a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mItems.remove(itemIndex); 1032a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mAdapter.destroyItem(this, pos, ii.object); 103371d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio if (DEBUG) { 103471d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio Log.i(TAG, "populate() - destroyItem() with pos: " + pos + 103571d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio " view: " + ((View) ii.object)); 103671d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio } 1037a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii = itemIndex < mItems.size() ? mItems.get(itemIndex) : null; 1038a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1039a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } else if (ii != null && pos == ii.position) { 1040a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell extraWidthRight += ii.widthFactor; 1041a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell itemIndex++; 1042a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii = itemIndex < mItems.size() ? mItems.get(itemIndex) : null; 1043a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } else { 1044a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii = addNewItem(pos, itemIndex); 1045a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell itemIndex++; 1046a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell extraWidthRight += ii.widthFactor; 1047a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii = itemIndex < mItems.size() ? mItems.get(itemIndex) : null; 1048a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1049a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1050d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1051a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 1052a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell calculatePageOffsets(curItem, curIndex, oldCurInfo); 1053d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1054d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 10554c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn if (DEBUG) { 10564c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn Log.i(TAG, "Current page list:"); 10574c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn for (int i=0; i<mItems.size(); i++) { 10584c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn Log.i(TAG, "#" + i + ": page " + mItems.get(i).position); 1059d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1060d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1061d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 10622a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn mAdapter.setPrimaryItem(this, mCurItem, curItem != null ? curItem.object : null); 10632a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn 10645c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn mAdapter.finishUpdate(this); 10652a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn 10667e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell // Check width measurement of current pages and drawing sort order. 10677e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell // Update LayoutParams as needed. 1068a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int childCount = getChildCount(); 1069a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell for (int i = 0; i < childCount; i++) { 1070a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final View child = getChildAt(i); 1071a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 10727e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell lp.childIndex = i; 1073a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (!lp.isDecor && lp.widthFactor == 0.f) { 1074a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // 0 means requery the adapter for this, it doesn't have a valid width. 1075a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final ItemInfo ii = infoForChild(child); 1076a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (ii != null) { 1077a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell lp.widthFactor = ii.widthFactor; 10787e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell lp.position = ii.position; 1079a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1080a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1081a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1082f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell sortChildDrawingOrder(); 1083a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 10842a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if (hasFocus()) { 10852a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn View currentFocused = findFocus(); 1086218c1e661578e2a17928f7dbb590b43d1c79aeb7Dianne Hackborn ItemInfo ii = currentFocused != null ? infoForAnyChild(currentFocused) : null; 10872a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if (ii == null || ii.position != mCurItem) { 10882a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn for (int i=0; i<getChildCount(); i++) { 10892a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn View child = getChildAt(i); 10902a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn ii = infoForChild(child); 10912a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if (ii != null && ii.position == mCurItem) { 1092860155ee7a4c7968f3cbe1d8dbb0c8a35f9fec2dDake Gu if (child.requestFocus(focusDirection)) { 10932a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn break; 10942a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 10952a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 10962a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 10972a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 10982a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 1099d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1100d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1101f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell private void sortChildDrawingOrder() { 1102f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell if (mDrawingOrder != DRAW_ORDER_DEFAULT) { 1103f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell if (mDrawingOrderedChildren == null) { 1104f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell mDrawingOrderedChildren = new ArrayList<View>(); 1105f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell } else { 1106f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell mDrawingOrderedChildren.clear(); 1107f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell } 1108f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell final int childCount = getChildCount(); 1109f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell for (int i = 0; i < childCount; i++) { 1110f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell final View child = getChildAt(i); 1111f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell mDrawingOrderedChildren.add(child); 1112f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell } 1113f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell Collections.sort(mDrawingOrderedChildren, sPositionComparator); 1114f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell } 1115f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell } 1116f1452d17be15651c6047ec4eb7ff5892538e8265Adam Powell 1117a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell private void calculatePageOffsets(ItemInfo curItem, int curIndex, ItemInfo oldCurInfo) { 1118a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int N = mAdapter.getCount(); 1119becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu final int width = getClientWidth(); 1120a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final float marginOffset = width > 0 ? (float) mPageMargin / width : 0; 1121a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // Fix up offsets for later layout. 1122a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (oldCurInfo != null) { 1123a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int oldCurPosition = oldCurInfo.position; 1124a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // Base offsets off of oldCurInfo. 1125a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (oldCurPosition < curItem.position) { 1126a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell int itemIndex = 0; 1127a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ItemInfo ii = null; 11286bd60735de55d6621a4dffb0f6f4494decda484aAdam Powell float offset = oldCurInfo.offset + oldCurInfo.widthFactor + marginOffset; 1129a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell for (int pos = oldCurPosition + 1; 1130a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell pos <= curItem.position && itemIndex < mItems.size(); pos++) { 1131a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii = mItems.get(itemIndex); 1132a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell while (pos > ii.position && itemIndex < mItems.size() - 1) { 1133a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell itemIndex++; 1134a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii = mItems.get(itemIndex); 1135a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1136a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell while (pos < ii.position) { 1137a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // We don't have an item populated for this, 1138a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // ask the adapter for an offset. 1139a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell offset += mAdapter.getPageWidth(pos) + marginOffset; 1140a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell pos++; 1141a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1142a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii.offset = offset; 1143a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell offset += ii.widthFactor + marginOffset; 1144a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1145a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } else if (oldCurPosition > curItem.position) { 1146a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell int itemIndex = mItems.size() - 1; 1147a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ItemInfo ii = null; 1148a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell float offset = oldCurInfo.offset; 1149a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell for (int pos = oldCurPosition - 1; 1150a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell pos >= curItem.position && itemIndex >= 0; pos--) { 1151a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii = mItems.get(itemIndex); 1152a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell while (pos < ii.position && itemIndex > 0) { 1153a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell itemIndex--; 1154a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii = mItems.get(itemIndex); 1155a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1156a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell while (pos > ii.position) { 1157a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // We don't have an item populated for this, 1158a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // ask the adapter for an offset. 1159a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell offset -= mAdapter.getPageWidth(pos) + marginOffset; 1160a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell pos--; 1161a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1162a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell offset -= ii.widthFactor + marginOffset; 1163a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii.offset = offset; 1164a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1165a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1166a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1167a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 1168a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // Base all offsets off of curItem. 1169a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int itemCount = mItems.size(); 1170a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell float offset = curItem.offset; 1171a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell int pos = curItem.position - 1; 1172a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mFirstOffset = curItem.position == 0 ? curItem.offset : -Float.MAX_VALUE; 117331bb17f88734747206586eeb3eb57123e3cc2434Adam Powell mLastOffset = curItem.position == N - 1 ? 117431bb17f88734747206586eeb3eb57123e3cc2434Adam Powell curItem.offset + curItem.widthFactor - 1 : Float.MAX_VALUE; 1175a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // Previous pages 1176a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell for (int i = curIndex - 1; i >= 0; i--, pos--) { 1177a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final ItemInfo ii = mItems.get(i); 1178a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell while (pos > ii.position) { 1179a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell offset -= mAdapter.getPageWidth(pos--) + marginOffset; 1180a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1181a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell offset -= ii.widthFactor + marginOffset; 1182a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii.offset = offset; 1183a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (ii.position == 0) mFirstOffset = offset; 1184a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1185a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell offset = curItem.offset + curItem.widthFactor + marginOffset; 1186a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell pos = curItem.position + 1; 1187a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // Next pages 1188a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell for (int i = curIndex + 1; i < itemCount; i++, pos++) { 1189a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final ItemInfo ii = mItems.get(i); 1190a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell while (pos < ii.position) { 1191a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell offset += mAdapter.getPageWidth(pos++) + marginOffset; 1192a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 119331bb17f88734747206586eeb3eb57123e3cc2434Adam Powell if (ii.position == N - 1) { 119431bb17f88734747206586eeb3eb57123e3cc2434Adam Powell mLastOffset = offset + ii.widthFactor - 1; 119531bb17f88734747206586eeb3eb57123e3cc2434Adam Powell } 1196a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii.offset = offset; 1197a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell offset += ii.widthFactor + marginOffset; 1198a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1199a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 1200a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mNeedCalculatePageOffsets = false; 1201a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1202a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 12037dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn /** 12047dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * This is the persistent state that is saved by ViewPager. Only needed 12057dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * if you are creating a sublass of ViewPager that must save its own 12067dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * state, in which case it should implement a subclass of this which 12077dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * contains that state. 12087dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn */ 1209d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn public static class SavedState extends BaseSavedState { 1210d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn int position; 1211ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn Parcelable adapterState; 12125c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn ClassLoader loader; 1213d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 12145c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn public SavedState(Parcelable superState) { 1215d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn super(superState); 1216d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1217d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1218d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn @Override 1219d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn public void writeToParcel(Parcel out, int flags) { 1220d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn super.writeToParcel(out, flags); 1221d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn out.writeInt(position); 12225c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn out.writeParcelable(adapterState, flags); 1223d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1224d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1225d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn @Override 1226d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn public String toString() { 1227d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn return "FragmentPager.SavedState{" 1228d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn + Integer.toHexString(System.identityHashCode(this)) 1229d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn + " position=" + position + "}"; 1230d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1231d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 12325c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn public static final Parcelable.Creator<SavedState> CREATOR 12335c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn = ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks<SavedState>() { 12345c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn @Override 12355c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn public SavedState createFromParcel(Parcel in, ClassLoader loader) { 12365c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn return new SavedState(in, loader); 12375c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn } 12385c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn @Override 12395c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn public SavedState[] newArray(int size) { 12405c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn return new SavedState[size]; 12415c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn } 12425c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn }); 12435c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn 12445c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn SavedState(Parcel in, ClassLoader loader) { 1245d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn super(in); 12465c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn if (loader == null) { 12475c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn loader = getClass().getClassLoader(); 1248ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn } 12495c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn position = in.readInt(); 12505c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn adapterState = in.readParcelable(loader); 12515c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn this.loader = loader; 1252d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1253d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1254d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1255d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn @Override 1256d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn public Parcelable onSaveInstanceState() { 1257d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn Parcelable superState = super.onSaveInstanceState(); 1258d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn SavedState ss = new SavedState(superState); 1259d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn ss.position = mCurItem; 1260677ada6ea45f3889fb5118e85a3aa706f99e4d72Makoto Onuki if (mAdapter != null) { 1261677ada6ea45f3889fb5118e85a3aa706f99e4d72Makoto Onuki ss.adapterState = mAdapter.saveState(); 1262677ada6ea45f3889fb5118e85a3aa706f99e4d72Makoto Onuki } 1263d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn return ss; 1264d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1265d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1266d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn @Override 1267d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn public void onRestoreInstanceState(Parcelable state) { 1268d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (!(state instanceof SavedState)) { 1269d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn super.onRestoreInstanceState(state); 1270d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn return; 1271d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1272d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1273d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn SavedState ss = (SavedState)state; 1274d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn super.onRestoreInstanceState(ss.getSuperState()); 1275d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1276d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (mAdapter != null) { 12775c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn mAdapter.restoreState(ss.adapterState, ss.loader); 1278d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn setCurrentItemInternal(ss.position, false, true); 1279d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } else { 1280d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mRestoredCurItem = ss.position; 1281ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn mRestoredAdapterState = ss.adapterState; 12825c1637087453de15e31861f073eae5133c4e9f7bDianne Hackborn mRestoredClassLoader = ss.loader; 1283d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1284d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1285d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1286d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn @Override 12878fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell public void addView(View child, int index, ViewGroup.LayoutParams params) { 12881ccb8bcb79557d861de7f271c13e2fd8e54e012aAdam Powell if (!checkLayoutParams(params)) { 12891ccb8bcb79557d861de7f271c13e2fd8e54e012aAdam Powell params = generateLayoutParams(params); 12901ccb8bcb79557d861de7f271c13e2fd8e54e012aAdam Powell } 12911ccb8bcb79557d861de7f271c13e2fd8e54e012aAdam Powell final LayoutParams lp = (LayoutParams) params; 12921ccb8bcb79557d861de7f271c13e2fd8e54e012aAdam Powell lp.isDecor |= child instanceof Decor; 1293d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (mInLayout) { 12948fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (lp != null && lp.isDecor) { 12958fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell throw new IllegalStateException("Cannot add pager decor view during layout"); 12968fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 1297a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell lp.needsMeasure = true; 1298d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn addViewInLayout(child, index, params); 1299d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } else { 1300d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn super.addView(child, index, params); 1301d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1302d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1303d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (USE_CACHE) { 1304d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (child.getVisibility() != GONE) { 1305d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn child.setDrawingCacheEnabled(mScrollingCacheEnabled); 1306d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } else { 1307d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn child.setDrawingCacheEnabled(false); 1308d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1309d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1310d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1311d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 131237a7c5d234e23a4a3290bc75b064b355870e2622Chet Haase @Override 131337a7c5d234e23a4a3290bc75b064b355870e2622Chet Haase public void removeView(View view) { 131437a7c5d234e23a4a3290bc75b064b355870e2622Chet Haase if (mInLayout) { 131537a7c5d234e23a4a3290bc75b064b355870e2622Chet Haase removeViewInLayout(view); 131637a7c5d234e23a4a3290bc75b064b355870e2622Chet Haase } else { 131737a7c5d234e23a4a3290bc75b064b355870e2622Chet Haase super.removeView(view); 131837a7c5d234e23a4a3290bc75b064b355870e2622Chet Haase } 131937a7c5d234e23a4a3290bc75b064b355870e2622Chet Haase } 132037a7c5d234e23a4a3290bc75b064b355870e2622Chet Haase 1321d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn ItemInfo infoForChild(View child) { 1322d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn for (int i=0; i<mItems.size(); i++) { 1323d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn ItemInfo ii = mItems.get(i); 1324ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn if (mAdapter.isViewFromObject(child, ii.object)) { 1325d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn return ii; 1326d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1327d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1328d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn return null; 1329d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1330d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1331218c1e661578e2a17928f7dbb590b43d1c79aeb7Dianne Hackborn ItemInfo infoForAnyChild(View child) { 1332218c1e661578e2a17928f7dbb590b43d1c79aeb7Dianne Hackborn ViewParent parent; 1333218c1e661578e2a17928f7dbb590b43d1c79aeb7Dianne Hackborn while ((parent=child.getParent()) != this) { 1334218c1e661578e2a17928f7dbb590b43d1c79aeb7Dianne Hackborn if (parent == null || !(parent instanceof View)) { 1335218c1e661578e2a17928f7dbb590b43d1c79aeb7Dianne Hackborn return null; 1336218c1e661578e2a17928f7dbb590b43d1c79aeb7Dianne Hackborn } 1337218c1e661578e2a17928f7dbb590b43d1c79aeb7Dianne Hackborn child = (View)parent; 1338218c1e661578e2a17928f7dbb590b43d1c79aeb7Dianne Hackborn } 1339218c1e661578e2a17928f7dbb590b43d1c79aeb7Dianne Hackborn return infoForChild(child); 1340218c1e661578e2a17928f7dbb590b43d1c79aeb7Dianne Hackborn } 1341218c1e661578e2a17928f7dbb590b43d1c79aeb7Dianne Hackborn 1342a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ItemInfo infoForPosition(int position) { 1343a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell for (int i = 0; i < mItems.size(); i++) { 1344a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ItemInfo ii = mItems.get(i); 1345a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (ii.position == position) { 1346a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell return ii; 1347a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1348a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1349a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell return null; 1350a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1351a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 1352d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn @Override 1353ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn protected void onAttachedToWindow() { 1354ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn super.onAttachedToWindow(); 135597d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell mFirstLayout = true; 1356ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn } 1357ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn 1358ea2c91b0198855073983b4a8437aa71cbd83872fDianne Hackborn @Override 1359d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 1360fdd9223ac2d8fc0c7a74a076c1cd4defc7acf499Adam Powell // For simple implementation, our internal size is always 0. 1361d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // We depend on the container to specify the layout size of 1362d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // our view. We can't really know what it is since we will be 1363d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // adding and removing different arbitrary views and do not 1364d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // want the layout to change as this happens. 1365d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), 1366d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn getDefaultSize(0, heightMeasureSpec)); 1367d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 13688f19b17dbc34bfc7e5caacbf83a7099e5cb5a47cAdam Powell final int measuredWidth = getMeasuredWidth(); 13698f19b17dbc34bfc7e5caacbf83a7099e5cb5a47cAdam Powell final int maxGutterSize = measuredWidth / 10; 13708f19b17dbc34bfc7e5caacbf83a7099e5cb5a47cAdam Powell mGutterSize = Math.min(maxGutterSize, mDefaultGutterSize); 13718f19b17dbc34bfc7e5caacbf83a7099e5cb5a47cAdam Powell 1372d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // Children are just made to fill our space. 13738f19b17dbc34bfc7e5caacbf83a7099e5cb5a47cAdam Powell int childWidthSize = measuredWidth - getPaddingLeft() - getPaddingRight(); 13748fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell int childHeightSize = getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); 13758fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 13768fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell /* 13778fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * Make sure all children have been properly measured. Decor views first. 13788fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * Right now we cheat and make this less complicated by assuming decor 13798fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * views won't intersect. We will pin to edges based on gravity. 13808fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell */ 1381862ffa0efd58922b8ec119bf6fa6695c316423f7Adam Powell int size = getChildCount(); 13828fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell for (int i = 0; i < size; ++i) { 13838fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final View child = getChildAt(i); 13848fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (child.getVisibility() != GONE) { 13858fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 13868fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (lp != null && lp.isDecor) { 13878fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; 13888fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK; 13898fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell int widthMode = MeasureSpec.AT_MOST; 13908fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell int heightMode = MeasureSpec.AT_MOST; 13918fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell boolean consumeVertical = vgrav == Gravity.TOP || vgrav == Gravity.BOTTOM; 13928fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell boolean consumeHorizontal = hgrav == Gravity.LEFT || hgrav == Gravity.RIGHT; 13938fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 13948fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (consumeVertical) { 13958fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell widthMode = MeasureSpec.EXACTLY; 13968fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } else if (consumeHorizontal) { 13978fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell heightMode = MeasureSpec.EXACTLY; 13988fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 13998fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 1400a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell int widthSize = childWidthSize; 1401a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell int heightSize = childHeightSize; 1402a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (lp.width != LayoutParams.WRAP_CONTENT) { 1403a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell widthMode = MeasureSpec.EXACTLY; 1404a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (lp.width != LayoutParams.FILL_PARENT) { 1405a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell widthSize = lp.width; 1406a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1407a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1408a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (lp.height != LayoutParams.WRAP_CONTENT) { 1409a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell heightMode = MeasureSpec.EXACTLY; 1410a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (lp.height != LayoutParams.FILL_PARENT) { 1411a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell heightSize = lp.height; 1412a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1413a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1414a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode); 1415a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int heightSpec = MeasureSpec.makeMeasureSpec(heightSize, heightMode); 14168fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell child.measure(widthSpec, heightSpec); 14178fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 14188fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (consumeVertical) { 14198fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell childHeightSize -= child.getMeasuredHeight(); 14208fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } else if (consumeHorizontal) { 14218fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell childWidthSize -= child.getMeasuredWidth(); 14228fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 14238fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 14248fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 14258fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 14268fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 14278fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mChildWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY); 14288fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mChildHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeightSize, MeasureSpec.EXACTLY); 1429d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1430d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // Make sure we have created all fragments that we need to have shown. 1431d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mInLayout = true; 1432d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn populate(); 1433d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mInLayout = false; 1434d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 14358fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell // Page views next. 1436862ffa0efd58922b8ec119bf6fa6695c316423f7Adam Powell size = getChildCount(); 1437d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn for (int i = 0; i < size; ++i) { 1438d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn final View child = getChildAt(i); 1439d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (child.getVisibility() != GONE) { 1440d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (DEBUG) Log.v(TAG, "Measuring #" + i + " " + child 14418fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell + ": " + mChildWidthMeasureSpec); 14428fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 14438fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 14448fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (lp == null || !lp.isDecor) { 1445a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int widthSpec = MeasureSpec.makeMeasureSpec( 1446a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell (int) (childWidthSize * lp.widthFactor), MeasureSpec.EXACTLY); 1447a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell child.measure(widthSpec, mChildHeightMeasureSpec); 14488fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 1449d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1450d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1451d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1452d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1453d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn @Override 1454d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn protected void onSizeChanged(int w, int h, int oldw, int oldh) { 1455d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn super.onSizeChanged(w, h, oldw, oldh); 1456d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1457d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // Make sure scroll position is set correctly. 1458053e500a0e25cabf53139f57dc474a0b28751b91Adam Powell if (w != oldw) { 1459329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell recomputeScrollPosition(w, oldw, mPageMargin, mPageMargin); 1460329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell } 1461329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell } 1462329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell 1463329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell private void recomputeScrollPosition(int width, int oldWidth, int margin, int oldMargin) { 146491eec7fd0b6ffdbb44cd13777950552f74f654e6Adam Powell if (oldWidth > 0 && !mItems.isEmpty()) { 1465becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu final int widthWithMargin = width - getPaddingLeft() - getPaddingRight() + margin; 1466becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu final int oldWidthWithMargin = oldWidth - getPaddingLeft() - getPaddingRight() 1467becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu + oldMargin; 14688d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell final int xpos = getScrollX(); 14695f6568e7e269783e2668527461878cadfbe65215Adam Powell final float pageOffset = (float) xpos / oldWidthWithMargin; 14705f6568e7e269783e2668527461878cadfbe65215Adam Powell final int newOffsetPixels = (int) (pageOffset * widthWithMargin); 1471a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 14725f6568e7e269783e2668527461878cadfbe65215Adam Powell scrollTo(newOffsetPixels, getScrollY()); 1473329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell if (!mScroller.isFinished()) { 1474329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell // We now return to your regularly scheduled scroll, already in progress. 1475329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell final int newDuration = mScroller.getDuration() - mScroller.timePassed(); 1476a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ItemInfo targetInfo = infoForPosition(mCurItem); 14775f6568e7e269783e2668527461878cadfbe65215Adam Powell mScroller.startScroll(newOffsetPixels, 0, 14788d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell (int) (targetInfo.offset * width), 0, newDuration); 1479329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell } 1480329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell } else { 1481a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final ItemInfo ii = infoForPosition(mCurItem); 14828d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell final float scrollOffset = ii != null ? Math.min(ii.offset, mLastOffset) : 0; 1483becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu final int scrollPos = (int) (scrollOffset * 1484becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu (width - getPaddingLeft() - getPaddingRight())); 1485329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell if (scrollPos != getScrollX()) { 148671d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio completeScroll(false); 1487053e500a0e25cabf53139f57dc474a0b28751b91Adam Powell scrollTo(scrollPos, getScrollY()); 14889bc74aa50cd69dbd1d813102718c8dbf94c42abaAdam Powell } 1489d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1490d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1491d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1492d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn @Override 1493d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn protected void onLayout(boolean changed, int l, int t, int r, int b) { 1494d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn final int count = getChildCount(); 14958fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell int width = r - l; 14968fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell int height = b - t; 14978fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell int paddingLeft = getPaddingLeft(); 14988fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell int paddingTop = getPaddingTop(); 14998fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell int paddingRight = getPaddingRight(); 15008fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell int paddingBottom = getPaddingBottom(); 15018fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int scrollX = getScrollX(); 15028fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 15038fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell int decorCount = 0; 1504d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1505a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // First pass - decor views. We need to do this in two passes so that 1506a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // we have the proper offsets for non-decor views later. 1507d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn for (int i = 0; i < count; i++) { 15088fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final View child = getChildAt(i); 15098fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (child.getVisibility() != GONE) { 15108fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 15118fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell int childLeft = 0; 15128fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell int childTop = 0; 15138fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (lp.isDecor) { 15148fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; 15158fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK; 15168fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell switch (hgrav) { 15178fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell default: 15188fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell childLeft = paddingLeft; 15198fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell break; 15208fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell case Gravity.LEFT: 15218fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell childLeft = paddingLeft; 15228fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell paddingLeft += child.getMeasuredWidth(); 15238fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell break; 15248fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell case Gravity.CENTER_HORIZONTAL: 15258fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell childLeft = Math.max((width - child.getMeasuredWidth()) / 2, 15268fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell paddingLeft); 15278fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell break; 15288fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell case Gravity.RIGHT: 15298fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell childLeft = width - paddingRight - child.getMeasuredWidth(); 15308fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell paddingRight += child.getMeasuredWidth(); 15318fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell break; 15328fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 15338fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell switch (vgrav) { 15348fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell default: 15358fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell childTop = paddingTop; 15368fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell break; 15378fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell case Gravity.TOP: 15388fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell childTop = paddingTop; 15398fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell paddingTop += child.getMeasuredHeight(); 15408fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell break; 15418fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell case Gravity.CENTER_VERTICAL: 15428fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell childTop = Math.max((height - child.getMeasuredHeight()) / 2, 15438fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell paddingTop); 15448fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell break; 15458fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell case Gravity.BOTTOM: 15468fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell childTop = height - paddingBottom - child.getMeasuredHeight(); 15478fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell paddingBottom += child.getMeasuredHeight(); 15488fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell break; 15498fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 15508fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell childLeft += scrollX; 1551abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell child.layout(childLeft, childTop, 1552abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell childLeft + child.getMeasuredWidth(), 1553abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell childTop + child.getMeasuredHeight()); 1554a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell decorCount++; 1555a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1556a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1557a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 1558a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 1559becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu final int childWidth = width - paddingLeft - paddingRight; 1560a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // Page views. Do this once we have the right padding offsets from above. 1561a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell for (int i = 0; i < count; i++) { 1562a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final View child = getChildAt(i); 1563a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (child.getVisibility() != GONE) { 1564a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1565a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ItemInfo ii; 1566a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (!lp.isDecor && (ii = infoForChild(child)) != null) { 1567becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu int loff = (int) (childWidth * ii.offset); 1568a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell int childLeft = paddingLeft + loff; 1569a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell int childTop = paddingTop; 1570a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (lp.needsMeasure) { 1571a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // This was added during layout and needs measurement. 1572a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // Do it now that we know what we're working with. 1573a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell lp.needsMeasure = false; 1574a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int widthSpec = MeasureSpec.makeMeasureSpec( 1575becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu (int) (childWidth * lp.widthFactor), 1576a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell MeasureSpec.EXACTLY); 1577a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int heightSpec = MeasureSpec.makeMeasureSpec( 1578a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell (int) (height - paddingTop - paddingBottom), 1579a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell MeasureSpec.EXACTLY); 1580a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell child.measure(widthSpec, heightSpec); 1581a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 15828fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (DEBUG) Log.v(TAG, "Positioning #" + i + " " + child + " f=" + ii.object 15838fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell + ":" + childLeft + "," + childTop + " " + child.getMeasuredWidth() 15848fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell + "x" + child.getMeasuredHeight()); 1585abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell child.layout(childLeft, childTop, 1586abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell childLeft + child.getMeasuredWidth(), 1587abc968f1eba800c34a4008deb43b015da5d23a5fAdam Powell childTop + child.getMeasuredHeight()); 15888fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 1589d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1590d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 15918fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mTopPageBounds = paddingTop; 15928fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mBottomPageBounds = height - paddingBottom; 15938fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mDecorChildCount = decorCount; 159444fc13985aed09d1fda3fdf2fd900ec13720a5dfAdam Powell 159544fc13985aed09d1fda3fdf2fd900ec13720a5dfAdam Powell if (mFirstLayout) { 159644fc13985aed09d1fda3fdf2fd900ec13720a5dfAdam Powell scrollToItem(mCurItem, false, 0, false); 159744fc13985aed09d1fda3fdf2fd900ec13720a5dfAdam Powell } 159897d6e631c6a0f698ae6fb249617f1596cb9c1cf1Adam Powell mFirstLayout = false; 1599d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1600d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1601d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn @Override 1602d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn public void computeScroll() { 1603a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (!mScroller.isFinished() && mScroller.computeScrollOffset()) { 1604a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell int oldX = getScrollX(); 1605a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell int oldY = getScrollY(); 1606a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell int x = mScroller.getCurrX(); 1607a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell int y = mScroller.getCurrY(); 16083661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 1609a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (oldX != x || oldY != y) { 1610a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell scrollTo(x, y); 16114783095cc69fa85e484132337526c94d42d41c43Adam Powell if (!pageScrolled(x)) { 16124783095cc69fa85e484132337526c94d42d41c43Adam Powell mScroller.abortAnimation(); 16134783095cc69fa85e484132337526c94d42d41c43Adam Powell scrollTo(0, y); 16144783095cc69fa85e484132337526c94d42d41c43Adam Powell } 1615d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1616a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 1617a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // Keep on drawing until the animation has finished. 1618b469af6dc2f8cda4020a78fb4582c1483089fd6eAdam Powell ViewCompat.postInvalidateOnAnimation(this); 1619a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell return; 1620d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 16214c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn 16224c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn // Done with scroll, clean up state. 162371d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio completeScroll(true); 1624d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1625d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 16264783095cc69fa85e484132337526c94d42d41c43Adam Powell private boolean pageScrolled(int xpos) { 16274783095cc69fa85e484132337526c94d42d41c43Adam Powell if (mItems.size() == 0) { 16284783095cc69fa85e484132337526c94d42d41c43Adam Powell mCalledSuper = false; 16294783095cc69fa85e484132337526c94d42d41c43Adam Powell onPageScrolled(0, 0, 0); 16304783095cc69fa85e484132337526c94d42d41c43Adam Powell if (!mCalledSuper) { 16314783095cc69fa85e484132337526c94d42d41c43Adam Powell throw new IllegalStateException( 16324783095cc69fa85e484132337526c94d42d41c43Adam Powell "onPageScrolled did not call superclass implementation"); 16334783095cc69fa85e484132337526c94d42d41c43Adam Powell } 16344783095cc69fa85e484132337526c94d42d41c43Adam Powell return false; 16354783095cc69fa85e484132337526c94d42d41c43Adam Powell } 1636a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final ItemInfo ii = infoForCurrentScrollPosition(); 1637becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu final int width = getClientWidth(); 1638a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int widthWithMargin = width + mPageMargin; 1639a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final float marginOffset = (float) mPageMargin / width; 1640a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int currentPage = ii.position; 1641a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final float pageOffset = (((float) xpos / width) - ii.offset) / 1642a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell (ii.widthFactor + marginOffset); 1643a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int offsetPixels = (int) (pageOffset * widthWithMargin); 16448fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 16458fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mCalledSuper = false; 1646a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell onPageScrolled(currentPage, pageOffset, offsetPixels); 16478fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (!mCalledSuper) { 16488fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell throw new IllegalStateException( 16498fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell "onPageScrolled did not call superclass implementation"); 16508fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 16514783095cc69fa85e484132337526c94d42d41c43Adam Powell return true; 16528fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 16538fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 16548fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell /** 16558fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * This method will be invoked when the current page is scrolled, either as part 16568fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * of a programmatically initiated smooth scroll or a user initiated touch scroll. 16578fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * If you override this method you must call through to the superclass implementation 16588fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * (e.g. super.onPageScrolled(position, offset, offsetPixels)) before onPageScrolled 16598fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * returns. 16608fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * 16618fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * @param position Position index of the first page currently being displayed. 16628fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * Page position+1 will be visible if positionOffset is nonzero. 16638fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * @param offset Value from [0, 1) indicating the offset from the page at position. 16648fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * @param offsetPixels Value in pixels indicating the offset from position. 16658fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell */ 16668fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell protected void onPageScrolled(int position, float offset, int offsetPixels) { 16678fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell // Offset any decor views if needed - keep them on-screen at all times. 16688fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (mDecorChildCount > 0) { 16698fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int scrollX = getScrollX(); 16708fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell int paddingLeft = getPaddingLeft(); 16718fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell int paddingRight = getPaddingRight(); 16728fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int width = getWidth(); 16738fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int childCount = getChildCount(); 16748fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell for (int i = 0; i < childCount; i++) { 16758fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final View child = getChildAt(i); 16768fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 16778fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (!lp.isDecor) continue; 16788fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 16798fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; 16808fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell int childLeft = 0; 16818fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell switch (hgrav) { 16828fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell default: 16838fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell childLeft = paddingLeft; 16848fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell break; 16858fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell case Gravity.LEFT: 16868fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell childLeft = paddingLeft; 16878fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell paddingLeft += child.getWidth(); 16888fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell break; 16898fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell case Gravity.CENTER_HORIZONTAL: 16908fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell childLeft = Math.max((width - child.getMeasuredWidth()) / 2, 16918fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell paddingLeft); 16928fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell break; 16938fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell case Gravity.RIGHT: 16948fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell childLeft = width - paddingRight - child.getMeasuredWidth(); 16958fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell paddingRight += child.getMeasuredWidth(); 16968fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell break; 16978fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 16988fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell childLeft += scrollX; 16998fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 17008fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int childOffset = childLeft - child.getLeft(); 17018fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (childOffset != 0) { 17028fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell child.offsetLeftAndRight(childOffset); 17038fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 17048fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 17058fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 17068fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 17078fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (mOnPageChangeListener != null) { 17088fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mOnPageChangeListener.onPageScrolled(position, offset, offsetPixels); 17098fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 17108fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (mInternalPageChangeListener != null) { 17118fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mInternalPageChangeListener.onPageScrolled(position, offset, offsetPixels); 17128fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 17138a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell 17148a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell if (mPageTransformer != null) { 17158a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell final int scrollX = getScrollX(); 17168a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell final int childCount = getChildCount(); 17178a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell for (int i = 0; i < childCount; i++) { 17188a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell final View child = getChildAt(i); 17197e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 17207e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell 17217e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell if (lp.isDecor) continue; 17227e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell 1723becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu final float transformPos = (float) (child.getLeft() - scrollX) / getClientWidth(); 17248a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell mPageTransformer.transformPage(child, transformPos); 17258a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell } 17268a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell } 17278a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell 17288fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mCalledSuper = true; 17298fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 17308fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 173171d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio private void completeScroll(boolean postEvents) { 17328d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell boolean needPopulate = mScrollState == SCROLL_STATE_SETTLING; 1733cf2312ee850d26c9d1a2413c996d41397e816fb5Minh Pham if (needPopulate) { 17344c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn // Done with scroll, no longer want to cache view drawing. 17354c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn setScrollingCacheEnabled(false); 1736d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mScroller.abortAnimation(); 1737d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn int oldX = getScrollX(); 1738d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn int oldY = getScrollY(); 1739d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn int x = mScroller.getCurrX(); 1740d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn int y = mScroller.getCurrY(); 1741d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (oldX != x || oldY != y) { 1742d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn scrollTo(x, y); 1743d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 17444c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn } 17453661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell mPopulatePending = false; 17464c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn for (int i=0; i<mItems.size(); i++) { 17474c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn ItemInfo ii = mItems.get(i); 17484c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn if (ii.scrolling) { 17494c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn needPopulate = true; 17504c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn ii.scrolling = false; 17514c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn } 17524c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn } 17534c2eb6dc16814bc44915d7603d1af465dff0407dDianne Hackborn if (needPopulate) { 175471d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio if (postEvents) { 175571d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio ViewCompat.postOnAnimation(this, mEndScrollRunnable); 175671d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio } else { 175771d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio mEndScrollRunnable.run(); 175871d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio } 1759d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1760d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1761d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 17628f19b17dbc34bfc7e5caacbf83a7099e5cb5a47cAdam Powell private boolean isGutterDrag(float x, float dx) { 17638f19b17dbc34bfc7e5caacbf83a7099e5cb5a47cAdam Powell return (x < mGutterSize && dx > 0) || (x > getWidth() - mGutterSize && dx < 0); 17648f19b17dbc34bfc7e5caacbf83a7099e5cb5a47cAdam Powell } 17658f19b17dbc34bfc7e5caacbf83a7099e5cb5a47cAdam Powell 17668a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell private void enableLayers(boolean enable) { 17678a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell final int childCount = getChildCount(); 17688a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell for (int i = 0; i < childCount; i++) { 17698a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell final int layerType = enable ? 17708a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell ViewCompat.LAYER_TYPE_HARDWARE : ViewCompat.LAYER_TYPE_NONE; 17718a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell ViewCompat.setLayerType(getChildAt(i), layerType, null); 17728a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell } 17738a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell } 17748a0c51a3d438802df28612e02fdf0cc8fab06ddbAdam Powell 1775d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn @Override 1776d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn public boolean onInterceptTouchEvent(MotionEvent ev) { 1777d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn /* 1778d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * This method JUST determines whether we want to intercept the motion. 1779d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * If we return true, onMotionEvent will be called and we do the actual 1780d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * scrolling there. 1781d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn */ 1782d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1783d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn final int action = ev.getAction() & MotionEventCompat.ACTION_MASK; 1784d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1785d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // Always take care of the touch gesture being complete. 1786d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { 1787d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // Release the drag. 1788d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (DEBUG) Log.v(TAG, "Intercept done!"); 1789d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mIsBeingDragged = false; 1790d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mIsUnableToDrag = false; 1791d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mActivePointerId = INVALID_POINTER; 17923ce9274ccb8034c1787415c77307bbda36071bddAdam Powell if (mVelocityTracker != null) { 17933ce9274ccb8034c1787415c77307bbda36071bddAdam Powell mVelocityTracker.recycle(); 17943ce9274ccb8034c1787415c77307bbda36071bddAdam Powell mVelocityTracker = null; 17953ce9274ccb8034c1787415c77307bbda36071bddAdam Powell } 1796d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn return false; 1797d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1798d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1799d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // Nothing more to do here if we have decided whether or not we 1800d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // are dragging. 1801d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (action != MotionEvent.ACTION_DOWN) { 1802d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (mIsBeingDragged) { 1803d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (DEBUG) Log.v(TAG, "Intercept returning true!"); 1804d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn return true; 1805d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1806d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (mIsUnableToDrag) { 1807d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (DEBUG) Log.v(TAG, "Intercept returning false!"); 1808d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn return false; 1809d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1810d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1811d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1812d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn switch (action) { 1813d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn case MotionEvent.ACTION_MOVE: { 1814d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn /* 1815d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check 1816d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * whether the user has moved far enough from his original down touch. 1817d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn */ 1818d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1819d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn /* 1820d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * Locally do absolute value. mLastMotionY is set to the y value 1821d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * of the down event. 1822d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn */ 1823d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn final int activePointerId = mActivePointerId; 1824d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (activePointerId == INVALID_POINTER) { 1825d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // If we don't have a valid id, the touch down wasn't on content. 1826d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn break; 1827d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1828d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1829d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn final int pointerIndex = MotionEventCompat.findPointerIndex(ev, activePointerId); 1830d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn final float x = MotionEventCompat.getX(ev, pointerIndex); 183147dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell final float dx = x - mLastMotionX; 183247dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell final float xDiff = Math.abs(dx); 1833d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn final float y = MotionEventCompat.getY(ev, pointerIndex); 183416991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell final float yDiff = Math.abs(y - mInitialMotionY); 1835d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (DEBUG) Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff); 1836bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell 18378f19b17dbc34bfc7e5caacbf83a7099e5cb5a47cAdam Powell if (dx != 0 && !isGutterDrag(mLastMotionX, dx) && 18388f19b17dbc34bfc7e5caacbf83a7099e5cb5a47cAdam Powell canScroll(this, false, (int) dx, (int) x, (int) y)) { 1839bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell // Nested view has scrollable area under this point. Let it be handled there. 184016991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell mLastMotionX = x; 1841bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell mLastMotionY = y; 1842b469af6dc2f8cda4020a78fb4582c1483089fd6eAdam Powell mIsUnableToDrag = true; 1843bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell return false; 1844bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell } 184516991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell if (xDiff > mTouchSlop && xDiff * 0.5f > yDiff) { 1846d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (DEBUG) Log.v(TAG, "Starting drag!"); 1847d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mIsBeingDragged = true; 184847dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell setScrollState(SCROLL_STATE_DRAGGING); 18498d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell mLastMotionX = dx > 0 ? mInitialMotionX + mTouchSlop : 18508d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell mInitialMotionX - mTouchSlop; 185116991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell mLastMotionY = y; 1852d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn setScrollingCacheEnabled(true); 185316991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell } else if (yDiff > mTouchSlop) { 185416991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell // The finger has moved enough in the vertical 185516991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell // direction to be counted as a drag... abort 185616991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell // any attempt to drag horizontally, to work correctly 185716991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell // with children that have scrolling containers. 185816991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell if (DEBUG) Log.v(TAG, "Starting unable to drag!"); 185916991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell mIsUnableToDrag = true; 1860d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 18616e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell if (mIsBeingDragged) { 18626e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell // Scroll to follow the motion event 18636e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell if (performDrag(x)) { 18646e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell ViewCompat.postInvalidateOnAnimation(this); 18656e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell } 18666e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell } 1867d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn break; 1868d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1869d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1870d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn case MotionEvent.ACTION_DOWN: { 1871d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn /* 1872d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * Remember location of down touch. 1873d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn * ACTION_DOWN always refers to pointer index 0. 1874d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn */ 1875d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mLastMotionX = mInitialMotionX = ev.getX(); 187616991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell mLastMotionY = mInitialMotionY = ev.getY(); 1877d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mActivePointerId = MotionEventCompat.getPointerId(ev, 0); 1878b469af6dc2f8cda4020a78fb4582c1483089fd6eAdam Powell mIsUnableToDrag = false; 1879d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 18808d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell mScroller.computeScrollOffset(); 1881b469af6dc2f8cda4020a78fb4582c1483089fd6eAdam Powell if (mScrollState == SCROLL_STATE_SETTLING && 1882b469af6dc2f8cda4020a78fb4582c1483089fd6eAdam Powell Math.abs(mScroller.getFinalX() - mScroller.getCurrX()) > mCloseEnough) { 188347dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell // Let the user 'catch' the pager as it animates. 18848d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell mScroller.abortAnimation(); 18858d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell mPopulatePending = false; 18868d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell populate(); 188747dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell mIsBeingDragged = true; 188847dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell setScrollState(SCROLL_STATE_DRAGGING); 188947dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell } else { 189071d54737b6d60ec99799aabdf9b48d2da26d8ccbFabrice Di Meglio completeScroll(false); 189147dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell mIsBeingDragged = false; 189247dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell } 1893d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1894d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (DEBUG) Log.v(TAG, "Down at " + mLastMotionX + "," + mLastMotionY 1895d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn + " mIsBeingDragged=" + mIsBeingDragged 1896d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn + "mIsUnableToDrag=" + mIsUnableToDrag); 1897d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn break; 1898d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1899d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1900d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn case MotionEventCompat.ACTION_POINTER_UP: 1901d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn onSecondaryPointerUp(ev); 1902d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn break; 1903d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1904d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 19058d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell if (mVelocityTracker == null) { 19068d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell mVelocityTracker = VelocityTracker.obtain(); 19073ce9274ccb8034c1787415c77307bbda36071bddAdam Powell } 19088d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell mVelocityTracker.addMovement(ev); 19093ce9274ccb8034c1787415c77307bbda36071bddAdam Powell 1910d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn /* 19113ce9274ccb8034c1787415c77307bbda36071bddAdam Powell * The only time we want to intercept motion events is if we are in the 19123ce9274ccb8034c1787415c77307bbda36071bddAdam Powell * drag mode. 19133ce9274ccb8034c1787415c77307bbda36071bddAdam Powell */ 1914d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn return mIsBeingDragged; 1915d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1916d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1917d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn @Override 1918d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn public boolean onTouchEvent(MotionEvent ev) { 191969b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell if (mFakeDragging) { 192069b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell // A fake drag is in progress already, ignore this real one 192169b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell // but still eat the touch events. 192269b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell // (It is likely that the user is multi-touching the screen.) 192369b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell return true; 192469b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell } 1925d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1926d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (ev.getAction() == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) { 1927d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // Don't handle edge touches immediately -- they may actually belong to one of our 1928d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // descendants. 1929d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn return false; 1930d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1931d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 19323661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell if (mAdapter == null || mAdapter.getCount() == 0) { 19333661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell // Nothing to present or scroll; nothing to touch. 19343661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell return false; 19353661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 19363661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 1937d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (mVelocityTracker == null) { 1938d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mVelocityTracker = VelocityTracker.obtain(); 1939d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1940d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mVelocityTracker.addMovement(ev); 1941d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1942d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn final int action = ev.getAction(); 1943560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell boolean needsInvalidate = false; 1944d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1945d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn switch (action & MotionEventCompat.ACTION_MASK) { 1946d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn case MotionEvent.ACTION_DOWN: { 19478d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell mScroller.abortAnimation(); 19488d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell mPopulatePending = false; 19498d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell populate(); 1950d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 1951d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // Remember where the motion event started 1952d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mLastMotionX = mInitialMotionX = ev.getX(); 195316991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell mLastMotionY = mInitialMotionY = ev.getY(); 1954d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mActivePointerId = MotionEventCompat.getPointerId(ev, 0); 1955d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn break; 1956d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1957d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn case MotionEvent.ACTION_MOVE: 19583661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell if (!mIsBeingDragged) { 19593661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); 19603661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell final float x = MotionEventCompat.getX(ev, pointerIndex); 196147dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell final float xDiff = Math.abs(x - mLastMotionX); 19623661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell final float y = MotionEventCompat.getY(ev, pointerIndex); 196347dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell final float yDiff = Math.abs(y - mLastMotionY); 19643661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell if (DEBUG) Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff); 19653661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell if (xDiff > mTouchSlop && xDiff > yDiff) { 19663661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell if (DEBUG) Log.v(TAG, "Starting drag!"); 19673661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell mIsBeingDragged = true; 19688d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell mLastMotionX = x - mInitialMotionX > 0 ? mInitialMotionX + mTouchSlop : 19698d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell mInitialMotionX - mTouchSlop; 197016991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell mLastMotionY = y; 197147dc57337c13a2760ea3512ad84d6aa9f24ccd28Adam Powell setScrollState(SCROLL_STATE_DRAGGING); 19723661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell setScrollingCacheEnabled(true); 197323f32662b0e412510094d59c478f1d5370a15244Chris Banes 197423f32662b0e412510094d59c478f1d5370a15244Chris Banes // Disallow Parent Intercept, just in case 197523f32662b0e412510094d59c478f1d5370a15244Chris Banes ViewParent parent = getParent(); 197623f32662b0e412510094d59c478f1d5370a15244Chris Banes if (parent != null) { 197723f32662b0e412510094d59c478f1d5370a15244Chris Banes parent.requestDisallowInterceptTouchEvent(true); 197823f32662b0e412510094d59c478f1d5370a15244Chris Banes } 19793661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 19803661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 198131bb17f88734747206586eeb3eb57123e3cc2434Adam Powell // Not else! Note that mIsBeingDragged can be set above. 1982d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (mIsBeingDragged) { 1983d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // Scroll to follow the motion event 1984d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn final int activePointerIndex = MotionEventCompat.findPointerIndex( 1985d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn ev, mActivePointerId); 1986d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn final float x = MotionEventCompat.getX(ev, activePointerIndex); 19876e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell needsInvalidate |= performDrag(x); 1988d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 1989d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn break; 1990d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn case MotionEvent.ACTION_UP: 1991d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (mIsBeingDragged) { 1992d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn final VelocityTracker velocityTracker = mVelocityTracker; 1993d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); 19941cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell int initialVelocity = (int) VelocityTrackerCompat.getXVelocity( 1995d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn velocityTracker, mActivePointerId); 1996d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mPopulatePending = true; 1997becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu final int width = getClientWidth(); 19981cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell final int scrollX = getScrollX(); 1999a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final ItemInfo ii = infoForCurrentScrollPosition(); 2000a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int currentPage = ii.position; 2001a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final float pageOffset = (((float) scrollX / width) - ii.offset) / ii.widthFactor; 2002035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell final int activePointerIndex = 2003035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell MotionEventCompat.findPointerIndex(ev, mActivePointerId); 2004035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell final float x = MotionEventCompat.getX(ev, activePointerIndex); 2005035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell final int totalDelta = (int) (x - mInitialMotionX); 2006035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell int nextPage = determineTargetPage(currentPage, pageOffset, initialVelocity, 2007035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell totalDelta); 20081cbf48f28f6ef523af2a4aafa98c5437964cb48aAdam Powell setCurrentItemInternal(nextPage, true, true, initialVelocity); 2009d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 2010d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mActivePointerId = INVALID_POINTER; 2011d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn endDrag(); 2012560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell needsInvalidate = mLeftEdge.onRelease() | mRightEdge.onRelease(); 2013d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 2014d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn break; 2015d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn case MotionEvent.ACTION_CANCEL: 2016d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (mIsBeingDragged) { 2017a862399a9f738aa7e14012bc30491627f9dc6befPhilip Milne scrollToItem(mCurItem, true, 0, false); 2018d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mActivePointerId = INVALID_POINTER; 2019d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn endDrag(); 2020560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell needsInvalidate = mLeftEdge.onRelease() | mRightEdge.onRelease(); 2021d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 2022d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn break; 2023d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn case MotionEventCompat.ACTION_POINTER_DOWN: { 2024d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn final int index = MotionEventCompat.getActionIndex(ev); 2025d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn final float x = MotionEventCompat.getX(ev, index); 2026d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mLastMotionX = x; 2027d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mActivePointerId = MotionEventCompat.getPointerId(ev, index); 2028d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn break; 2029d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 2030d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn case MotionEventCompat.ACTION_POINTER_UP: 2031d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn onSecondaryPointerUp(ev); 2032d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mLastMotionX = MotionEventCompat.getX(ev, 2033d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn MotionEventCompat.findPointerIndex(ev, mActivePointerId)); 2034d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn break; 2035d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 2036560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell if (needsInvalidate) { 2037b469af6dc2f8cda4020a78fb4582c1483089fd6eAdam Powell ViewCompat.postInvalidateOnAnimation(this); 2038560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 2039d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn return true; 2040d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 2041d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 20426e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell private boolean performDrag(float x) { 20436e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell boolean needsInvalidate = false; 20446e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell 20456e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell final float deltaX = mLastMotionX - x; 20466e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell mLastMotionX = x; 20476e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell 20486e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell float oldScrollX = getScrollX(); 20496e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell float scrollX = oldScrollX + deltaX; 2050becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu final int width = getClientWidth(); 20516e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell 20526e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell float leftBound = width * mFirstOffset; 20536e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell float rightBound = width * mLastOffset; 20546e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell boolean leftAbsolute = true; 20556e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell boolean rightAbsolute = true; 20566e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell 20576e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell final ItemInfo firstItem = mItems.get(0); 20586e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell final ItemInfo lastItem = mItems.get(mItems.size() - 1); 20596e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell if (firstItem.position != 0) { 20606e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell leftAbsolute = false; 20616e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell leftBound = firstItem.offset * width; 20626e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell } 20636e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell if (lastItem.position != mAdapter.getCount() - 1) { 20646e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell rightAbsolute = false; 20656e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell rightBound = lastItem.offset * width; 20666e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell } 20676e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell 20686e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell if (scrollX < leftBound) { 20696e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell if (leftAbsolute) { 20706e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell float over = leftBound - scrollX; 20716e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell needsInvalidate = mLeftEdge.onPull(Math.abs(over) / width); 20726e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell } 20736e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell scrollX = leftBound; 20746e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell } else if (scrollX > rightBound) { 20756e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell if (rightAbsolute) { 20766e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell float over = scrollX - rightBound; 20776e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell needsInvalidate = mRightEdge.onPull(Math.abs(over) / width); 20786e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell } 20796e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell scrollX = rightBound; 20806e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell } 20816e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell // Don't lose the rounded component 20826e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell mLastMotionX += scrollX - (int) scrollX; 20836e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell scrollTo((int) scrollX, getScrollY()); 20846e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell pageScrolled((int) scrollX); 20856e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell 20866e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell return needsInvalidate; 20876e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell } 20886e7700ca575523895f8ebc5696e3e57aeccf30c0Adam Powell 2089a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell /** 2090a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * @return Info about the page at the current scroll position. 2091a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * This can be synthetic for a missing middle page; the 'object' field can be null. 2092a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell */ 2093a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell private ItemInfo infoForCurrentScrollPosition() { 2094becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu final int width = getClientWidth(); 2095a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final float scrollOffset = width > 0 ? (float) getScrollX() / width : 0; 2096a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final float marginOffset = width > 0 ? (float) mPageMargin / width : 0; 2097a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell int lastPos = -1; 2098a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell float lastOffset = 0.f; 2099a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell float lastWidth = 0.f; 2100a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell boolean first = true; 2101a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 2102ad079a869adf67a87a2721342de27970a3ba1844Adam Powell ItemInfo lastItem = null; 2103a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell for (int i = 0; i < mItems.size(); i++) { 2104a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ItemInfo ii = mItems.get(i); 2105a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell float offset; 2106a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (!first && ii.position != lastPos + 1) { 2107a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // Create a synthetic item for a missing page. 2108a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii = mTempItem; 2109a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii.offset = lastOffset + lastWidth + marginOffset; 2110a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii.position = lastPos + 1; 2111a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii.widthFactor = mAdapter.getPageWidth(ii.position); 2112a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell i--; 2113a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 2114a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell offset = ii.offset; 2115a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 21168d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell final float leftBound = offset; 21178d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell final float rightBound = offset + ii.widthFactor + marginOffset; 2118ad079a869adf67a87a2721342de27970a3ba1844Adam Powell if (first || scrollOffset >= leftBound) { 2119ad079a869adf67a87a2721342de27970a3ba1844Adam Powell if (scrollOffset < rightBound || i == mItems.size() - 1) { 2120ad079a869adf67a87a2721342de27970a3ba1844Adam Powell return ii; 2121ad079a869adf67a87a2721342de27970a3ba1844Adam Powell } 2122ad079a869adf67a87a2721342de27970a3ba1844Adam Powell } else { 2123ad079a869adf67a87a2721342de27970a3ba1844Adam Powell return lastItem; 2124a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 2125a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell first = false; 2126a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell lastPos = ii.position; 2127a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell lastOffset = offset; 2128a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell lastWidth = ii.widthFactor; 2129ad079a869adf67a87a2721342de27970a3ba1844Adam Powell lastItem = ii; 2130a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 2131a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 2132ad079a869adf67a87a2721342de27970a3ba1844Adam Powell return lastItem; 2133a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 2134a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 2135035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell private int determineTargetPage(int currentPage, float pageOffset, int velocity, int deltaX) { 2136035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell int targetPage; 2137035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell if (Math.abs(deltaX) > mFlingDistance && Math.abs(velocity) > mMinimumVelocity) { 2138035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell targetPage = velocity > 0 ? currentPage : currentPage + 1; 2139035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell } else { 214016991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell final float truncator = currentPage >= mCurItem ? 0.4f : 0.6f; 214116991ca86a49023bf6eb47b4e215bb1f2209de6dAdam Powell targetPage = (int) (currentPage + pageOffset + truncator); 2142035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell } 2143035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell 2144a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (mItems.size() > 0) { 2145a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final ItemInfo firstItem = mItems.get(0); 2146a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final ItemInfo lastItem = mItems.get(mItems.size() - 1); 2147a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 2148a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // Only let the user target pages we have items for 2149a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell targetPage = Math.max(firstItem.position, Math.min(targetPage, lastItem.position)); 2150a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 2151a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 2152035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell return targetPage; 2153035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell } 2154035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell 2155560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell @Override 2156560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public void draw(Canvas canvas) { 2157560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell super.draw(canvas); 2158560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell boolean needsInvalidate = false; 2159560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 2160560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell final int overScrollMode = ViewCompat.getOverScrollMode(this); 2161560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell if (overScrollMode == ViewCompat.OVER_SCROLL_ALWAYS || 2162560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell (overScrollMode == ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS && 2163560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell mAdapter != null && mAdapter.getCount() > 1)) { 2164560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell if (!mLeftEdge.isFinished()) { 2165560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell final int restoreCount = canvas.save(); 2166560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell final int height = getHeight() - getPaddingTop() - getPaddingBottom(); 2167a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int width = getWidth(); 2168560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 2169560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell canvas.rotate(270); 2170a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell canvas.translate(-height + getPaddingTop(), mFirstOffset * width); 2171a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mLeftEdge.setSize(height, width); 2172560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell needsInvalidate |= mLeftEdge.draw(canvas); 2173560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell canvas.restoreToCount(restoreCount); 2174560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 2175560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell if (!mRightEdge.isFinished()) { 2176560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell final int restoreCount = canvas.save(); 2177560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell final int width = getWidth(); 2178560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell final int height = getHeight() - getPaddingTop() - getPaddingBottom(); 2179560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 2180560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell canvas.rotate(90); 2181a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell canvas.translate(-getPaddingTop(), -(mLastOffset + 1) * width); 2182560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell mRightEdge.setSize(height, width); 2183560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell needsInvalidate |= mRightEdge.draw(canvas); 2184560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell canvas.restoreToCount(restoreCount); 2185560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 2186560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } else { 2187560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell mLeftEdge.finish(); 2188560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell mRightEdge.finish(); 2189560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 2190560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 2191560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell if (needsInvalidate) { 2192560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell // Keep animating 2193b469af6dc2f8cda4020a78fb4582c1483089fd6eAdam Powell ViewCompat.postInvalidateOnAnimation(this); 2194560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 2195560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 2196560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 2197329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell @Override 2198329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell protected void onDraw(Canvas canvas) { 2199329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell super.onDraw(canvas); 2200329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell 2201a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell // Draw the margin drawable between pages if needed. 2202a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (mPageMargin > 0 && mMarginDrawable != null && mItems.size() > 0 && mAdapter != null) { 2203329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell final int scrollX = getScrollX(); 2204329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell final int width = getWidth(); 2205a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 2206a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final float marginOffset = (float) mPageMargin / width; 2207a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell int itemIndex = 0; 2208a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ItemInfo ii = mItems.get(0); 2209a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell float offset = ii.offset; 2210a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int itemCount = mItems.size(); 2211a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int firstPos = ii.position; 2212a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int lastPos = mItems.get(itemCount - 1).position; 2213a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell for (int pos = firstPos; pos < lastPos; pos++) { 2214a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell while (pos > ii.position && itemIndex < itemCount) { 2215a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell ii = mItems.get(++itemIndex); 2216a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 2217a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 221823b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell float drawAt; 2219a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (pos == ii.position) { 222023b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell drawAt = (ii.offset + ii.widthFactor) * width; 2221a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell offset = ii.offset + ii.widthFactor + marginOffset; 2222a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } else { 2223a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell float widthFactor = mAdapter.getPageWidth(pos); 222423b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell drawAt = (offset + widthFactor) * width; 2225a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell offset += widthFactor + marginOffset; 2226a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 2227a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 2228a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (drawAt + mPageMargin > scrollX) { 2229a56d6faa9df608aaa2907864669800abb68acec7Adam Powell mMarginDrawable.setBounds((int) drawAt, mTopPageBounds, 223023b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell (int) (drawAt + mPageMargin + 0.5f), mBottomPageBounds); 2231a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mMarginDrawable.draw(canvas); 2232a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 2233a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 2234a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (drawAt > scrollX + width) { 2235a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell break; // No more visible, no sense in continuing 2236a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 2237329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell } 2238329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell } 2239329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell } 2240329da4d5431ae7923279b56b45b84e70c52f8eeeAdam Powell 224169b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell /** 224269b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * Start a fake drag of the pager. 224369b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * 224469b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * <p>A fake drag can be useful if you want to synchronize the motion of the ViewPager 224569b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * with the touch scrolling of another view, while still letting the ViewPager 224669b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * control the snapping motion and fling behavior. (e.g. parallax-scrolling tabs.) 224769b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * Call {@link #fakeDragBy(float)} to simulate the actual drag motion. Call 224869b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * {@link #endFakeDrag()} to complete the fake drag and fling as necessary. 224969b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * 225069b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * <p>During a fake drag the ViewPager will ignore all touch events. If a real drag 225169b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * is already in progress, this method will return false. 225269b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * 225369b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * @return true if the fake drag began successfully, false if it could not be started. 225469b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * 225569b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * @see #fakeDragBy(float) 225669b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * @see #endFakeDrag() 225769b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell */ 225869b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell public boolean beginFakeDrag() { 225969b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell if (mIsBeingDragged) { 226069b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell return false; 226169b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell } 226269b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell mFakeDragging = true; 226369b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell setScrollState(SCROLL_STATE_DRAGGING); 226469b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell mInitialMotionX = mLastMotionX = 0; 226569b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell if (mVelocityTracker == null) { 226669b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell mVelocityTracker = VelocityTracker.obtain(); 226769b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell } else { 226869b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell mVelocityTracker.clear(); 226969b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell } 227069b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell final long time = SystemClock.uptimeMillis(); 227169b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell final MotionEvent ev = MotionEvent.obtain(time, time, MotionEvent.ACTION_DOWN, 0, 0, 0); 227269b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell mVelocityTracker.addMovement(ev); 227369b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell ev.recycle(); 227469b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell mFakeDragBeginTime = time; 227569b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell return true; 227669b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell } 227769b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell 227869b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell /** 227969b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * End a fake drag of the pager. 228069b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * 228169b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * @see #beginFakeDrag() 228269b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * @see #fakeDragBy(float) 228369b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell */ 228469b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell public void endFakeDrag() { 228569b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell if (!mFakeDragging) { 228669b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell throw new IllegalStateException("No fake drag in progress. Call beginFakeDrag first."); 228769b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell } 228869b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell 228969b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell final VelocityTracker velocityTracker = mVelocityTracker; 229069b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); 22910f034dc2c69044597a91649b8c073ae5e98a2f25Adam Powell int initialVelocity = (int) VelocityTrackerCompat.getXVelocity( 229269b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell velocityTracker, mActivePointerId); 229369b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell mPopulatePending = true; 2294becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu final int width = getClientWidth(); 2295035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell final int scrollX = getScrollX(); 2296a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final ItemInfo ii = infoForCurrentScrollPosition(); 2297a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int currentPage = ii.position; 2298a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final float pageOffset = (((float) scrollX / width) - ii.offset) / ii.widthFactor; 2299a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int totalDelta = (int) (mLastMotionX - mInitialMotionX); 2300a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell int nextPage = determineTargetPage(currentPage, pageOffset, initialVelocity, 2301a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell totalDelta); 2302035f6aa81bbb439d2aa20dcd2eac4459a76d561eAdam Powell setCurrentItemInternal(nextPage, true, true, initialVelocity); 230369b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell endDrag(); 230469b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell 230569b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell mFakeDragging = false; 230669b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell } 230769b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell 230869b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell /** 230969b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * Fake drag by an offset in pixels. You must have called {@link #beginFakeDrag()} first. 231069b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * 231169b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * @param xOffset Offset in pixels to drag by. 231269b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * @see #beginFakeDrag() 231369b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * @see #endFakeDrag() 231469b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell */ 231569b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell public void fakeDragBy(float xOffset) { 231669b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell if (!mFakeDragging) { 231769b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell throw new IllegalStateException("No fake drag in progress. Call beginFakeDrag first."); 231869b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell } 231969b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell 232069b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell mLastMotionX += xOffset; 2321a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 2322a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell float oldScrollX = getScrollX(); 23230f034dc2c69044597a91649b8c073ae5e98a2f25Adam Powell float scrollX = oldScrollX - xOffset; 2324becb552984e4693c87f5f0ae38b6ebf4f719b740Dake Gu final int width = getClientWidth(); 232569b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell 2326a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell float leftBound = width * mFirstOffset; 2327a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell float rightBound = width * mLastOffset; 2328a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 2329a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final ItemInfo firstItem = mItems.get(0); 2330a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final ItemInfo lastItem = mItems.get(mItems.size() - 1); 2331a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (firstItem.position != 0) { 2332a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell leftBound = firstItem.offset * width; 2333a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 2334a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell if (lastItem.position != mAdapter.getCount() - 1) { 2335a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell rightBound = lastItem.offset * width; 2336a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 2337a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 233869b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell if (scrollX < leftBound) { 233969b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell scrollX = leftBound; 234069b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell } else if (scrollX > rightBound) { 234169b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell scrollX = rightBound; 234269b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell } 234369b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell // Don't lose the rounded component 234469b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell mLastMotionX += scrollX - (int) scrollX; 234569b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell scrollTo((int) scrollX, getScrollY()); 23468fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell pageScrolled((int) scrollX); 234769b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell 234869b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell // Synthesize an event for the VelocityTracker. 234969b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell final long time = SystemClock.uptimeMillis(); 235069b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell final MotionEvent ev = MotionEvent.obtain(mFakeDragBeginTime, time, MotionEvent.ACTION_MOVE, 235169b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell mLastMotionX, 0, 0); 235269b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell mVelocityTracker.addMovement(ev); 235369b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell ev.recycle(); 235469b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell } 235569b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell 235669b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell /** 235769b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * Returns true if a fake drag is in progress. 235869b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * 235969b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * @return true if currently in a fake drag, false otherwise. 236069b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * 236169b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * @see #beginFakeDrag() 236269b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * @see #fakeDragBy(float) 236369b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell * @see #endFakeDrag() 236469b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell */ 236569b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell public boolean isFakeDragging() { 236669b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell return mFakeDragging; 236769b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell } 236869b7a33f67a5577ceb2bd43ff389d89b592f85b1Adam Powell 2369d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private void onSecondaryPointerUp(MotionEvent ev) { 2370d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn final int pointerIndex = MotionEventCompat.getActionIndex(ev); 2371d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); 2372d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (pointerId == mActivePointerId) { 2373d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // This was our active pointer going up. Choose a new 2374d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn // active pointer and adjust accordingly. 2375d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn final int newPointerIndex = pointerIndex == 0 ? 1 : 0; 2376d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mLastMotionX = MotionEventCompat.getX(ev, newPointerIndex); 2377d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); 2378d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (mVelocityTracker != null) { 2379d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mVelocityTracker.clear(); 2380d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 2381d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 2382d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 2383d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 2384d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private void endDrag() { 2385d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mIsBeingDragged = false; 2386d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mIsUnableToDrag = false; 2387d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 2388d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (mVelocityTracker != null) { 2389d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mVelocityTracker.recycle(); 2390d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mVelocityTracker = null; 2391d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 2392d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 2393d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn 2394d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn private void setScrollingCacheEnabled(boolean enabled) { 2395d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (mScrollingCacheEnabled != enabled) { 2396d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn mScrollingCacheEnabled = enabled; 2397d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (USE_CACHE) { 2398d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn final int size = getChildCount(); 2399d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn for (int i = 0; i < size; ++i) { 2400d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn final View child = getChildAt(i); 2401d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn if (child.getVisibility() != GONE) { 2402d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn child.setDrawingCacheEnabled(enabled); 2403d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 2404d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 2405d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 2406d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 2407d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn } 24083661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell 2409bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell /** 2410cf2312ee850d26c9d1a2413c996d41397e816fb5Minh Pham * Tests scrollability within child views of v given a delta of dx. 2411bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell * 2412bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell * @param v View to test for horizontal scrollability 2413bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell * @param checkV Whether the view v passed should itself be checked for scrollability (true), 2414bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell * or just its children (false). 2415bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell * @param dx Delta scrolled in pixels 2416cf2312ee850d26c9d1a2413c996d41397e816fb5Minh Pham * @param x X coordinate of the active touch point 2417bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell * @param y Y coordinate of the active touch point 2418cf2312ee850d26c9d1a2413c996d41397e816fb5Minh Pham * @return true if child views of v can be scrolled by delta of dx. 2419bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell */ 2420cf2312ee850d26c9d1a2413c996d41397e816fb5Minh Pham protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) { 2421bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell if (v instanceof ViewGroup) { 2422bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell final ViewGroup group = (ViewGroup) v; 2423bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell final int scrollX = v.getScrollX(); 2424bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell final int scrollY = v.getScrollY(); 2425bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell final int count = group.getChildCount(); 2426bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell // Count backwards - let topmost views consume scroll distance first. 2427bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell for (int i = count - 1; i >= 0; i--) { 2428bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell // TODO: Add versioned support here for transformed views. 2429bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell // This will not work for transformed views in Honeycomb+ 2430bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell final View child = group.getChildAt(i); 2431bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() && 2432bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell y + scrollY >= child.getTop() && y + scrollY < child.getBottom() && 2433bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell canScroll(child, true, dx, x + scrollX - child.getLeft(), 2434bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell y + scrollY - child.getTop())) { 2435bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell return true; 2436bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell } 2437bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell } 2438bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell } 2439bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell 2440bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell return checkV && ViewCompat.canScrollHorizontally(v, -dx); 2441bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell } 2442bc889e39e279fcf8c3d35fc11d8052c002eddf38Adam Powell 2443481243c175651c5de0741ab9390eb10f5b024d98Adam Powell @Override 24442a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn public boolean dispatchKeyEvent(KeyEvent event) { 24452a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn // Let the focused view and/or our descendants get the key first 24462a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn return super.dispatchKeyEvent(event) || executeKeyEvent(event); 24472a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 24482a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn 24492a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn /** 24502a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn * You can call this function yourself to have the scroll view perform 24512a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn * scrolling from a key event, just as if the event had been dispatched to 24522a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn * it by the view hierarchy. 24532a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn * 24542a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn * @param event The key event to execute. 24552a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn * @return Return true if the event was handled, else false. 24562a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn */ 24572a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn public boolean executeKeyEvent(KeyEvent event) { 24582a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn boolean handled = false; 24592a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if (event.getAction() == KeyEvent.ACTION_DOWN) { 24602a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn switch (event.getKeyCode()) { 24612a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn case KeyEvent.KEYCODE_DPAD_LEFT: 24622a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn handled = arrowScroll(FOCUS_LEFT); 24632a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn break; 24642a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn case KeyEvent.KEYCODE_DPAD_RIGHT: 24652a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn handled = arrowScroll(FOCUS_RIGHT); 24662a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn break; 24672a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn case KeyEvent.KEYCODE_TAB: 24685de8804b248eebaf7c29113ec80a0dff3a03c97aAdam Powell if (Build.VERSION.SDK_INT >= 11) { 24695de8804b248eebaf7c29113ec80a0dff3a03c97aAdam Powell // The focus finder had a bug handling FOCUS_FORWARD and FOCUS_BACKWARD 24705de8804b248eebaf7c29113ec80a0dff3a03c97aAdam Powell // before Android 3.0. Ignore the tab key on those devices. 24715de8804b248eebaf7c29113ec80a0dff3a03c97aAdam Powell if (KeyEventCompat.hasNoModifiers(event)) { 24725de8804b248eebaf7c29113ec80a0dff3a03c97aAdam Powell handled = arrowScroll(FOCUS_FORWARD); 24735de8804b248eebaf7c29113ec80a0dff3a03c97aAdam Powell } else if (KeyEventCompat.hasModifiers(event, KeyEvent.META_SHIFT_ON)) { 24745de8804b248eebaf7c29113ec80a0dff3a03c97aAdam Powell handled = arrowScroll(FOCUS_BACKWARD); 24755de8804b248eebaf7c29113ec80a0dff3a03c97aAdam Powell } 24762a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 24772a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn break; 24782a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 24792a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 24802a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn return handled; 24812a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 24822a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn 24832a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn public boolean arrowScroll(int direction) { 24842a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn View currentFocused = findFocus(); 248531dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell if (currentFocused == this) { 248631dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell currentFocused = null; 248731dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell } else if (currentFocused != null) { 248831dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell boolean isChild = false; 248931dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell for (ViewParent parent = currentFocused.getParent(); parent instanceof ViewGroup; 249031dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell parent = parent.getParent()) { 249131dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell if (parent == this) { 249231dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell isChild = true; 249331dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell break; 249431dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell } 249531dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell } 249631dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell if (!isChild) { 249731dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell // This would cause the focus search down below to fail in fun ways. 249831dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell final StringBuilder sb = new StringBuilder(); 249931dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell sb.append(currentFocused.getClass().getSimpleName()); 250031dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell for (ViewParent parent = currentFocused.getParent(); parent instanceof ViewGroup; 250131dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell parent = parent.getParent()) { 250231dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell sb.append(" => ").append(parent.getClass().getSimpleName()); 250331dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell } 250431dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell Log.e(TAG, "arrowScroll tried to find focus based on non-child " + 250531dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell "current focused view " + sb.toString()); 250631dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell currentFocused = null; 250731dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell } 250831dac59d77ff5c1e1ae2c425fa5fc939c6ec15cdAdam Powell } 25092a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn 25102a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn boolean handled = false; 25112a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn 25122a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, 25132a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn direction); 25142a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if (nextFocused != null && nextFocused != currentFocused) { 25152a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if (direction == View.FOCUS_LEFT) { 25162a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn // If there is nothing to the left, or this is causing us to 25172a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn // jump to the right, then what we really want to do is page left. 2518dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell final int nextLeft = getChildRectInPagerCoordinates(mTempRect, nextFocused).left; 2519dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell final int currLeft = getChildRectInPagerCoordinates(mTempRect, currentFocused).left; 2520dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell if (currentFocused != null && nextLeft >= currLeft) { 25212a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn handled = pageLeft(); 25222a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } else { 25232a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn handled = nextFocused.requestFocus(); 25242a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 25252a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } else if (direction == View.FOCUS_RIGHT) { 25262a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn // If there is nothing to the right, or this is causing us to 25272a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn // jump to the left, then what we really want to do is page right. 2528dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell final int nextLeft = getChildRectInPagerCoordinates(mTempRect, nextFocused).left; 2529dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell final int currLeft = getChildRectInPagerCoordinates(mTempRect, currentFocused).left; 2530dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell if (currentFocused != null && nextLeft <= currLeft) { 25312a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn handled = pageRight(); 25322a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } else { 25332a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn handled = nextFocused.requestFocus(); 25342a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 25352a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 25362a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } else if (direction == FOCUS_LEFT || direction == FOCUS_BACKWARD) { 25372a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn // Trying to move left and nothing there; try to page. 25382a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn handled = pageLeft(); 25392a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } else if (direction == FOCUS_RIGHT || direction == FOCUS_FORWARD) { 25402a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn // Trying to move right and nothing there; try to page. 25412a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn handled = pageRight(); 25422a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 25432a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if (handled) { 25442a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction)); 25452a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 25462a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn return handled; 25472a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 25482a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn 2549dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell private Rect getChildRectInPagerCoordinates(Rect outRect, View child) { 2550dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell if (outRect == null) { 2551dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell outRect = new Rect(); 2552dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell } 2553efea2e772645ccd2d0de3e92fa8382d5444eab11Adam Powell if (child == null) { 2554efea2e772645ccd2d0de3e92fa8382d5444eab11Adam Powell outRect.set(0, 0, 0, 0); 2555efea2e772645ccd2d0de3e92fa8382d5444eab11Adam Powell return outRect; 2556efea2e772645ccd2d0de3e92fa8382d5444eab11Adam Powell } 2557dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell outRect.left = child.getLeft(); 2558dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell outRect.right = child.getRight(); 2559dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell outRect.top = child.getTop(); 2560dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell outRect.bottom = child.getBottom(); 2561dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell 2562dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell ViewParent parent = child.getParent(); 2563dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell while (parent instanceof ViewGroup && parent != this) { 2564dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell final ViewGroup group = (ViewGroup) parent; 2565dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell outRect.left += group.getLeft(); 2566dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell outRect.right += group.getRight(); 2567dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell outRect.top += group.getTop(); 2568dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell outRect.bottom += group.getBottom(); 2569dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell 2570dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell parent = group.getParent(); 2571dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell } 2572dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell return outRect; 2573dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell } 2574dd24aab287e08428b20270b9f12921af13fbd72bAdam Powell 25752a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn boolean pageLeft() { 25762a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if (mCurItem > 0) { 25772a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn setCurrentItem(mCurItem-1, true); 25782a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn return true; 25792a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 25802a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn return false; 25812a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 25822a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn 25832a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn boolean pageRight() { 2584218c1e661578e2a17928f7dbb590b43d1c79aeb7Dianne Hackborn if (mAdapter != null && mCurItem < (mAdapter.getCount()-1)) { 25852a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn setCurrentItem(mCurItem+1, true); 25862a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn return true; 25872a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 25882a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn return false; 25892a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 25902a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn 25912a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn /** 25922a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn * We only want the current page that is being shown to be focusable. 25932a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn */ 25942a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn @Override 25952a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn public void addFocusables(ArrayList<View> views, int direction, int focusableMode) { 25962a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn final int focusableCount = views.size(); 25972a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn 25982a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn final int descendantFocusability = getDescendantFocusability(); 25992a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn 26002a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) { 26012a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn for (int i = 0; i < getChildCount(); i++) { 26022a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn final View child = getChildAt(i); 26032a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if (child.getVisibility() == VISIBLE) { 26042a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn ItemInfo ii = infoForChild(child); 26052a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if (ii != null && ii.position == mCurItem) { 26062a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn child.addFocusables(views, direction, focusableMode); 26072a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 26082a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 26092a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 26102a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 26112a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn 26122a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn // we add ourselves (if focusable) in all cases except for when we are 26132a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn // FOCUS_AFTER_DESCENDANTS and there are some descendants focusable. this is 26142a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn // to avoid the focus search finding layouts when a more precise search 26152a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn // among the focusable children would be more interesting. 26162a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if ( 26172a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn descendantFocusability != FOCUS_AFTER_DESCENDANTS || 26182a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn // No focusable descendants 26192a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn (focusableCount == views.size())) { 26202a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn // Note that we can't call the superclass here, because it will 26212a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn // add all views in. So we need to do the same thing View does. 26222a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if (!isFocusable()) { 26232a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn return; 26242a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 26252a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE && 26262a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn isInTouchMode() && !isFocusableInTouchMode()) { 26272a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn return; 26282a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 26292a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if (views != null) { 26302a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn views.add(this); 26312a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 26322a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 26332a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 26342a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn 26352a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn /** 26362a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn * We only want the current page that is being shown to be touchable. 26372a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn */ 26382a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn @Override 26392a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn public void addTouchables(ArrayList<View> views) { 26402a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn // Note that we don't call super.addTouchables(), which means that 26412a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn // we don't call View.addTouchables(). This is okay because a ViewPager 26422a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn // is itself not touchable. 26432a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn for (int i = 0; i < getChildCount(); i++) { 26442a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn final View child = getChildAt(i); 26452a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if (child.getVisibility() == VISIBLE) { 26462a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn ItemInfo ii = infoForChild(child); 26472a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if (ii != null && ii.position == mCurItem) { 26482a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn child.addTouchables(views); 26492a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 26502a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 26512a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 26522a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 26532a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn 26542a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn /** 26552a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn * We only want the current page that is being shown to be focusable. 26562a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn */ 26572a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn @Override 26582a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn protected boolean onRequestFocusInDescendants(int direction, 26592a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn Rect previouslyFocusedRect) { 26602a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn int index; 26612a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn int increment; 26622a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn int end; 26632a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn int count = getChildCount(); 26642a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if ((direction & FOCUS_FORWARD) != 0) { 26652a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn index = 0; 26662a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn increment = 1; 26672a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn end = count; 26682a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } else { 26692a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn index = count - 1; 26702a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn increment = -1; 26712a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn end = -1; 26722a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 26732a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn for (int i = index; i != end; i += increment) { 26742a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn View child = getChildAt(i); 26752a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if (child.getVisibility() == VISIBLE) { 26762a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn ItemInfo ii = infoForChild(child); 26772a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if (ii != null && ii.position == mCurItem) { 26782a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn if (child.requestFocus(direction, previouslyFocusedRect)) { 26792a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn return true; 26802a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 26812a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 26822a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn } 2683481243c175651c5de0741ab9390eb10f5b024d98Adam Powell } 26842a4d8518f36346ea25a22a736453ff28f2954165Dianne Hackborn return false; 2685481243c175651c5de0741ab9390eb10f5b024d98Adam Powell } 2686481243c175651c5de0741ab9390eb10f5b024d98Adam Powell 2687481243c175651c5de0741ab9390eb10f5b024d98Adam Powell @Override 2688481243c175651c5de0741ab9390eb10f5b024d98Adam Powell public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 2689481243c175651c5de0741ab9390eb10f5b024d98Adam Powell // ViewPagers should only report accessibility info for the current page, 2690481243c175651c5de0741ab9390eb10f5b024d98Adam Powell // otherwise things get very confusing. 2691481243c175651c5de0741ab9390eb10f5b024d98Adam Powell 2692481243c175651c5de0741ab9390eb10f5b024d98Adam Powell // TODO: Should this note something about the paging container? 2693481243c175651c5de0741ab9390eb10f5b024d98Adam Powell 2694481243c175651c5de0741ab9390eb10f5b024d98Adam Powell final int childCount = getChildCount(); 2695481243c175651c5de0741ab9390eb10f5b024d98Adam Powell for (int i = 0; i < childCount; i++) { 2696481243c175651c5de0741ab9390eb10f5b024d98Adam Powell final View child = getChildAt(i); 2697481243c175651c5de0741ab9390eb10f5b024d98Adam Powell if (child.getVisibility() == VISIBLE) { 2698481243c175651c5de0741ab9390eb10f5b024d98Adam Powell final ItemInfo ii = infoForChild(child); 2699481243c175651c5de0741ab9390eb10f5b024d98Adam Powell if (ii != null && ii.position == mCurItem && 2700481243c175651c5de0741ab9390eb10f5b024d98Adam Powell child.dispatchPopulateAccessibilityEvent(event)) { 2701481243c175651c5de0741ab9390eb10f5b024d98Adam Powell return true; 2702481243c175651c5de0741ab9390eb10f5b024d98Adam Powell } 2703481243c175651c5de0741ab9390eb10f5b024d98Adam Powell } 2704481243c175651c5de0741ab9390eb10f5b024d98Adam Powell } 2705481243c175651c5de0741ab9390eb10f5b024d98Adam Powell 2706481243c175651c5de0741ab9390eb10f5b024d98Adam Powell return false; 2707481243c175651c5de0741ab9390eb10f5b024d98Adam Powell } 2708481243c175651c5de0741ab9390eb10f5b024d98Adam Powell 27098fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell @Override 27108fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell protected ViewGroup.LayoutParams generateDefaultLayoutParams() { 27118fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell return new LayoutParams(); 27128fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 27138fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 27148fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell @Override 27158fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 27168fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell return generateDefaultLayoutParams(); 27178fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 27188fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 27198fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell @Override 27208fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 27218fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell return p instanceof LayoutParams && super.checkLayoutParams(p); 27228fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 27238fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 27248fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell @Override 27258fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { 27261ccb8bcb79557d861de7f271c13e2fd8e54e012aAdam Powell return new LayoutParams(getContext(), attrs); 27278fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 27288fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 272925121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov class MyAccessibilityDelegate extends AccessibilityDelegateCompat { 273025121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov 273125121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov @Override 273225121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { 273325121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov super.onInitializeAccessibilityEvent(host, event); 273425121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov event.setClassName(ViewPager.class.getName()); 273525121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov } 273625121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov 273725121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov @Override 273825121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { 273925121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov super.onInitializeAccessibilityNodeInfo(host, info); 274025121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov info.setClassName(ViewPager.class.getName()); 274125121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov info.setScrollable(mAdapter != null && mAdapter.getCount() > 1); 274225121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov if (mAdapter != null && mCurItem >= 0 && mCurItem < mAdapter.getCount() - 1) { 274325121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov info.addAction(AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD); 274425121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov } 274525121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov if (mAdapter != null && mCurItem > 0 && mCurItem < mAdapter.getCount()) { 274625121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov info.addAction(AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD); 274725121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov } 274825121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov } 274925121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov 275025121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov @Override 275125121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov public boolean performAccessibilityAction(View host, int action, Bundle args) { 275225121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov if (super.performAccessibilityAction(host, action, args)) { 275325121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov return true; 275425121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov } 275525121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov switch (action) { 275625121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov case AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD: { 275725121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov if (mAdapter != null && mCurItem >= 0 && mCurItem < mAdapter.getCount() - 1) { 275825121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov setCurrentItem(mCurItem + 1); 275925121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov return true; 276025121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov } 276125121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov } return false; 276225121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov case AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD: { 276325121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov if (mAdapter != null && mCurItem > 0 && mCurItem < mAdapter.getCount()) { 276425121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov setCurrentItem(mCurItem - 1); 276525121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov return true; 276625121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov } 276725121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov } return false; 276825121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov } 276925121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov return false; 277025121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov } 277125121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov } 277225121559b53b9f6c7ef7159203d42e11b9aee281Svetoslav Ganov 27738fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private class PagerObserver extends DataSetObserver { 27748fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell @Override 27758fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell public void onChanged() { 27768fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell dataSetChanged(); 27778fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 27783661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell @Override 27798fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell public void onInvalidated() { 27803661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell dataSetChanged(); 27813661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 27823661ad6c9143d58f741568f940f77ca9d38dec47Adam Powell } 27838fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 27847dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn /** 27857dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * Layout parameters that should be supplied for views added to a 27867dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * ViewPager. 27877dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn */ 27888fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell public static class LayoutParams extends ViewGroup.LayoutParams { 27898fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell /** 27908fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * true if this view is a decoration on the pager itself and not 27918fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * a view supplied by the adapter. 27928fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell */ 27938fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell public boolean isDecor; 27948fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 2795a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell /** 27963d9e557a9a9152db585264987d64f81fa86c73b5Dianne Hackborn * Gravity setting for use on decor views only: 27977dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * Where to position the view page within the overall ViewPager 27987dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * container; constants are defined in {@link android.view.Gravity}. 2799a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell */ 28008fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell public int gravity; 28018fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 2802a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell /** 2803a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * Width as a 0-1 multiplier of the measured pager width 2804a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell */ 28057e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell float widthFactor = 0.f; 2806a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 2807a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell /** 2808a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * true if this view was added during layout and needs to be measured 2809a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * before being positioned. 2810a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell */ 28117e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell boolean needsMeasure; 28127e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell 28137e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell /** 28147e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell * Adapter position this view is for if !isDecor 28157e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell */ 28167e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell int position; 28177e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell 28187e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell /** 28197e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell * Current child index within the ViewPager that this view occupies 28207e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell */ 28217e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell int childIndex; 2822a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 28238fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell public LayoutParams() { 28248fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell super(FILL_PARENT, FILL_PARENT); 28258fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 28268fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 28278fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell public LayoutParams(Context context, AttributeSet attrs) { 28288fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell super(context, attrs); 28298fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 28308fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS); 2831a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell gravity = a.getInteger(0, Gravity.TOP); 28328fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell a.recycle(); 28338fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 28348fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 28357e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell 28367e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell static class ViewPositionComparator implements Comparator<View> { 28377e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell @Override 28387e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell public int compare(View lhs, View rhs) { 28397e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell final LayoutParams llp = (LayoutParams) lhs.getLayoutParams(); 28407e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell final LayoutParams rlp = (LayoutParams) rhs.getLayoutParams(); 28417e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell if (llp.isDecor != rlp.isDecor) { 28427e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell return llp.isDecor ? 1 : -1; 28437e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell } 28447e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell return llp.position - rlp.position; 28457e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell } 28467e464c3f9ff67d08c61f1c7a57dee0532c3c9449Adam Powell } 2847d59dd1decc75fb41e19928c21b90d25e3eda2559Dianne Hackborn} 2848