Android UI(继承控件)--VerticalViewPager 垂直方向的viewpager

  1 package com.wzq.verticalViewPager;
  2 
  3 import android.content.Context;
  4 import android.util.AttributeSet;
  5 import android.util.DisplayMetrics;
  6 import android.util.Log;
  7 import android.view.MotionEvent;
  8 import android.view.VelocityTracker;
  9 import android.view.View;
 10 import android.view.ViewGroup;
 11 import android.view.WindowManager;
 12 import android.widget.Scroller;
 13 
 14 /**
 15  * 垂直方向上的ViewPager
 16  */
 17 public class VerticalViewPager extends ViewGroup {
 18 
 19     /**
 20      * 屏幕的高度
 21      */
 22     private int mScreenHeight;
 23     /**
 24      * 手指按下时的getScrollY
 25      */
 26     private int mScrollStart;
 27     /**
 28      * 手指抬起时的getScrollY
 29      */
 30     private int mScrollEnd;
 31     /**
 32      * 记录移动时的Y
 33      */
 34     private int mLastY;
 35     /**
 36      * 滚动的辅助类
 37      */
 38     private Scroller mScroller;
 39     /**
 40      * 是否正在滚动
 41      */
 42     private boolean isScrolling;
 43     /**
 44      * 加速度检测
 45      */
 46     private VelocityTracker mVelocityTracker;
 47     /**
 48      * 记录当前页
 49      */
 50     private int currentPage = 0;
 51 
 52     private OnPageChangeListener mOnPageChangeListener;
 53 
 54     /**
 55      * 回调接口
 56      */
 57     public interface OnPageChangeListener {
 58         void onPageChange(int currentPage);
 59     }
 60 
 61     /**
 62      * 设置回调接口
 63      * 
 64      * @param listener
 65      */
 66     public void setOnPageChangeListener(OnPageChangeListener listener) {
 67         mOnPageChangeListener = listener;
 68     }
 69 
 70     public VerticalViewPager(Context context, AttributeSet attrs) {
 71         super(context, attrs);
 72         /**
 73          * 获取屏幕高度
 74          */
 75         DisplayMetrics dm = new DisplayMetrics();
 76         WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
 77         wm.getDefaultDisplay().getMetrics(dm);
 78         mScreenHeight = dm.heightPixels;
 79         // 初始化滚动辅助类
 80         mScroller = new Scroller(context);
 81     }
 82 
 83     @Override
 84     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 85         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 86         int count = getChildCount();
 87         for (int i = 0; i < count; i++) {
 88             View childView = getChildAt(i);
 89             measureChild(childView, widthMeasureSpec, heightMeasureSpec);
 90         }
 91     }
 92 
 93     @Override
 94     protected void onLayout(boolean changed, int l, int t, int r, int b) {
 95         if (changed) {
 96             childCount = getChildCount();
 97 
 98             // 1, 设置主布局的高度(孩子个数 * 屏幕高度)
 99             MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
100             lp.height = mScreenHeight * childCount;
101             setLayoutParams(lp);
102             // 2,调整每个孩子的高度
103             for (int i = 0; i < childCount; i++) {
104                 View child = getChildAt(i);
105                 if (child.getVisibility() != View.GONE) {
106                     child.layout(l, i * mScreenHeight, r, (i + 1) * mScreenHeight);
107                 }
108             }
109         }
110     }
111 
112     private String TAG = "VerticalViewPager";
113     private int childCount;
114 
115     @Override
116     public boolean onTouchEvent(MotionEvent event) {
117         // 如果当前正在滚动,调用父类的onTouchEvent
118         if (isScrolling)
119             return super.onTouchEvent(event);
120         int action = event.getAction();
121         int y = (int) event.getY();
122         obtainVelocity(event);
123         switch (action) {
124         case MotionEvent.ACTION_DOWN:
125             mScrollStart = getScrollY();
126             mLastY = y;
127             Log.i(TAG, "111111---ACTION_DOWN getScrollY = " + mScrollStart + " ; mLastY = "
128                     + mLastY);
129             break;
130         case MotionEvent.ACTION_MOVE:
131             if (!mScroller.isFinished()) {
132                 mScroller.abortAnimation();
133             }
134             int dy = mLastY - y;
135             int scrollY = getScrollY();
136             // 边界值检查
137             Log.i(TAG, "2---ACTION_MOVE ; dy =  " + dy + " scrollY = " + scrollY);
138             // 已经到达控件最顶端,此时下拉,拉拽速度减半
139             if (dy < 0 && scrollY <= 0) {
140                 dy = dy / 2;// 控件移动速度减半
141             }
142             // 已经到达控件最底部,此时上拉,拉拽速度减半
143             // if (dy > 0 && scrollY + dy > getHeight() - mScreenHeight) {
144             if (dy > 0 && scrollY > (childCount - 1) * mScreenHeight) {
145                 dy = dy / 2;// 控件移动速度减半
146             }
147             scrollBy(0, dy);
148             mLastY = y;
149             break;
150         case MotionEvent.ACTION_UP:
151             mScrollEnd = getScrollY();
152             int dScrollY = mScrollEnd - mScrollStart;
153             Log.i(TAG, "333333---ACTION_UP_UP getScrollY = " + mScrollEnd + " ; dScrollY = "
154                     + dScrollY);
155             if (wantScrollToNext()) {// 往上滑动
156                 if (mScrollStart == (childCount - 1) * mScreenHeight) {// 已经在整个控件的最底部了
157                     mScroller.startScroll(0, getScrollY(), 0, -dScrollY);// 回弹(用户不想换页)
158                 } else {
159                     if (shouldScrollToNext()) {
160                         mScroller.startScroll(0, getScrollY(), 0, mScreenHeight - dScrollY);// 换页
161                     } else {
162                         mScroller.startScroll(0, getScrollY(), 0, -dScrollY);// 回弹
163                     }
164                 }
165             }
166             if (wantScrollToPre()) {// 往下滑动
167                 if (mScrollStart == 0) {// 已经在整个控件的最顶部了
168                     mScroller.startScroll(0, getScrollY(), 0, -dScrollY);// 回弹
169                 } else {
170                     if (shouldScrollToPre()) {
171                         mScroller.startScroll(0, getScrollY(), 0, -mScreenHeight - dScrollY);// 换页
172                     } else {
173                         mScroller.startScroll(0, getScrollY(), 0, -dScrollY);// 回弹
174                     }
175                 }
176             }
177             isScrolling = true;
178             postInvalidate();
179             recycleVelocity();
180             break;
181         }
182         return true;
183     }
184 
185     @Override
186     public void computeScroll() {
187         super.computeScroll();
188         // the animation is not yet finished
189         if (mScroller.computeScrollOffset()) {
190             scrollTo(0, mScroller.getCurrY());
191             postInvalidate();
192             Log.i(TAG, "44---computeScroll  animation is not not not not not yet finished");
193         } else {// animation is finished
194             Log.i(TAG, "44---computeScroll  animation finished");
195             int position = getScrollY() / mScreenHeight;
196             Log.i(TAG, "~~~~~~~~~computeScroll  position = " + position + " , currentPage = "
197                     + currentPage);
198             if (position != currentPage) {
199                 if (mOnPageChangeListener != null) {
200                     currentPage = position;
201                     mOnPageChangeListener.onPageChange(currentPage);
202                 }
203             }
204             isScrolling = false;
205         }
206     }
207 
208     /**
209      * 根据滚动距离判断是否能够滚到下一页
210      * 
211      * @return
212      */
213     private boolean shouldScrollToNext() {
214         return mScrollEnd - mScrollStart > mScreenHeight / 2 || Math.abs(getVelocity()) > 600;
215     }
216 
217     /**
218      * 根据滚动距离判断是否能够滚动到上一页
219      * 
220      * @return
221      */
222     private boolean shouldScrollToPre() {
223         return -mScrollEnd + mScrollStart > mScreenHeight / 2 || Math.abs(getVelocity()) > 600;
224     }
225 
226     /**
227      * 根据用户滑动,判断用户的意图是否是滚动到上一页,即手向下滑动。
228      * 
229      * @return
230      */
231     private boolean wantScrollToPre() {
232         return mScrollEnd < mScrollStart;
233     }
234 
235     /**
236      * 根据用户滑动,判断用户的意图是否是滚到到下一页,即手向上滑动。
237      * 
238      * @return
239      */
240     private boolean wantScrollToNext() {
241         return mScrollEnd > mScrollStart;
242     }
243 
244     /**
245      * 获取Y方向的加速度
246      * 
247      * @return
248      */
249     private int getVelocity() {
250         mVelocityTracker.computeCurrentVelocity(1000);
251         return (int) mVelocityTracker.getYVelocity();
252     }
253 
254     /**
255      * 初始化加速度检测器
256      * 
257      * @param event
258      */
259     private void obtainVelocity(MotionEvent event) {
260         if (mVelocityTracker == null) {
261             mVelocityTracker = VelocityTracker.obtain();
262         }
263         mVelocityTracker.addMovement(event);
264     }
265 
266     /**
267      * 是否资源
268      */
269     private void recycleVelocity() {
270         if (mVelocityTracker != null) {
271             mVelocityTracker.recycle();
272             mVelocityTracker = null;
273         }
274     }
275 
276 }

xml文件 

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <com.wzq.verticalViewPager.VerticalViewPager xmlns:android="http://schemas.android.com/apk/res/android"
 3     xmlns:tools="http://schemas.android.com/tools"
 4     android:id="@+id/id_main_ly"
 5     android:layout_width="match_parent"
 6     android:layout_height="match_parent"
 7     android:orientation="vertical" >
 8 
 9     <RelativeLayout
10         android:layout_width="match_parent"
11         android:layout_height="match_parent"
12         android:background="@drawable/introduce" >
13 
14         <Button
15             android:layout_width="wrap_content"
16             android:layout_height="wrap_content"
17             android:text="position = 0" />
18     </RelativeLayout>
19 
20     <RelativeLayout
21         android:layout_width="match_parent"
22         android:layout_height="match_parent"
23         android:background="@drawable/introduce" >
24 
25         <Button
26             android:layout_width="wrap_content"
27             android:layout_height="wrap_content"
28             android:text="position = 1" />
29     </RelativeLayout>
30 
31     <RelativeLayout
32         android:layout_width="match_parent"
33         android:layout_height="match_parent"
34         android:background="@drawable/introduce" >
35 
36         <Button
37             android:layout_width="wrap_content"
38             android:layout_height="wrap_content"
39             android:text="position = 2" />
40     </RelativeLayout>
41 
42     <RelativeLayout
43         android:layout_width="match_parent"
44         android:layout_height="match_parent"
45         android:background="@drawable/introduce" >
46 
47         <Button
48             android:layout_width="wrap_content"
49             android:layout_height="wrap_content"
50             android:text="position = 3" />
51     </RelativeLayout>
52 
53 </com.wzq.verticalViewPager.VerticalViewPager>

引用

 1 public class VerticalViewPagerActivity extends Activity {
 2     private VerticalViewPager mMianLayout;
 3 
 4     @Override
 5     protected void onCreate(Bundle savedInstanceState) {
 6         super.onCreate(savedInstanceState);
 7         setContentView(R.layout.a_vertical_viewpager);
 8 
 9         mMianLayout = (VerticalViewPager) findViewById(R.id.id_main_ly);
10         mMianLayout.setOnPageChangeListener(new OnPageChangeListener() {
11             @Override
12             public void onPageChange(int currentPage) {
13                 // TODO
14             }
15         });
16     }
17 
18 }

参考:http://blog.csdn.net/lmj623565791/article/details/23692439 

原文地址:https://www.cnblogs.com/wangziqiang/p/4187222.html