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

提取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源码:
 

 

view plaincopy to clipboardprint?
01.package com.yao_guet.test; 
02.import android.content.Context; 
03.import android.graphics.Canvas; 
04.import android.util.AttributeSet; 
05.import android.util.Log; 
06.import android.view.MotionEvent; 
07.import android.view.VelocityTracker; 
08.import android.view.View; 
09.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.        if (changed) { 
51.            int childLeft = 0; 
52.            final int childCount = getChildCount(); 
53.             
54.            for (int i=0; i<childCount; i++) { 
55.                final View childView = getChildAt(i); 
56.                if (childView.getVisibility() != View.GONE) { 
57.                    final int childWidth = childView.getMeasuredWidth(); 
58.                    childView.layout(childLeft, 0,  
59.                            childLeft+childWidth, childView.getMeasuredHeight()); 
60.                    childLeft += childWidth; 
61.                } 
62.            } 
63.        } 
64.    } 
65.    @Override   
66.    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    
67.        Log.e(TAG, "onMeasure"); 
68.        super.onMeasure(widthMeasureSpec, heightMeasureSpec);    
69.   
70.        final int width = MeasureSpec.getSize(widthMeasureSpec);    
71.        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);    
72.        if (widthMode != MeasureSpec.EXACTLY) {    
73.            throw new IllegalStateException("ScrollLayout only canmCurScreen run at EXACTLY mode!");  
74.        }    
75.   
76.        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);    
77.        if (heightMode != MeasureSpec.EXACTLY) {    
78.            throw new IllegalStateException("ScrollLayout only can run at EXACTLY mode!"); 
79.        }    
80.   
81.        // The children are given the same width and height as the scrollLayout    
82.        final int count = getChildCount();    
83.        for (int i = 0; i < count; i++) {    
84.            getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);    
85.        }    
86.        // Log.e(TAG, "moving to screen "+mCurScreen);    
87.        scrollTo(mCurScreen * width, 0);          
88.    }   
89.     
90.    /**
91.     * According to the position of current layout
92.     * scroll to the destination page.
93.     */ 
94.    public void snapToDestination() { 
95.        final int screenWidth = getWidth(); 
96.        final int destScreen = (getScrollX()+ screenWidth/2)/screenWidth; 
97.        snapToScreen(destScreen); 
98.    } 
99.     
100.    public void snapToScreen(int whichScreen) { 
101.        // get the valid layout page 
102.        whichScreen = Math.max(0, Math.min(whichScreen, getChildCount()-1)); 
103.        if (getScrollX() != (whichScreen*getWidth())) { 
104.             
105.            final int delta = whichScreen*getWidth()-getScrollX(); 
106.            mScroller.startScroll(getScrollX(), 0,  
107.                    delta, 0, Math.abs(delta)*2); 
108.            mCurScreen = whichScreen; 
109.            invalidate();       // Redraw the layout 
110.        } 
111.    } 
112.     
113.    public void setToScreen(int whichScreen) { 
114.        whichScreen = Math.max(0, Math.min(whichScreen, getChildCount()-1)); 
115.        mCurScreen = whichScreen; 
116.        scrollTo(whichScreen*getWidth(), 0); 
117.    } 
118.     
119.    public int getCurScreen() { 
120.        return mCurScreen; 
121.    } 
122.     
123.    @Override 
124.    public void computeScroll() { 
125.        // TODO Auto-generated method stub 
126.        if (mScroller.computeScrollOffset()) { 
127.            scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); 
128.            postInvalidate(); 
129.        } 
130.    } 
131.    @Override 
132.    public boolean onTouchEvent(MotionEvent event) { 
133.        // TODO Auto-generated method stub 
134.         
135.        if (mVelocityTracker == null) { 
136.            mVelocityTracker = VelocityTracker.obtain(); 
137.        } 
138.        mVelocityTracker.addMovement(event); 
139.         
140.        final int action = event.getAction(); 
141.        final float x = event.getX(); 
142.        final float y = event.getY(); 
143.         
144.        switch (action) { 
145.        case MotionEvent.ACTION_DOWN: 
146.            Log.e(TAG, "event down!"); 
147.            if (!mScroller.isFinished()){ 
148.                mScroller.abortAnimation(); 
149.            } 
150.            mLastMotionX = x; 
151.            break; 
152.             
153.        case MotionEvent.ACTION_MOVE: 
154.            int deltaX = (int)(mLastMotionX - x); 
155.            mLastMotionX = x; 
156.             
157.            scrollBy(deltaX, 0); 
158.            break; 
159.             
160.        case MotionEvent.ACTION_UP: 
161.            Log.e(TAG, "event : up");    
162.            // if (mTouchState == TOUCH_STATE_SCROLLING) {    
163.            final VelocityTracker velocityTracker = mVelocityTracker;    
164.            velocityTracker.computeCurrentVelocity(1000);    
165.            int velocityX = (int) velocityTracker.getXVelocity();    
166.            Log.e(TAG, "velocityX:"+velocityX);  
167.             
168.            if (velocityX > SNAP_VELOCITY && mCurScreen > 0) {    
169.                // Fling enough to move left    
170.                Log.e(TAG, "snap left"); 
171.                snapToScreen(mCurScreen - 1);    
172.            } else if (velocityX < -SNAP_VELOCITY    
173.                    && mCurScreen < getChildCount() - 1) {    
174.                // Fling enough to move right    
175.                Log.e(TAG, "snap right"); 
176.                snapToScreen(mCurScreen + 1);    
177.            } else {    
178.                snapToDestination();    
179.            }    
180.            if (mVelocityTracker != null) {    
181.                mVelocityTracker.recycle();    
182.                mVelocityTracker = null;    
183.            }    
184.            // }    
185.            mTouchState = TOUCH_STATE_REST;    
186.            break; 
187.        case MotionEvent.ACTION_CANCEL: 
188.            mTouchState = TOUCH_STATE_REST; 
189.            break; 
190.        } 
191.         
192.        return true; 
193.    } 
194.    @Override 
195.    public boolean onInterceptTouchEvent(MotionEvent ev) { 
196.        // TODO Auto-generated method stub 
197.        Log.e(TAG, "onInterceptTouchEvent-slop:"+mTouchSlop); 
198.         
199.        final int action = ev.getAction(); 
200.        if ((action == MotionEvent.ACTION_MOVE) &&  
201.                (mTouchState != TOUCH_STATE_REST)) { 
202.            return true; 
203.        } 
204.         
205.        final float x = ev.getX(); 
206.        final float y = ev.getY(); 
207.         
208.        switch (action) { 
209.        case MotionEvent.ACTION_MOVE: 
210.            final int xDiff = (int)Math.abs(mLastMotionX-x); 
211.            if (xDiff>mTouchSlop) { 
212.                mTouchState = TOUCH_STATE_SCROLLING; 
213.                 
214.            } 
215.            break; 
216.             
217.        case MotionEvent.ACTION_DOWN: 
218.            mLastMotionX = x; 
219.            mLastMotionY = y; 
220.            mTouchState = mScroller.isFinished()? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING; 
221.            break; 
222.             
223.        case MotionEvent.ACTION_CANCEL: 
224.        case MotionEvent.ACTION_UP: 
225.            mTouchState = TOUCH_STATE_REST; 
226.            break; 
227.        } 
228.         
229.        return mTouchState != TOUCH_STATE_REST; 
230.    } 
231.     
232.} 
 
 
测试程序布局:
 

 

view plaincopy to clipboardprint?
01.<?xml version="1.0" encoding="utf-8"?> 
02.<com.yao_guet.test.ScrollLayout 
03.  xmlns:android="http://schemas.android.com/apk/res/android" 
04.  android:id="@+id/ScrollLayoutTest" 
05.  android:layout_width="fill_parent" 
06.  android:layout_height="fill_parent"> 
07.<LinearLayout 
08.  android:background="#FF00" 
09.  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> 
 
 
源码下载:http://download.csdn.net/source/3246818


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Yao_GUET/archive/2011/05/04/6393962.aspx

 

你可能感兴趣的:(提取Launcher中的WorkSapce,可以左右滑动切换屏幕页面的类)