Android 页面滑动切换(类Launcher滑动屏幕实现)

来源:互联网 发布:淘宝精仿 编辑:程序博客网 时间:2024/05/16 14:41

          下面的这个例子也是从网上找来的,不是自己写的,一直想学习下,但是一直没有写,以前也研究研究的是launcher的页面跳转,launcher修改--左右滑动屏幕切换源码追踪说实话,那个代码有点复杂,所以理解的也不是很透彻。看到这个例子,比较简单些,再这里学习下:

       首先,看下效果图吧:虽然很花哨,都是背景图片。

Android 页面滑动切换(类Launcher滑动屏幕实现)

       看下他的布局文件:

01<?xml version="1.0" encoding="utf-8"?>   
02<RelativeLayout
03    android:layout_width="fill_parent"
04    android:layout_height="fill_parent"
05    xmlns:android="http://schemas.android.com/apk/res/android">   
06    <com.genius.scroll.MyScrollLayout   
07      xmlns:android="http://schemas.android.com/apk/res/android"   
08      android:id="@+id/ScrollLayout"   
09      android:layout_width="fill_parent"   
10      android:layout_height="fill_parent">    
11      <FrameLayout   
12        android:background="@drawable/guide01"   
13        android:layout_width="fill_parent"   
14        android:layout_height="fill_parent">
15      </FrameLayout>       
16      <FrameLayout   
17        android:background="@drawable/guide02"   
18        android:layout_width="fill_parent"   
19        android:layout_height="fill_parent">
20      </FrameLayout>           
21      <FrameLayout    
22        android:background="@drawable/guide03"    
23        android:layout_width="fill_parent"   
24        android:layout_height="fill_parent">     
25      </FrameLayout>       
26      <FrameLayout   
27        android:background="@drawable/guide04"   
28        android:layout_width="fill_parent"   
29        android:layout_height="fill_parent">   
30      </FrameLayout>       
31      <FrameLayout   
32        android:background="@drawable/guide05"   
33        android:layout_width="fill_parent"   
34        android:layout_height="fill_parent">   
35      </FrameLayout>         
36    </com.genius.scroll.MyScrollLayout>
37    <LinearLayout
38        android:orientation="horizontal"
39        android:id="@+id/llayout"
40        android:layout_width="wrap_content"
41        android:layout_height="wrap_content"
42        android:layout_marginBottom="24.0dip"
43        android:layout_alignParentBottom="true"
44        android:layout_centerHorizontal="true">     
45        <ImageView android:clickable="true" 
46            android:padding="15.0dip"
47            android:layout_gravity="center_vertical"
48            android:layout_width="wrap_content"
49            android:layout_height="wrap_content"
50            android:src="@drawable/guide_round" />
51        <ImageView android:clickable="true" 
52            android:padding="15.0dip" 
53            android:layout_gravity="center_vertical"
54            android:layout_width="wrap_content"
55            android:layout_height="wrap_content"
56            android:src="@drawable/guide_round" />
57        <ImageView android:clickable="true" 
58            android:padding="15.0dip" 
59            android:layout_gravity="center_vertical"
60            android:layout_width="wrap_content"
61            android:layout_height="wrap_content"
62            android:src="@drawable/guide_round" />
63        <ImageView android:clickable="true" 
64            android:padding="15.0dip" 
65            android:layout_gravity="center_vertical"
66            android:layout_width="wrap_content"
67            android:layout_height="wrap_content"
68            android:src="@drawable/guide_round" />
69        <ImageView android:clickable="true" 
70            android:padding="15.0dip" 
71            android:layout_gravity="center_vertical"
72            android:layout_width="wrap_content"
73            android:layout_height="wrap_content"
74            android:src="@drawable/guide_round" />
75    </LinearLayout>  
76</RelativeLayout>

        底部的LinearLayout是放了5个按钮,上面使用到了一个自定义的控件:MyScrollLayout下面再看下这个自定义控件:里面使用frameLayout放了5张图片。

001public class MyScrollLayout extends ViewGroup{
002 
003    private static final String TAG = "ScrollLayout";     
004    private VelocityTracker mVelocityTracker;           // 用于判断甩动手势   
005    private static final int SNAP_VELOCITY = 600;       
006    private Scroller  mScroller;                        // 滑动控制器   
007    private int mCurScreen;                            
008    private int mDefaultScreen = 0;                         
009    private float mLastMotionX;      
010     
011    private OnViewChangeListener mOnViewChangeListener; 
012    public MyScrollLayout(Context context) {
013        super(context);
014        init(context);
015    }  
016    public MyScrollLayout(Context context, AttributeSet attrs) {
017        super(context, attrs);
018        init(context);
019    }  
020    public MyScrollLayout(Context context, AttributeSet attrs, int defStyle) {
021        super(context, attrs, defStyle);   
022        init(context);
023    }  
024    private void init(Context context)
025    {
026        mCurScreen = mDefaultScreen;                       
027        mScroller = new Scroller(context);     
028    }
029 
030    @Override
031    protected void onLayout(boolean changed, int l, int t, int r, int b) {
032        // TODO Auto-generated method stub     
033         if (changed) {   
034                int childLeft = 0;   
035                final int childCount = getChildCount();                    
036                for (int i=0; i<childCount; i++) {   
037                    final View childView = getChildAt(i);   
038                    if (childView.getVisibility() != View.GONE) {   
039                        final int childWidth = childView.getMeasuredWidth();   
040                        childView.layout(childLeft, 0,    
041                                childLeft+childWidth, childView.getMeasuredHeight());   
042                        childLeft += childWidth;   
043                    }   
044                }   
045            }   
046    }
047 
048    @Override
049    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
050        // TODO Auto-generated method stub
051        super.onMeasure(widthMeasureSpec, heightMeasureSpec);      
052        final int width = MeasureSpec.getSize(widthMeasureSpec);      
053        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);                   
054        final int count = getChildCount();      
055        for (int i = 0; i < count; i++) {      
056            getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);      
057        }               
058        scrollTo(mCurScreen * width, 0);       
059    }
060 
061     public void snapToDestination() {   
062            final int screenWidth = getWidth();   
063            final int destScreen = (getScrollX()+ screenWidth/2)/screenWidth;   
064            snapToScreen(destScreen);   
065     
066     
067     public void snapToScreen(int whichScreen) {       
068            // get the valid layout page   
069            whichScreen = Math.max(0, Math.min(whichScreen, getChildCount()-1));   
070            if (getScrollX() != (whichScreen*getWidth())) {                    
071                final int delta = whichScreen*getWidth()-getScrollX();   
072                        mScroller.startScroll(getScrollX(), 0,    
073                        delta, 0, Math.abs(delta)*2);              
074                mCurScreen = whichScreen;   
075                invalidate();       // Redraw the layout                   
076                if (mOnViewChangeListener != null)
077                {
078                    mOnViewChangeListener.OnViewChange(mCurScreen);
079                }
080            }   
081        }   
082 
083    @Override
084    public void computeScroll() {
085        // TODO Auto-generated method stub
086        if (mScroller.computeScrollOffset()) {   
087            scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); 
088            postInvalidate();   
089        }  
090    }
091 
092    @Override
093    public boolean onTouchEvent(MotionEvent event) {
094        // TODO Auto-generated method stub                         
095            final int action = event.getAction();   
096            final float x = event.getX();   
097            final float y = event.getY();                  
098            switch (action) {   
099            case MotionEvent.ACTION_DOWN:              
100                  Log.i("""onTouchEvent  ACTION_DOWN");                
101                if (mVelocityTracker == null) {   
102                        mVelocityTracker = VelocityTracker.obtain();   
103                        mVelocityTracker.addMovement(event);
104                }           
105                if (!mScroller.isFinished()){   
106                    mScroller.abortAnimation();   
107                }               
108                mLastMotionX = x;             
109                break;                     
110            case MotionEvent.ACTION_MOVE: 
111               int deltaX = (int)(mLastMotionX - x);              
112               if (IsCanMove(deltaX)){
113                 if (mVelocityTracker != null){
114                        mVelocityTracker.addMovement(event);
115                 }  
116                mLastMotionX = x;    
117                scrollBy(deltaX, 0);   
118               }      
119               break;                      
120            case MotionEvent.ACTION_UP:                    
121                int velocityX = 0;
122                if (mVelocityTracker != null){
123                    mVelocityTracker.addMovement(event);
124                    mVelocityTracker.computeCurrentVelocity(1000); 
125                    velocityX = (int) mVelocityTracker.getXVelocity();
126                }                                  
127                if (velocityX > SNAP_VELOCITY && mCurScreen > 0) {            
128                    Log.e(TAG, "snap left");   
129                    snapToScreen(mCurScreen - 1);      
130                else if (velocityX < -SNAP_VELOCITY      
131                        && mCurScreen < getChildCount() - 1) {          
132                    Log.e(TAG, "snap right");   
133                    snapToScreen(mCurScreen + 1);      
134                else {      
135                    snapToDestination();      
136                }                                  
137                if (mVelocityTracker != null) {      
138                    mVelocityTracker.recycle();      
139                    mVelocityTracker = null;      
140                }      
141                break;     
142            }                  
143            return true;   
144    }
145 
146    private boolean IsCanMove(int deltaX)
147    {
148        if (getScrollX() <= 0 && deltaX < 0 ){
149            return false;
150        }  
151        if  (getScrollX() >=  (getChildCount() - 1) * getWidth() && deltaX > 0){
152            return false;
153        }      
154        return true;
155    }
156     
157    public void SetOnViewChangeListener(OnViewChangeListener listener)
158    {
159        mOnViewChangeListener = listener;
160    }
161}

首先注意,他继承了ViewGroup类,在这里面主要重写了onMeasure()、onTouchEvent()等方法,在这里使用了一个自定义的接口private OnViewChangeListener mOnViewChangeListener。看下它的定义:

1public interface OnViewChangeListener {
2    public void OnViewChange(int view);
3}

这个接口里之定义了一个回调方法:OnViewChange()这个方法的具体实现,是在主Activity中:

01public class SwitchViewDemoActivity extends Activity implements OnViewChangeListener, OnClickListener{
02    /** Called when the activity is first created. */
03 
04    private MyScrollLayout mScrollLayout;  
05    private ImageView[] mImageViews;   
06    private int mViewCount;
07    private int mCurSel;
08     
09    @Override
10    public void onCreate(Bundle savedInstanceState) {
11        super.onCreate(savedInstanceState);
12        setContentView(R.layout.main);       
13        init();
14    }
15     
16    private void init()
17    {
18        mScrollLayout = (MyScrollLayout) findViewById(R.id.ScrollLayout);  
19        LinearLayout linearLayout = (LinearLayout) findViewById(R.id.llayout);     
20        mViewCount = mScrollLayout.getChildCount();
21        mImageViews = new ImageView[mViewCount];   
22        for(int i = 0; i < mViewCount; i++)      {
23            mImageViews[i] = (ImageView) linearLayout.getChildAt(i);
24            mImageViews[i].setEnabled(true);
25            mImageViews[i].setOnClickListener(this);
26            mImageViews[i].setTag(i);
27        }      
28        mCurSel = 0;
29        mImageViews[mCurSel].setEnabled(false);    
30        mScrollLayout.SetOnViewChangeListener(this);
31    }
32 
33    private void setCurPoint(int index)
34    {
35        if (index < 0 || index > mViewCount - 1 || mCurSel == index)      {
36            return ;
37        }      
38        mImageViews[mCurSel].setEnabled(true);
39        mImageViews[index].setEnabled(false);      
40        mCurSel = index;
41    }
42 
43    @Override
44    public void OnViewChange(int view) {
45        // TODO Auto-generated method stub
46        setCurPoint(view);
47    }
48 
49    @Override
50    public void onClick(View v) {
51        // TODO Auto-generated method stub
52        int pos = (Integer)(v.getTag());
53        setCurPoint(pos);
54        mScrollLayout.snapToScreen(pos);
55    }
56}

这个OnViewChange()方法,主要调用了setCurPoint()方法,就是完成界面的跳转。在MyScrollLayout中的snapToScreen()方法中就是典型的回调方法:

01public void snapToScreen(int whichScreen) {    
02            // get the valid layout page   
03            whichScreen = Math.max(0, Math.min(whichScreen, getChildCount()-1));   
04            if (getScrollX() != (whichScreen*getWidth())) {                    
05                final int delta = whichScreen*getWidth()-getScrollX();   
06                        mScroller.startScroll(getScrollX(), 0,    
07                        delta, 0, Math.abs(delta)*2);              
08                mCurScreen = whichScreen;   
09                invalidate();       // Redraw the layout                   
10                if (mOnViewChangeListener != null)
11                {
12                    mOnViewChangeListener.OnViewChange(mCurScreen);
13                }
14            }   
15        }

1mOnViewChangeListener.OnViewChange(mCurScreen);

这句代码就是典型的回调。

在MyScrollLayout的onTouchEvent()的方法里面是对触屏事件做出的响应:

01final int action = event.getAction();   
02            final float x = event.getX();   
03            final float y = event.getY();                  
04            switch (action) {   
05            case MotionEvent.ACTION_DOWN:              
06                  Log.i("""onTouchEvent  ACTION_DOWN");                
07                if (mVelocityTracker == null) {   
08                        mVelocityTracker = VelocityTracker.obtain();   
09                        mVelocityTracker.addMovement(event);
10                }           
11                if (!mScroller.isFinished()){   
12                    mScroller.abortAnimation();   
13                }               
14                mLastMotionX = x;             
15                break;                     
16            case MotionEvent.ACTION_MOVE: 
17               int deltaX = (int)(mLastMotionX - x);              
18               if (IsCanMove(deltaX)){
19                 if (mVelocityTracker != null){
20                        mVelocityTracker.addMovement(event);
21                 }  
22                mLastMotionX = x;    
23                scrollBy(deltaX, 0);   
24               }      
25               break;                      
26            case MotionEvent.ACTION_UP:                    
27                int velocityX = 0;
28                if (mVelocityTracker != null){
29                    mVelocityTracker.addMovement(event);
30                    mVelocityTracker.computeCurrentVelocity(1000); 
31                    velocityX = (int) mVelocityTracker.getXVelocity();
32                }                                  
33                if (velocityX > SNAP_VELOCITY && mCurScreen > 0) {            
34                    Log.e(TAG, "snap left");   
35                    snapToScreen(mCurScreen - 1);      
36                else if (velocityX < -SNAP_VELOCITY      
37                        && mCurScreen < getChildCount() - 1) {          
38                    Log.e(TAG, "snap right");   
39                    snapToScreen(mCurScreen + 1);      
40                else {      
41                    snapToDestination();      
42                }                                  
43                if (mVelocityTracker != null) {      
44                    mVelocityTracker.recycle();      
45                    mVelocityTracker = null;      
46                }      
47                break;     
48            }      

通过判断移动距离和移动方向做出不同的响应。


其他的代码都比较好懂了,有什么问题欢迎大家讨论,下面是代码的下载地址:

http://download.csdn.net/detail/aomandeshangxiao/4017928

原创粉丝点击