DirectionalViewPager支持横向和纵向的ViewPager

来源:互联网 发布:期货对冲交易 知乎 编辑:程序博客网 时间:2024/06/07 11:16

DirectionalViewPager支持横向和纵向的ViewPager

    博客分类: 
  • android进阶
android 
项目地址: 
https://github.com/JakeWharton/Android-DirectionalViewPager 

这个别人已经试过了: 

Android之仿网易V3.5新特性http://blog.csdn.net/way_ping_li/article/details/9359191 

我只是重新测试了一下,感觉可以用。 
只是要注意,需要导入-v4.jar包,并且VerticalViewPagerCompat.java一定要放在android.support.v4.view包中,具体见附件。 

用法同ViewPager几乎一样,只要设定 
viewPager.setOrientation(com.mobovip.views.DirectionalViewPager.VERTICAL); 
就可以纵向滑动了。 
参考代码如下: 
Java代码  收藏代码
  1. viewPager=(com.mobovip.views.DirectionalViewPager)findViewById(R.id.viewPager);  
  2.         viewPager.setAdapter(new MyPagerAdapter(listViews));  
  3.         viewPager.setOrientation(com.mobovip.views.DirectionalViewPager.VERTICAL);  
  4.         viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {  
  5.               
  6.             @Override  
  7.             public void onPageSelected(int position) {  
  8.                 // TODO Auto-generated method stub  
  9.                 btn.setVisibility(position==listViews.size()-1?View.VISIBLE:View.GONE);  
  10.             }  
  11.               
  12.             @Override  
  13.             public void onPageScrolled(int arg0, float arg1, int arg2) {  
  14.                 // TODO Auto-generated method stub  
  15.                   
  16.             }  
  17.               
  18.             @Override  
  19.             public void onPageScrollStateChanged(int arg0) {  
  20.                 // TODO Auto-generated method stub  
  21.                   
  22.             }  
  23.         });  


 

Java代码  收藏代码
  1. package android.support.v4.view;  
  2.   
  3. import android.support.v4.view.PagerAdapter;  
  4.   
  5. public final class VerticalViewPagerCompat {  
  6.     private VerticalViewPagerCompat() {  
  7.     }  
  8.   
  9.     public interface DataSetObserver extends PagerAdapter.DataSetObserver {  
  10.     }  
  11.   
  12.     public static void setDataSetObserver(PagerAdapter adapter,  
  13.             DataSetObserver observer) {  
  14.         adapter.setDataSetObserver(observer);  
  15.     }  
  16. }  


Java代码  收藏代码
  1. package com.mobovip.views;  
  2.   
  3. import java.util.ArrayList;  
  4. import android.content.Context;  
  5. import android.os.Build;  
  6. import android.os.Parcel;  
  7. import android.os.Parcelable;  
  8. import android.support.v4.os.ParcelableCompat;  
  9. import android.support.v4.os.ParcelableCompatCreatorCallbacks;  
  10. import android.support.v4.view.MotionEventCompat;  
  11. import android.support.v4.view.PagerAdapter;  
  12. import android.support.v4.view.VelocityTrackerCompat;  
  13. import android.support.v4.view.VerticalViewPagerCompat;  
  14. import android.support.v4.view.ViewConfigurationCompat;  
  15. import android.support.v4.view.ViewPager;  
  16. import android.util.AttributeSet;  
  17. import android.util.Log;  
  18. import android.view.MotionEvent;  
  19. import android.view.VelocityTracker;  
  20. import android.view.View;  
  21. import android.view.ViewConfiguration;  
  22. import android.view.ViewGroup;  
  23. import android.widget.Scroller;  
  24.   
  25. /** 
  26.  * Layout manager that allows the user to flip horizontally or vertically 
  27.  * through pages of data. You supply an implementation of a {@link PagerAdapter} 
  28.  * to generate the pages that the view shows. 
  29.  *  
  30.  * <p> 
  31.  * Note this class is currently under early design and development. The API will 
  32.  * likely change in later updates of the compatibility library, requiring 
  33.  * changes to the source code of apps when they are compiled against the newer 
  34.  * version. 
  35.  * </p> 
  36.  */  
  37. public class DirectionalViewPager extends ViewPager {  
  38.     private static final String TAG = "DirectionalViewPager";  
  39.     private static final String XML_NS = "http://schemas.android.com/apk/res/android";  
  40.     private static final boolean DEBUG = false;  
  41.   
  42.     private static final boolean USE_CACHE = false;  
  43.   
  44.     public static final int HORIZONTAL = 0;  
  45.     public static final int VERTICAL = 1;  
  46.   
  47.     static class ItemInfo {  
  48.         Object object;  
  49.         int position;  
  50.         boolean scrolling;  
  51.     }  
  52.   
  53.     private final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>();  
  54.   
  55.     private PagerAdapter mAdapter;  
  56.     private int mCurItem; // Index of currently displayed page.  
  57.     private int mRestoredCurItem = -1;  
  58.     private Parcelable mRestoredAdapterState = null;  
  59.     private ClassLoader mRestoredClassLoader = null;  
  60.     private Scroller mScroller;  
  61.     private VerticalViewPagerCompat.DataSetObserver mObserver;  
  62.   
  63.     private int mChildWidthMeasureSpec;  
  64.     private int mChildHeightMeasureSpec;  
  65.     private boolean mInLayout;  
  66.   
  67.     private boolean mScrollingCacheEnabled;  
  68.   
  69.     private boolean mPopulatePending;  
  70.     private boolean mScrolling;  
  71.   
  72.     private boolean mIsBeingDragged;  
  73.     private boolean mIsUnableToDrag;  
  74.     private int mTouchSlop;  
  75.     private float mInitialMotion;  
  76.     /** 
  77.      * Position of the last motion event. 
  78.      */  
  79.     private float mLastMotionX;  
  80.     private float mLastMotionY;  
  81.     private int mOrientation = HORIZONTAL;  
  82.     /** 
  83.      * ID of the active pointer. This is used to retain consistency during 
  84.      * drags/flings if multiple pointers are used. 
  85.      */  
  86.     private int mActivePointerId = INVALID_POINTER;  
  87.     /** 
  88.      * Sentinel value for no current active pointer. Used by 
  89.      * {@link #mActivePointerId}. 
  90.      */  
  91.     private static final int INVALID_POINTER = -1;  
  92.   
  93.     /** 
  94.      * Determines speed during touch scrolling 
  95.      */  
  96.     private VelocityTracker mVelocityTracker;  
  97.     private int mMinimumVelocity;  
  98.     private int mMaximumVelocity;  
  99.   
  100.     private OnPageChangeListener mOnPageChangeListener;  
  101.   
  102.     private int mScrollState = SCROLL_STATE_IDLE;  
  103.   
  104.     public DirectionalViewPager(Context context) {  
  105.         super(context);  
  106.         initViewPager();  
  107.     }  
  108.   
  109.     public DirectionalViewPager(Context context, AttributeSet attrs) {  
  110.         super(context, attrs);  
  111.         initViewPager();  
  112.   
  113.         // We default to horizontal, only change if a value is explicitly  
  114.         // specified  
  115.         int orientation = attrs.getAttributeIntValue(XML_NS, "orientation", -1);  
  116.         if (orientation != -1) {  
  117.             setOrientation(orientation);  
  118.         }  
  119.     }  
  120.   
  121.     void initViewPager() {  
  122.         setWillNotDraw(false);  
  123.         mScroller = new Scroller(getContext());  
  124.         final ViewConfiguration configuration = ViewConfiguration  
  125.                 .get(getContext());  
  126.         mTouchSlop = ViewConfigurationCompat  
  127.                 .getScaledPagingTouchSlop(configuration);  
  128.         mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();  
  129.         mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();  
  130.     }  
  131.   
  132.     private void setScrollState(int newState) {  
  133.         if (mScrollState == newState) {  
  134.             return;  
  135.         }  
  136.   
  137.         mScrollState = newState;  
  138.         if (mOnPageChangeListener != null) {  
  139.             mOnPageChangeListener.onPageScrollStateChanged(newState);  
  140.         }  
  141.     }  
  142.   
  143.     public void setAdapter(PagerAdapter adapter) {  
  144.         if (mAdapter != null) {  
  145.             VerticalViewPagerCompat.setDataSetObserver(mAdapter, null);  
  146.         }  
  147.   
  148.         mAdapter = adapter;  
  149.   
  150.         if (mAdapter != null) {  
  151.             if (mObserver == null) {  
  152.                 mObserver = new DataSetObserver();  
  153.             }  
  154.             VerticalViewPagerCompat.setDataSetObserver(mAdapter, mObserver);  
  155.             mPopulatePending = false;  
  156.             if (mRestoredCurItem >= 0) {  
  157.                 mAdapter.restoreState(mRestoredAdapterState,  
  158.                         mRestoredClassLoader);  
  159.                 setCurrentItemInternal(mRestoredCurItem, falsetrue);  
  160.                 mRestoredCurItem = -1;  
  161.                 mRestoredAdapterState = null;  
  162.                 mRestoredClassLoader = null;  
  163.             } else {  
  164.                 populate();  
  165.             }  
  166.         }  
  167.     }  
  168.   
  169.     public PagerAdapter getAdapter() {  
  170.         return mAdapter;  
  171.     }  
  172.   
  173.     public void setCurrentItem(int item) {  
  174.         mPopulatePending = false;  
  175.         setCurrentItemInternal(item, truefalse);  
  176.     }  
  177.   
  178.     void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) {  
  179.         if (mAdapter == null || mAdapter.getCount() <= 0) {  
  180.             setScrollingCacheEnabled(false);  
  181.             return;  
  182.         }  
  183.         if (!always && mCurItem == item && mItems.size() != 0) {  
  184.             setScrollingCacheEnabled(false);  
  185.             return;  
  186.         }  
  187.         if (item < 0) {  
  188.             item = 0;  
  189.         } else if (item >= mAdapter.getCount()) {  
  190.             item = mAdapter.getCount() - 1;  
  191.         }  
  192.         if (item > (mCurItem + 1) || item < (mCurItem - 1)) {  
  193.             // We are doing a jump by more than one page. To avoid  
  194.             // glitches, we want to keep all current pages in the view  
  195.             // until the scroll ends.  
  196.             for (int i = 0; i < mItems.size(); i++) {  
  197.                 mItems.get(i).scrolling = true;  
  198.             }  
  199.         }  
  200.         final boolean dispatchSelected = mCurItem != item;  
  201.         mCurItem = item;  
  202.         populate();  
  203.         if (smoothScroll) {  
  204.             if (mOrientation == HORIZONTAL) {  
  205.                 smoothScrollTo(getWidth() * item, 0);  
  206.             } else {  
  207.                 smoothScrollTo(0, getHeight() * item);  
  208.             }  
  209.             if (dispatchSelected && mOnPageChangeListener != null) {  
  210.                 mOnPageChangeListener.onPageSelected(item);  
  211.             }  
  212.         } else {  
  213.             if (dispatchSelected && mOnPageChangeListener != null) {  
  214.                 mOnPageChangeListener.onPageSelected(item);  
  215.             }  
  216.             completeScroll();  
  217.             if (mOrientation == HORIZONTAL) {  
  218.                 scrollTo(getWidth() * item, 0);  
  219.             } else {  
  220.                 scrollTo(0, getHeight() * item);  
  221.             }  
  222.         }  
  223.     }  
  224.   
  225.     public void setOnPageChangeListener(OnPageChangeListener listener) {  
  226.         mOnPageChangeListener = listener;  
  227.     }  
  228.   
  229.     /** 
  230.      * Like {@link View#scrollBy}, but scroll smoothly instead of immediately. 
  231.      *  
  232.      * @param dx 
  233.      *            the number of pixels to scroll by on the X axis 
  234.      * @param dy 
  235.      *            the number of pixels to scroll by on the Y axis 
  236.      */  
  237.     void smoothScrollTo(int x, int y) {  
  238.         if (getChildCount() == 0) {  
  239.             // Nothing to do.  
  240.             setScrollingCacheEnabled(false);  
  241.             return;  
  242.         }  
  243.         int sx = getScrollX();  
  244.         int sy = getScrollY();  
  245.         int dx = x - sx;  
  246.         int dy = y - sy;  
  247.         if (dx == 0 && dy == 0) {  
  248.             completeScroll();  
  249.             return;  
  250.         }  
  251.   
  252.         setScrollingCacheEnabled(true);  
  253.         mScrolling = true;  
  254.         setScrollState(SCROLL_STATE_SETTLING);  
  255.         mScroller.startScroll(sx, sy, dx, dy);  
  256.         invalidate();  
  257.     }  
  258.   
  259.     void addNewItem(int position, int index) {  
  260.         ItemInfo ii = new ItemInfo();  
  261.         ii.position = position;  
  262.         ii.object = mAdapter.instantiateItem(this, position);  
  263.         if (index < 0) {  
  264.             mItems.add(ii);  
  265.         } else {  
  266.             mItems.add(index, ii);  
  267.         }  
  268.     }  
  269.   
  270.     void dataSetChanged() {  
  271.         // This method only gets called if our observer is attached, so mAdapter  
  272.         // is non-null.  
  273.   
  274.         boolean needPopulate = mItems.isEmpty() && mAdapter.getCount() > 0;  
  275.         int newCurrItem = -1;  
  276.   
  277.         for (int i = 0; i < mItems.size(); i++) {  
  278.             final ItemInfo ii = mItems.get(i);  
  279.             final int newPos = mAdapter.getItemPosition(ii.object);  
  280.   
  281.             if (newPos == PagerAdapter.POSITION_UNCHANGED) {  
  282.                 continue;  
  283.             }  
  284.   
  285.             if (newPos == PagerAdapter.POSITION_NONE) {  
  286.                 mItems.remove(i);  
  287.                 i--;  
  288.                 mAdapter.destroyItem(this, ii.position, ii.object);  
  289.                 needPopulate = true;  
  290.   
  291.                 if (mCurItem == ii.position) {  
  292.                     // Keep the current item in the valid range  
  293.                     newCurrItem = Math.max(0,  
  294.                             Math.min(mCurItem, mAdapter.getCount() - 1));  
  295.                 }  
  296.                 continue;  
  297.             }  
  298.   
  299.             if (ii.position != newPos) {  
  300.                 if (ii.position == mCurItem) {  
  301.                     // Our current item changed position. Follow it.  
  302.                     newCurrItem = newPos;  
  303.                 }  
  304.   
  305.                 ii.position = newPos;  
  306.                 needPopulate = true;  
  307.             }  
  308.         }  
  309.   
  310.         if (newCurrItem >= 0) {  
  311.             // TODO This currently causes a jump.  
  312.             setCurrentItemInternal(newCurrItem, falsetrue);  
  313.             needPopulate = true;  
  314.         }  
  315.         if (needPopulate) {  
  316.             populate();  
  317.             requestLayout();  
  318.         }  
  319.     }  
  320.   
  321.     void populate() {  
  322.         if (mAdapter == null) {  
  323.             return;  
  324.         }  
  325.   
  326.         // Bail now if we are waiting to populate. This is to hold off  
  327.         // on creating views from the time the user releases their finger to  
  328.         // fling to a new position until we have finished the scroll to  
  329.         // that position, avoiding glitches from happening at that point.  
  330.         if (mPopulatePending) {  
  331.             if (DEBUG)  
  332.                 Log.i(TAG, "populate is pending, skipping for now...");  
  333.             return;  
  334.         }  
  335.   
  336.         // Also, don't populate until we are attached to a window. This is to  
  337.         // avoid trying to populate before we have restored our view hierarchy  
  338.         // state and conflicting with what is restored.  
  339.         if (getWindowToken() == null) {  
  340.             return;  
  341.         }  
  342.   
  343.         mAdapter.startUpdate(this);  
  344.   
  345.         final int startPos = mCurItem > 0 ? mCurItem - 1 : mCurItem;  
  346.         final int count = mAdapter.getCount();  
  347.         final int endPos = mCurItem < (count - 1) ? mCurItem + 1 : count - 1;  
  348.   
  349.         if (DEBUG)  
  350.             Log.v(TAG, "populating: startPos=" + startPos + " endPos=" + endPos);  
  351.   
  352.         // Add and remove pages in the existing list.  
  353.         int lastPos = -1;  
  354.         for (int i = 0; i < mItems.size(); i++) {  
  355.             ItemInfo ii = mItems.get(i);  
  356.             if ((ii.position < startPos || ii.position > endPos)  
  357.                     && !ii.scrolling) {  
  358.                 if (DEBUG)  
  359.                     Log.i(TAG, "removing: " + ii.position + " @ " + i);  
  360.                 mItems.remove(i);  
  361.                 i--;  
  362.                 mAdapter.destroyItem(this, ii.position, ii.object);  
  363.             } else if (lastPos < endPos && ii.position > startPos) {  
  364.                 // The next item is outside of our range, but we have a gap  
  365.                 // between it and the last item where we want to have a page  
  366.                 // shown. Fill in the gap.  
  367.                 lastPos++;  
  368.                 if (lastPos < startPos) {  
  369.                     lastPos = startPos;  
  370.                 }  
  371.                 while (lastPos <= endPos && lastPos < ii.position) {  
  372.                     if (DEBUG)  
  373.                         Log.i(TAG, "inserting: " + lastPos + " @ " + i);  
  374.                     addNewItem(lastPos, i);  
  375.                     lastPos++;  
  376.                     i++;  
  377.                 }  
  378.             }  
  379.             lastPos = ii.position;  
  380.         }  
  381.   
  382.         // Add any new pages we need at the end.  
  383.         lastPos = mItems.size() > 0 ? mItems.get(mItems.size() - 1).position  
  384.                 : -1;  
  385.         if (lastPos < endPos) {  
  386.             lastPos++;  
  387.             lastPos = lastPos > startPos ? lastPos : startPos;  
  388.             while (lastPos <= endPos) {  
  389.                 if (DEBUG)  
  390.                     Log.i(TAG, "appending: " + lastPos);  
  391.                 addNewItem(lastPos, -1);  
  392.                 lastPos++;  
  393.             }  
  394.         }  
  395.   
  396.         if (DEBUG) {  
  397.             Log.i(TAG, "Current page list:");  
  398.             for (int i = 0; i < mItems.size(); i++) {  
  399.                 Log.i(TAG, "#" + i + ": page " + mItems.get(i).position);  
  400.             }  
  401.         }  
  402.   
  403.         mAdapter.finishUpdate(this);  
  404.     }  
  405.   
  406.     public static class SavedState extends BaseSavedState {  
  407.         int position;  
  408.         Parcelable adapterState;  
  409.         ClassLoader loader;  
  410.   
  411.         public SavedState(Parcelable superState) {  
  412.             super(superState);  
  413.         }  
  414.   
  415.         @Override  
  416.         public void writeToParcel(Parcel out, int flags) {  
  417.             super.writeToParcel(out, flags);  
  418.             out.writeInt(position);  
  419.             out.writeParcelable(adapterState, flags);  
  420.         }  
  421.   
  422.         @Override  
  423.         public String toString() {  
  424.             return "FragmentPager.SavedState{"  
  425.                     + Integer.toHexString(System.identityHashCode(this))  
  426.                     + " position=" + position + "}";  
  427.         }  
  428.   
  429.         public static final Parcelable.Creator<SavedState> CREATOR = ParcelableCompat  
  430.                 .newCreator(new ParcelableCompatCreatorCallbacks<SavedState>() {  
  431.                     @Override  
  432.                     public SavedState createFromParcel(Parcel in,  
  433.                             ClassLoader loader) {  
  434.                         return new SavedState(in, loader);  
  435.                     }  
  436.   
  437.                     @Override  
  438.                     public SavedState[] newArray(int size) {  
  439.                         return new SavedState[size];  
  440.                     }  
  441.                 });  
  442.   
  443.         SavedState(Parcel in, ClassLoader loader) {  
  444.             super(in);  
  445.             if (loader == null) {  
  446.                 loader = getClass().getClassLoader();  
  447.             }  
  448.             position = in.readInt();  
  449.             adapterState = in.readParcelable(loader);  
  450.             this.loader = loader;  
  451.         }  
  452.     }  
  453.   
  454.     @Override  
  455.     public Parcelable onSaveInstanceState() {  
  456.         Parcelable superState = super.onSaveInstanceState();  
  457.         SavedState ss = new SavedState(superState);  
  458.         ss.position = mCurItem;  
  459.         ss.adapterState = mAdapter.saveState();  
  460.         return ss;  
  461.     }  
  462.   
  463.     @Override  
  464.     public void onRestoreInstanceState(Parcelable state) {  
  465.         if (!(state instanceof SavedState)) {  
  466.             super.onRestoreInstanceState(state);  
  467.             return;  
  468.         }  
  469.   
  470.         SavedState ss = (SavedState) state;  
  471.         super.onRestoreInstanceState(ss.getSuperState());  
  472.   
  473.         if (mAdapter != null) {  
  474.             mAdapter.restoreState(ss.adapterState, ss.loader);  
  475.             setCurrentItemInternal(ss.position, falsetrue);  
  476.         } else {  
  477.             mRestoredCurItem = ss.position;  
  478.             mRestoredAdapterState = ss.adapterState;  
  479.             mRestoredClassLoader = ss.loader;  
  480.         }  
  481.     }  
  482.   
  483.     public int getOrientation() {  
  484.         return mOrientation;  
  485.     }  
  486.   
  487.     public void setOrientation(int orientation) {  
  488.         switch (orientation) {  
  489.         case HORIZONTAL:  
  490.         case VERTICAL:  
  491.             break;  
  492.   
  493.         default:  
  494.             throw new IllegalArgumentException(  
  495.                     "Only HORIZONTAL and VERTICAL are valid orientations.");  
  496.         }  
  497.   
  498.         if (orientation == mOrientation) {  
  499.             return;  
  500.         }  
  501.   
  502.         // Complete any scroll we are currently in the middle of  
  503.         completeScroll();  
  504.   
  505.         // Reset values  
  506.         mInitialMotion = 0;  
  507.         mLastMotionX = 0;  
  508.         mLastMotionY = 0;  
  509.         if (mVelocityTracker != null) {  
  510.             mVelocityTracker.clear();  
  511.         }  
  512.   
  513.         // Adjust scroll for new orientation  
  514.         mOrientation = orientation;  
  515.         if (mOrientation == HORIZONTAL) {  
  516.             scrollTo(mCurItem * getWidth(), 0);  
  517.         } else {  
  518.             scrollTo(0, mCurItem * getHeight());  
  519.         }  
  520.         requestLayout();  
  521.     }  
  522.   
  523.     @Override  
  524.     public void addView(View child, int index, ViewGroup.LayoutParams params) {  
  525.         if (mInLayout) {  
  526.             addViewInLayout(child, index, params);  
  527.             child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec);  
  528.         } else {  
  529.             super.addView(child, index, params);  
  530.         }  
  531.   
  532.         if (USE_CACHE) {  
  533.             if (child.getVisibility() != GONE) {  
  534.                 child.setDrawingCacheEnabled(mScrollingCacheEnabled);  
  535.             } else {  
  536.                 child.setDrawingCacheEnabled(false);  
  537.             }  
  538.         }  
  539.     }  
  540.   
  541.     ItemInfo infoForChild(View child) {  
  542.         for (int i = 0; i < mItems.size(); i++) {  
  543.             ItemInfo ii = mItems.get(i);  
  544.             if (mAdapter.isViewFromObject(child, ii.object)) {  
  545.                 return ii;  
  546.             }  
  547.         }  
  548.         return null;  
  549.     }  
  550.   
  551.     @Override  
  552.     protected void onAttachedToWindow() {  
  553.         super.onAttachedToWindow();  
  554.         if (mAdapter != null) {  
  555.             populate();  
  556.         }  
  557.     }  
  558.   
  559.     @Override  
  560.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  561.         // For simple implementation, or internal size is always 0.  
  562.         // We depend on the container to specify the layout size of  
  563.         // our view. We can't really know what it is since we will be  
  564.         // adding and removing different arbitrary views and do not  
  565.         // want the layout to change as this happens.  
  566.         setMeasuredDimension(getDefaultSize(0, widthMeasureSpec),  
  567.                 getDefaultSize(0, heightMeasureSpec));  
  568.   
  569.         // Children are just made to fill our space.  
  570.         mChildWidthMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth()  
  571.                 - getPaddingLeft() - getPaddingRight(), MeasureSpec.EXACTLY);  
  572.         mChildHeightMeasureSpec = MeasureSpec.makeMeasureSpec(  
  573.                 getMeasuredHeight() - getPaddingTop() - getPaddingBottom(),  
  574.                 MeasureSpec.EXACTLY);  
  575.   
  576.         // Make sure we have created all fragments that we need to have shown.  
  577.         mInLayout = true;  
  578.         populate();  
  579.         mInLayout = false;  
  580.   
  581.         // Make sure all children have been properly measured.  
  582.         final int size = getChildCount();  
  583.         for (int i = 0; i < size; ++i) {  
  584.             final View child = getChildAt(i);  
  585.             if (child.getVisibility() != GONE) {  
  586.                 if (DEBUG)  
  587.                     Log.v(TAG, "Measuring #" + i + " " + child + ": "  
  588.                             + mChildWidthMeasureSpec + " x "  
  589.                             + mChildHeightMeasureSpec);  
  590.                 child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec);  
  591.             }  
  592.         }  
  593.     }  
  594.   
  595.     @Override  
  596.     protected void onSizeChanged(int w, int h, int oldw, int oldh) {  
  597.         super.onSizeChanged(w, h, oldw, oldh);  
  598.   
  599.         // Make sure scroll position is set correctly.  
  600.         if (mOrientation == HORIZONTAL) {  
  601.             int scrollPos = mCurItem * w;  
  602.             if (scrollPos != getScrollX()) {  
  603.                 completeScroll();  
  604.                 scrollTo(scrollPos, getScrollY());  
  605.             }  
  606.         } else {  
  607.             int scrollPos = mCurItem * h;  
  608.             if (scrollPos != getScrollY()) {  
  609.                 completeScroll();  
  610.                 scrollTo(getScrollX(), scrollPos);  
  611.             }  
  612.         }  
  613.     }  
  614.   
  615.     @Override  
  616.     protected void onLayout(boolean changed, int l, int t, int r, int b) {  
  617.         mInLayout = true;  
  618.         populate();  
  619.         mInLayout = false;  
  620.   
  621.         final int count = getChildCount();  
  622.         final int size = (mOrientation == HORIZONTAL) ? r - l : b - t;  
  623.   
  624.         for (int i = 0; i < count; i++) {  
  625.             View child = getChildAt(i);  
  626.             ItemInfo ii;  
  627.             if (child.getVisibility() != GONE  
  628.                     && (ii = infoForChild(child)) != null) {  
  629.                 int off = size * ii.position;  
  630.                 int childLeft = getPaddingLeft();  
  631.                 int childTop = getPaddingTop();  
  632.                 if (mOrientation == HORIZONTAL) {  
  633.                     childLeft += off;  
  634.                 } else {  
  635.                     childTop += off;  
  636.                 }  
  637.                 if (DEBUG)  
  638.                     Log.v(TAG,  
  639.                             "Positioning #" + i + " " + child + " f="  
  640.                                     + ii.object + ":" + childLeft + ","  
  641.                                     + childTop + " " + child.getMeasuredWidth()  
  642.                                     + "x" + child.getMeasuredHeight());  
  643.                 child.layout(childLeft, childTop,  
  644.                         childLeft + child.getMeasuredWidth(),  
  645.                         childTop + child.getMeasuredHeight());  
  646.             }  
  647.         }  
  648.     }  
  649.   
  650.     @Override  
  651.     public void computeScroll() {  
  652.         if (DEBUG)  
  653.             Log.i(TAG, "computeScroll: finished=" + mScroller.isFinished());  
  654.         if (!mScroller.isFinished()) {  
  655.             if (mScroller.computeScrollOffset()) {  
  656.                 if (DEBUG)  
  657.                     Log.i(TAG, "computeScroll: still scrolling");  
  658.                 int oldX = getScrollX();  
  659.                 int oldY = getScrollY();  
  660.                 int x = mScroller.getCurrX();  
  661.                 int y = mScroller.getCurrY();  
  662.   
  663.                 if (oldX != x || oldY != y) {  
  664.                     scrollTo(x, y);  
  665.                 }  
  666.   
  667.                 if (mOnPageChangeListener != null) {  
  668.                     int size;  
  669.                     int value;  
  670.                     if (mOrientation == HORIZONTAL) {  
  671.                         size = getWidth();  
  672.                         value = x;  
  673.                     } else {  
  674.                         size = getHeight();  
  675.                         value = y;  
  676.                     }  
  677.   
  678.                     final int position = value / size;  
  679.                     final int offsetPixels = value % size;  
  680.                     final float offset = (float) offsetPixels / size;  
  681.                     mOnPageChangeListener.onPageScrolled(position, offset,  
  682.                             offsetPixels);  
  683.                 }  
  684.   
  685.                 // Keep on drawing until the animation has finished.  
  686.                 invalidate();  
  687.                 return;  
  688.             }  
  689.         }  
  690.   
  691.         // Done with scroll, clean up state.  
  692.         completeScroll();  
  693.     }  
  694.   
  695.     private void completeScroll() {  
  696.         boolean needPopulate;  
  697.         if ((needPopulate = mScrolling)) {  
  698.             // Done with scroll, no longer want to cache view drawing.  
  699.             setScrollingCacheEnabled(false);  
  700.             mScroller.abortAnimation();  
  701.             int oldX = getScrollX();  
  702.             int oldY = getScrollY();  
  703.             int x = mScroller.getCurrX();  
  704.             int y = mScroller.getCurrY();  
  705.             if (oldX != x || oldY != y) {  
  706.                 scrollTo(x, y);  
  707.             }  
  708.             setScrollState(SCROLL_STATE_IDLE);  
  709.         }  
  710.         mPopulatePending = false;  
  711.         mScrolling = false;  
  712.         for (int i = 0; i < mItems.size(); i++) {  
  713.             ItemInfo ii = mItems.get(i);  
  714.             if (ii.scrolling) {  
  715.                 needPopulate = true;  
  716.                 ii.scrolling = false;  
  717.             }  
  718.         }  
  719.         if (needPopulate) {  
  720.             populate();  
  721.         }  
  722.     }  
  723.   
  724.     @Override  
  725.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
  726.         /* 
  727.          * This method JUST determines whether we want to intercept the motion. 
  728.          * If we return true, onMotionEvent will be called and we do the actual 
  729.          * scrolling there. 
  730.          */  
  731.   
  732.         final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;  
  733.   
  734.         // Always take care of the touch gesture being complete.  
  735.         if (action == MotionEvent.ACTION_CANCEL  
  736.                 || action == MotionEvent.ACTION_UP) {  
  737.             // Release the drag.  
  738.             if (DEBUG)  
  739.                 Log.v(TAG, "Intercept done!");  
  740.             mIsBeingDragged = false;  
  741.             mIsUnableToDrag = false;  
  742.             mActivePointerId = INVALID_POINTER;  
  743.             return false;  
  744.         }  
  745.   
  746.         // Nothing more to do here if we have decided whether or not we  
  747.         // are dragging.  
  748.         if (action != MotionEvent.ACTION_DOWN) {  
  749.             if (mIsBeingDragged) {  
  750.                 if (DEBUG)  
  751.                     Log.v(TAG, "Intercept returning true!");  
  752.                 return true;  
  753.             }  
  754.             if (mIsUnableToDrag) {  
  755.                 if (DEBUG)  
  756.                     Log.v(TAG, "Intercept returning false!");  
  757.                 return false;  
  758.             }  
  759.         }  
  760.   
  761.         switch (action) {  
  762.         case MotionEvent.ACTION_MOVE: {  
  763.             /* 
  764.              * mIsBeingDragged == false, otherwise the shortcut would have 
  765.              * caught it. Check whether the user has moved far enough from his 
  766.              * original down touch. 
  767.              */  
  768.   
  769.             /* 
  770.              * Locally do absolute value. mLastMotionY is set to the y value of 
  771.              * the down event. 
  772.              */  
  773.             final int activePointerId = mActivePointerId;  
  774.             if (activePointerId == INVALID_POINTER  
  775.                     && Build.VERSION.SDK_INT > Build.VERSION_CODES.DONUT) {  
  776.                 // If we don't have a valid id, the touch down wasn't on  
  777.                 // content.  
  778.                 break;  
  779.             }  
  780.   
  781.             final int pointerIndex = MotionEventCompat.findPointerIndex(ev,  
  782.                     activePointerId);  
  783.             final float x = MotionEventCompat.getX(ev, pointerIndex);  
  784.             final float y = MotionEventCompat.getY(ev, pointerIndex);  
  785.             final float xDiff = Math.abs(x - mLastMotionX);  
  786.             final float yDiff = Math.abs(y - mLastMotionY);  
  787.             float primaryDiff;  
  788.             float secondaryDiff;  
  789.   
  790.             if (mOrientation == HORIZONTAL) {  
  791.                 primaryDiff = xDiff;  
  792.                 secondaryDiff = yDiff;  
  793.             } else {  
  794.                 primaryDiff = yDiff;  
  795.                 secondaryDiff = xDiff;  
  796.             }  
  797.   
  798.             if (DEBUG)  
  799.                 Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + ","  
  800.                         + yDiff);  
  801.   
  802.             if (primaryDiff > mTouchSlop && primaryDiff > secondaryDiff) {  
  803.                 if (DEBUG)  
  804.                     Log.v(TAG, "Starting drag!");  
  805.                 mIsBeingDragged = true;  
  806.                 setScrollState(SCROLL_STATE_DRAGGING);  
  807.                 if (mOrientation == HORIZONTAL) {  
  808.                     mLastMotionX = x;  
  809.                 } else {  
  810.                     mLastMotionY = y;  
  811.                 }  
  812.                 setScrollingCacheEnabled(true);  
  813.             } else {  
  814.                 if (secondaryDiff > mTouchSlop) {  
  815.                     // The finger has moved enough in the vertical  
  816.                     // direction to be counted as a drag... abort  
  817.                     // any attempt to drag horizontally, to work correctly  
  818.                     // with children that have scrolling containers.  
  819.                     if (DEBUG)  
  820.                         Log.v(TAG, "Starting unable to drag!");  
  821.                     mIsUnableToDrag = true;  
  822.                 }  
  823.             }  
  824.             break;  
  825.         }  
  826.   
  827.         case MotionEvent.ACTION_DOWN: {  
  828.             /* 
  829.              * Remember location of down touch. ACTION_DOWN always refers to 
  830.              * pointer index 0. 
  831.              */  
  832.             if (mOrientation == HORIZONTAL) {  
  833.                 mLastMotionX = mInitialMotion = ev.getX();  
  834.                 mLastMotionY = ev.getY();  
  835.             } else {  
  836.                 mLastMotionX = ev.getX();  
  837.                 mLastMotionY = mInitialMotion = ev.getY();  
  838.             }  
  839.             mActivePointerId = MotionEventCompat.getPointerId(ev, 0);  
  840.   
  841.             if (mScrollState == SCROLL_STATE_SETTLING) {  
  842.                 // Let the user 'catch' the pager as it animates.  
  843.                 mIsBeingDragged = true;  
  844.                 mIsUnableToDrag = false;  
  845.                 setScrollState(SCROLL_STATE_DRAGGING);  
  846.             } else {  
  847.                 completeScroll();  
  848.                 mIsBeingDragged = false;  
  849.                 mIsUnableToDrag = false;  
  850.             }  
  851.   
  852.             if (DEBUG)  
  853.                 Log.v(TAG, "Down at " + mLastMotionX + "," + mLastMotionY  
  854.                         + " mIsBeingDragged=" + mIsBeingDragged  
  855.                         + "mIsUnableToDrag=" + mIsUnableToDrag);  
  856.             break;  
  857.         }  
  858.   
  859.         case MotionEventCompat.ACTION_POINTER_UP:  
  860.             onSecondaryPointerUp(ev);  
  861.             break;  
  862.         }  
  863.   
  864.         /* 
  865.          * The only time we want to intercept motion events is if we are in the 
  866.          * drag mode. 
  867.          */  
  868.         return mIsBeingDragged;  
  869.     }  
  870.   
  871.     @Override  
  872.     public boolean onTouchEvent(MotionEvent ev) {  
  873.   
  874.         if (ev.getAction() == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) {  
  875.             // Don't handle edge touches immediately -- they may actually belong  
  876.             // to one of our  
  877.             // descendants.  
  878.             return false;  
  879.         }  
  880.   
  881.         if (mAdapter == null || mAdapter.getCount() == 0) {  
  882.             // Nothing to present or scroll; nothing to touch.  
  883.             return false;  
  884.         }  
  885.   
  886.         if (mVelocityTracker == null) {  
  887.             mVelocityTracker = VelocityTracker.obtain();  
  888.         }  
  889.         mVelocityTracker.addMovement(ev);  
  890.   
  891.         final int action = ev.getAction();  
  892.   
  893.         switch (action & MotionEventCompat.ACTION_MASK) {  
  894.         case MotionEvent.ACTION_DOWN: {  
  895.             /* 
  896.              * If being flinged and user touches, stop the fling. isFinished 
  897.              * will be false if being flinged. 
  898.              */  
  899.             completeScroll();  
  900.   
  901.             // Remember where the motion event started  
  902.             if (mOrientation == HORIZONTAL) {  
  903.                 mLastMotionX = mInitialMotion = ev.getX();  
  904.             } else {  
  905.                 mLastMotionY = mInitialMotion = ev.getY();  
  906.             }  
  907.             mActivePointerId = MotionEventCompat.getPointerId(ev, 0);  
  908.             break;  
  909.         }  
  910.         case MotionEvent.ACTION_MOVE:  
  911.             if (!mIsBeingDragged) {  
  912.                 final int pointerIndex = MotionEventCompat.findPointerIndex(ev,  
  913.                         mActivePointerId);  
  914.                 final float x = MotionEventCompat.getX(ev, pointerIndex);  
  915.                 final float y = MotionEventCompat.getY(ev, pointerIndex);  
  916.                 final float xDiff = Math.abs(x - mLastMotionX);  
  917.                 final float yDiff = Math.abs(y - mLastMotionY);  
  918.                 float primaryDiff;  
  919.                 float secondaryDiff;  
  920.   
  921.                 if (mOrientation == HORIZONTAL) {  
  922.                     primaryDiff = xDiff;  
  923.                     secondaryDiff = yDiff;  
  924.                 } else {  
  925.                     primaryDiff = yDiff;  
  926.                     secondaryDiff = xDiff;  
  927.                 }  
  928.   
  929.                 if (DEBUG)  
  930.                     Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff  
  931.                             + "," + yDiff);  
  932.                 if (primaryDiff > mTouchSlop && primaryDiff > secondaryDiff) {  
  933.                     if (DEBUG)  
  934.                         Log.v(TAG, "Starting drag!");  
  935.                     mIsBeingDragged = true;  
  936.                     if (mOrientation == HORIZONTAL) {  
  937.                         mLastMotionX = x;  
  938.                     } else {  
  939.                         mLastMotionY = y;  
  940.                     }  
  941.                     setScrollState(SCROLL_STATE_DRAGGING);  
  942.                     setScrollingCacheEnabled(true);  
  943.                 }  
  944.             }  
  945.             if (mIsBeingDragged) {  
  946.                 // Scroll to follow the motion event  
  947.                 final int activePointerIndex = MotionEventCompat  
  948.                         .findPointerIndex(ev, mActivePointerId);  
  949.                 final float x = MotionEventCompat.getX(ev, activePointerIndex);  
  950.                 final float y = MotionEventCompat.getY(ev, activePointerIndex);  
  951.   
  952.                 int size;  
  953.                 float scroll;  
  954.   
  955.                 if (mOrientation == HORIZONTAL) {  
  956.                     size = getWidth();  
  957.                     scroll = getScrollX() + (mLastMotionX - x);  
  958.                     mLastMotionX = x;  
  959.                 } else {  
  960.                     size = getHeight();  
  961.                     scroll = getScrollY() + (mLastMotionY - y);  
  962.                     mLastMotionY = y;  
  963.                 }  
  964.   
  965.                 final float lowerBound = Math.max(0, (mCurItem - 1) * size);  
  966.                 final float upperBound = Math.min(mCurItem + 1,  
  967.                         mAdapter.getCount() - 1)  
  968.                         * size;  
  969.                 if (scroll < lowerBound) {  
  970.                     scroll = lowerBound;  
  971.                 } else if (scroll > upperBound) {  
  972.                     scroll = upperBound;  
  973.                 }  
  974.                 if (mOrientation == HORIZONTAL) {  
  975.                     // Don't lose the rounded component  
  976.                     mLastMotionX += scroll - (int) scroll;  
  977.                     scrollTo((int) scroll, getScrollY());  
  978.                 } else {  
  979.                     // Don't lose the rounded component  
  980.                     mLastMotionY += scroll - (int) scroll;  
  981.                     scrollTo(getScrollX(), (int) scroll);  
  982.                 }  
  983.                 if (mOnPageChangeListener != null) {  
  984.                     final int position = (int) scroll / size;  
  985.                     final int positionOffsetPixels = (int) scroll % size;  
  986.                     final float positionOffset = (float) positionOffsetPixels  
  987.                             / size;  
  988.                     mOnPageChangeListener.onPageScrolled(position,  
  989.                             positionOffset, positionOffsetPixels);  
  990.                 }  
  991.             }  
  992.             break;  
  993.         case MotionEvent.ACTION_UP:  
  994.             if (mIsBeingDragged) {  
  995.                 final VelocityTracker velocityTracker = mVelocityTracker;  
  996.                 velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);  
  997.                 int initialVelocity;  
  998.                 float lastMotion;  
  999.                 int sizeOverThree;  
  1000.   
  1001.                 if (mOrientation == HORIZONTAL) {  
  1002.                     initialVelocity = (int) VelocityTrackerCompat.getXVelocity(  
  1003.                             velocityTracker, mActivePointerId);  
  1004.                     lastMotion = mLastMotionX;  
  1005.                     sizeOverThree = getWidth() / 3;  
  1006.                 } else {  
  1007.                     initialVelocity = (int) VelocityTrackerCompat.getYVelocity(  
  1008.                             velocityTracker, mActivePointerId);  
  1009.                     lastMotion = mLastMotionY;  
  1010.                     sizeOverThree = getHeight() / 3;  
  1011.                 }  
  1012.   
  1013.                 mPopulatePending = true;  
  1014.                 if ((Math.abs(initialVelocity) > mMinimumVelocity)  
  1015.                         || Math.abs(mInitialMotion - lastMotion) >= sizeOverThree) {  
  1016.                     if (lastMotion > mInitialMotion) {  
  1017.                         setCurrentItemInternal(mCurItem - 1truetrue);  
  1018.                     } else {  
  1019.                         setCurrentItemInternal(mCurItem + 1truetrue);  
  1020.                     }  
  1021.                 } else {  
  1022.                     setCurrentItemInternal(mCurItem, truetrue);  
  1023.                 }  
  1024.   
  1025.                 mActivePointerId = INVALID_POINTER;  
  1026.                 endDrag();  
  1027.             }  
  1028.             break;  
  1029.         case MotionEvent.ACTION_CANCEL:  
  1030.             if (mIsBeingDragged) {  
  1031.                 setCurrentItemInternal(mCurItem, truetrue);  
  1032.                 mActivePointerId = INVALID_POINTER;  
  1033.                 endDrag();  
  1034.             }  
  1035.             break;  
  1036.         case MotionEventCompat.ACTION_POINTER_DOWN: {  
  1037.             final int index = MotionEventCompat.getActionIndex(ev);  
  1038.             if (mOrientation == HORIZONTAL) {  
  1039.                 mLastMotionX = MotionEventCompat.getX(ev, index);  
  1040.             } else {  
  1041.                 mLastMotionY = MotionEventCompat.getY(ev, index);  
  1042.             }  
  1043.             mActivePointerId = MotionEventCompat.getPointerId(ev, index);  
  1044.             break;  
  1045.         }  
  1046.         case MotionEventCompat.ACTION_POINTER_UP:  
  1047.             onSecondaryPointerUp(ev);  
  1048.             final int index = MotionEventCompat.findPointerIndex(ev,  
  1049.                     mActivePointerId);  
  1050.             if (mOrientation == HORIZONTAL) {  
  1051.                 mLastMotionX = MotionEventCompat.getX(ev, index);  
  1052.             } else {  
  1053.                 mLastMotionY = MotionEventCompat.getY(ev, index);  
  1054.             }  
  1055.             break;  
  1056.         }  
  1057.         return true;  
  1058.     }  
  1059.   
  1060.     private void onSecondaryPointerUp(MotionEvent ev) {  
  1061.         final int pointerIndex = MotionEventCompat.getActionIndex(ev);  
  1062.         final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);  
  1063.         if (pointerId == mActivePointerId) {  
  1064.             // This was our active pointer going up. Choose a new  
  1065.             // active pointer and adjust accordingly.  
  1066.             final int newPointerIndex = pointerIndex == 0 ? 1 : 0;  
  1067.             if (mOrientation == HORIZONTAL) {  
  1068.                 mLastMotionX = MotionEventCompat.getX(ev, newPointerIndex);  
  1069.             } else {  
  1070.                 mLastMotionY = MotionEventCompat.getY(ev, newPointerIndex);  
  1071.             }  
  1072.             mActivePointerId = MotionEventCompat.getPointerId(ev,  
  1073.                     newPointerIndex);  
  1074.             if (mVelocityTracker != null) {  
  1075.                 mVelocityTracker.clear();  
  1076.             }  
  1077.         }  
  1078.     }  
  1079.   
  1080.     private void endDrag() {  
  1081.         mIsBeingDragged = false;  
  1082.         mIsUnableToDrag = false;  
  1083.   
  1084.         if (mVelocityTracker != null) {  
  1085.             mVelocityTracker.recycle();  
  1086.             mVelocityTracker = null;  
  1087.         }  
  1088.     }  
  1089.   
  1090.     private void setScrollingCacheEnabled(boolean enabled) {  
  1091.         if (mScrollingCacheEnabled != enabled) {  
  1092.             mScrollingCacheEnabled = enabled;  
  1093.             if (USE_CACHE) {  
  1094.                 final int size = getChildCount();  
  1095.                 for (int i = 0; i < size; ++i) {  
  1096.                     final View child = getChildAt(i);  
  1097.                     if (child.getVisibility() != GONE) {  
  1098.                         child.setDrawingCacheEnabled(enabled);  
  1099.                     }  
  1100.                 }  
  1101.             }  
  1102.         }  
  1103.     }  
  1104.   
  1105.     private class DataSetObserver implements  
  1106.             VerticalViewPagerCompat.DataSetObserver {  
  1107.         @Override  
  1108.         public void onDataSetChanged() {  
  1109.             dataSetChanged();  
  1110.         }  
  1111.     }  
  1112. }  


Andoird 自定义ViewGroup实现竖向引导界面 
http://blog.csdn.net/lmj623565791/article/details/23692439 


Android-PullToNextLayout 
http://www.23code.com/android-pulltonextlayout/
1 0
原创粉丝点击