提取Launcher中的WorkSapce,可以左右滑动切换屏幕页面的类

来源:互联网 发布:中国工业数据库 编辑:程序博客网 时间:2024/05/17 04:52

提取Launcher中的WorkSapce,可以左右滑动切换屏幕页面的类

 

By:Yao.GUET 转载请注明出处。

http://blog.csdn.net/Yao_GUET

 

 

对于Launcher的桌面滑动大家应该都比较熟悉了,最好的体验应该是可以随着手指的滑动而显示不同位置的桌面,

比一般用ViewFlinger+动画所实现的手势切换页面感觉良好多了~~~~

分析了一下Launcher中的WorkSpace,里面有太多的代码我们用不上了(拖拽,长按,,,),把里面的冗余代码去掉得到实现滑动切换屏幕所必需的。。。。

新建一个ScrollLayout类,继承自ViewGroup。

重写onMeasure和onLayout两个方法:

其中onMeasure方法中,得到ScrollLayout的布局方式(一般使用FILL_PARENT),然后再枚举其中所有的子view,设置它们的布局(FILL_PARENT),这样在ScrollLayout之中的每一个子view即为充满屏幕可以滑动显示的其中一页。

在onLayout方法中,横向画出每一个子view,这样所得到的view的高与屏幕高一致,宽度为getChildCount()-1个屏幕宽度的view。

 

添加一个Scroller来平滑过渡各个页面之间的切换,

 

重写onInterceptTouchEvent和onTouchEvent来响应手指按下划动时所需要捕获的消息,例如划动的速度,划动的距离等。再配合使用scrollBy (int x, int y)方法得到慢速滑动小距离的时候,所需要显示的内容。最后当手指起来时,根据划动的速度与跨度来判断是向左滑动一页还是向右滑动一页,确保每次用户操作结束之后显示的都是整体的一个子view.

 

 

 

ScrollLayout源码:

[java] view plaincopy
  1. package com.yao_guet.test;  
  2. import android.content.Context;  
  3. import android.graphics.Canvas;  
  4. import android.util.AttributeSet;  
  5. import android.util.Log;  
  6. import android.view.MotionEvent;  
  7. import android.view.VelocityTracker;  
  8. import android.view.View;  
  9. import android.view.ViewConfiguration;  
  10. import android.view.ViewGroup;  
  11. import android.widget.Scroller;  
  12. /** 
  13.  * 仿Launcher中的WorkSapce,可以左右滑动切换屏幕的类 
  14.  * @author Yao.GUET 
  15.  * blog: http://blog.csdn.net/Yao_GUET 
  16.  * date: 2011-05-04 
  17.  */  
  18. public class ScrollLayout extends ViewGroup {  
  19.     private static final String TAG = "ScrollLayout";  
  20.     private Scroller mScroller;  
  21.     private VelocityTracker mVelocityTracker;  
  22.       
  23.     private int mCurScreen;  
  24.     private int mDefaultScreen = 0;  
  25.       
  26.     private static final int TOUCH_STATE_REST = 0;  
  27.     private static final int TOUCH_STATE_SCROLLING = 1;  
  28.       
  29.     private static final int SNAP_VELOCITY = 600;  
  30.       
  31.     private int mTouchState = TOUCH_STATE_REST;  
  32.     private int mTouchSlop;  
  33.     private float mLastMotionX;  
  34.     private float mLastMotionY;  
  35.     public ScrollLayout(Context context, AttributeSet attrs) {  
  36.         this(context, attrs, 0);  
  37.         // TODO Auto-generated constructor stub  
  38.     }  
  39.     public ScrollLayout(Context context, AttributeSet attrs, int defStyle) {  
  40.         super(context, attrs, defStyle);  
  41.         // TODO Auto-generated constructor stub  
  42.         mScroller = new Scroller(context);  
  43.           
  44.         mCurScreen = mDefaultScreen;  
  45.         mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();  
  46.     }  
  47.     @Override  
  48.     protected void onLayout(boolean changed, int l, int t, int r, int b) {  
  49.         // TODO Auto-generated method stub  
  50.         int childLeft = 0;  
  51.         final int childCount = getChildCount();  
  52.           
  53.         for (int i=0; i<childCount; i++) {  
  54.             final View childView = getChildAt(i);  
  55.             if (childView.getVisibility() != View.GONE) {  
  56.                 final int childWidth = childView.getMeasuredWidth();  
  57.                 childView.layout(childLeft, 0,   
  58.                         childLeft+childWidth, childView.getMeasuredHeight());  
  59.                 childLeft += childWidth;  
  60.             }  
  61.         }  
  62.     }  
  63.     @Override    
  64.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {     
  65.         Log.e(TAG, "onMeasure");  
  66.         super.onMeasure(widthMeasureSpec, heightMeasureSpec);     
  67.     
  68.         final int width = MeasureSpec.getSize(widthMeasureSpec);     
  69.         final int widthMode = MeasureSpec.getMode(widthMeasureSpec);     
  70.         if (widthMode != MeasureSpec.EXACTLY) {     
  71.             throw new IllegalStateException("ScrollLayout only canmCurScreen run at EXACTLY mode!");   
  72.         }     
  73.     
  74.         final int heightMode = MeasureSpec.getMode(heightMeasureSpec);     
  75.         if (heightMode != MeasureSpec.EXACTLY) {     
  76.             throw new IllegalStateException("ScrollLayout only can run at EXACTLY mode!");  
  77.         }     
  78.     
  79.         // The children are given the same width and height as the scrollLayout     
  80.         final int count = getChildCount();     
  81.         for (int i = 0; i < count; i++) {     
  82.             getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);     
  83.         }     
  84.         // Log.e(TAG, "moving to screen "+mCurScreen);     
  85.         scrollTo(mCurScreen * width, 0);           
  86.     }    
  87.       
  88.     /** 
  89.      * According to the position of current layout 
  90.      * scroll to the destination page. 
  91.      */  
  92.     public void snapToDestination() {  
  93.         final int screenWidth = getWidth();  
  94.         final int destScreen = (getScrollX()+ screenWidth/2)/screenWidth;  
  95.         snapToScreen(destScreen);  
  96.     }  
  97.       
  98.     public void snapToScreen(int whichScreen) {  
  99.         // get the valid layout page  
  100.         whichScreen = Math.max(0, Math.min(whichScreen, getChildCount()-1));  
  101.         if (getScrollX() != (whichScreen*getWidth())) {  
  102.               
  103.             final int delta = whichScreen*getWidth()-getScrollX();  
  104.             mScroller.startScroll(getScrollX(), 0,   
  105.                     delta, 0, Math.abs(delta)*2);  
  106.             mCurScreen = whichScreen;  
  107.             invalidate();       // Redraw the layout  
  108.         }  
  109.     }  
  110.       
  111.     public void setToScreen(int whichScreen) {  
  112.         whichScreen = Math.max(0, Math.min(whichScreen, getChildCount()-1));  
  113.         mCurScreen = whichScreen;  
  114.         scrollTo(whichScreen*getWidth(), 0);  
  115.     }  
  116.       
  117.     public int getCurScreen() {  
  118.         return mCurScreen;  
  119.     }  
  120.       
  121.     @Override  
  122.     public void computeScroll() {  
  123.         // TODO Auto-generated method stub  
  124.         if (mScroller.computeScrollOffset()) {  
  125.             scrollTo(mScroller.getCurrX(), mScroller.getCurrY());  
  126.             postInvalidate();  
  127.         }  
  128.     }  
  129.     @Override  
  130.     public boolean onTouchEvent(MotionEvent event) {  
  131.         // TODO Auto-generated method stub  
  132.           
  133.         if (mVelocityTracker == null) {  
  134.             mVelocityTracker = VelocityTracker.obtain();  
  135.         }  
  136.         mVelocityTracker.addMovement(event);  
  137.           
  138.         final int action = event.getAction();  
  139.         final float x = event.getX();  
  140.         final float y = event.getY();  
  141.           
  142.         switch (action) {  
  143.         case MotionEvent.ACTION_DOWN:  
  144.             Log.e(TAG, "event down!");  
  145.             if (!mScroller.isFinished()){  
  146.                 mScroller.abortAnimation();  
  147.             }  
  148.             mLastMotionX = x;  
  149.             break;  
  150.               
  151.         case MotionEvent.ACTION_MOVE:  
  152.             int deltaX = (int)(mLastMotionX - x);  
  153.             mLastMotionX = x;  
  154.               
  155.             scrollBy(deltaX, 0);  
  156.             break;  
  157.               
  158.         case MotionEvent.ACTION_UP:  
  159.             Log.e(TAG, "event : up");     
  160.             // if (mTouchState == TOUCH_STATE_SCROLLING) {     
  161.             final VelocityTracker velocityTracker = mVelocityTracker;     
  162.             velocityTracker.computeCurrentVelocity(1000);     
  163.             int velocityX = (int) velocityTracker.getXVelocity();     
  164.             Log.e(TAG, "velocityX:"+velocityX);   
  165.               
  166.             if (velocityX > SNAP_VELOCITY && mCurScreen > 0) {     
  167.                 // Fling enough to move left     
  168.                 Log.e(TAG, "snap left");  
  169.                 snapToScreen(mCurScreen - 1);     
  170.             } else if (velocityX < -SNAP_VELOCITY     
  171.                     && mCurScreen < getChildCount() - 1) {     
  172.                 // Fling enough to move right     
  173.                 Log.e(TAG, "snap right");  
  174.                 snapToScreen(mCurScreen + 1);     
  175.             } else {     
  176.                 snapToDestination();     
  177.             }     
  178.             if (mVelocityTracker != null) {     
  179.                 mVelocityTracker.recycle();     
  180.                 mVelocityTracker = null;     
  181.             }     
  182.             // }     
  183.             mTouchState = TOUCH_STATE_REST;     
  184.             break;  
  185.         case MotionEvent.ACTION_CANCEL:  
  186.             mTouchState = TOUCH_STATE_REST;  
  187.             break;  
  188.         }  
  189.           
  190.         return true;  
  191.     }  
  192.     @Override  
  193.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
  194.         // TODO Auto-generated method stub  
  195.         Log.e(TAG, "onInterceptTouchEvent-slop:"+mTouchSlop);  
  196.           
  197.         final int action = ev.getAction();  
  198.         if ((action == MotionEvent.ACTION_MOVE) &&   
  199.                 (mTouchState != TOUCH_STATE_REST)) {  
  200.             return true;  
  201.         }  
  202.           
  203.         final float x = ev.getX();  
  204.         final float y = ev.getY();  
  205.           
  206.         switch (action) {  
  207.         case MotionEvent.ACTION_MOVE:  
  208.             final int xDiff = (int)Math.abs(mLastMotionX-x);  
  209.             if (xDiff>mTouchSlop) {  
  210.                 mTouchState = TOUCH_STATE_SCROLLING;  
  211.                   
  212.             }  
  213.             break;  
  214.               
  215.         case MotionEvent.ACTION_DOWN:  
  216.             mLastMotionX = x;  
  217.             mLastMotionY = y;  
  218.             mTouchState = mScroller.isFinished()? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;  
  219.             break;  
  220.               
  221.         case MotionEvent.ACTION_CANCEL:  
  222.         case MotionEvent.ACTION_UP:  
  223.             mTouchState = TOUCH_STATE_REST;  
  224.             break;  
  225.         }  
  226.           
  227.         return mTouchState != TOUCH_STATE_REST;  
  228.     }  
  229.       
  230. }  


测试程序布局:

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <com.yao_guet.test.ScrollLayout  
  3.   xmlns:android="http://schemas.android.com/apk/res/android"  
  4.   android:id="@+id/ScrollLayoutTest"  
  5.   android:layout_width="fill_parent"  
  6.   android:layout_height="fill_parent">  
  7. <LinearLayout  
  8.   android:background="#FF00"  
  9.   android:layout_width="fill_parent"  
  10.   android:layout_height="fill_parent"></LinearLayout>  
  11.     
  12. <FrameLayout  
  13.   android:background="#F0F0"  
  14.   android:layout_width="fill_parent"  
  15.   android:layout_height="fill_parent"></FrameLayout>  
  16.     
  17. <FrameLayout  
  18.   android:background="#F00F"  
  19.   android:layout_width="fill_parent"  
  20.   android:layout_height="fill_parent">  
  21.   </FrameLayout>  
  22.     
  23. <LinearLayout  
  24.   android:background="#FF00"  
  25.   android:layout_width="fill_parent"  
  26.   android:layout_height="fill_parent">  
  27.   <Button  
  28.     android:layout_width="wrap_content"  
  29.     android:layout_height="wrap_content"  
  30.     android:text="Button1" />  
  31.   </LinearLayout>  
  32. <LinearLayout  
  33.   android:layout_width="wrap_content"  
  34.   android:layout_height="wrap_content">  
  35.   <Button  
  36.     android:layout_width="wrap_content"  
  37.     android:layout_height="wrap_content"  
  38.     android:text="Button2" />  
  39.   </LinearLayout>  
  40. </com.yao_guet.test.ScrollLayout>  


原创粉丝点击