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

jopen 13年前
     <p>          <span style="font-size:16px;">下面的这个例子也是从网上找来的,不是自己写的,一直想学习下,但是一直没有写,以前也研究研究的是launcher的页面跳转,</span><a style="text-align:left;line-height:30px;font-family:'Microsoft YaHei';color:#666666;text-decoration:none;" title="launcher修改--左右滑动屏幕切换源码追踪" href="/misc/goto?guid=4959500739954799649"><span style="font-size:16px;">launcher修改--左右滑动屏幕切换源码追踪</span></a><span style="font-size:16px;">说实话,那个代码有点复杂,所以理解的也不是很透彻。看到这个例子,比较简单些,再这里学习下:</span></p>    <p><span style="font-size:16px;">       首先,看下效果图吧:虽然很花哨,都是背景图片。</span></p>    <p><span style="font-size:16px;"><img title="Android 页面滑动切换(类Launcher滑动屏幕实现)" border="0" alt="Android 页面滑动切换(类Launcher滑动屏幕实现)" src="https://simg.open-open.com/show/22ef892b42e3f3a0a78ff1250feadd81.jpg" width="485" height="710" /><br /> </span></p>    <p><span style="font-size:16px;">       看下他的布局文件:</span></p>    <p></p>    <pre class="brush:xml; toolbar: true; auto-links: false;"><?xml version="1.0" encoding="utf-8"?>     <RelativeLayout   android:layout_width="fill_parent"   android:layout_height="fill_parent"     xmlns:android="http://schemas.android.com/apk/res/android">         <com.genius.scroll.MyScrollLayout        xmlns:android="http://schemas.android.com/apk/res/android"        android:id="@+id/ScrollLayout"        android:layout_width="fill_parent"        android:layout_height="fill_parent">          <FrameLayout         android:background="@drawable/guide01"         android:layout_width="fill_parent"         android:layout_height="fill_parent">    </FrameLayout>            <FrameLayout         android:background="@drawable/guide02"         android:layout_width="fill_parent"         android:layout_height="fill_parent">    </FrameLayout>               <FrameLayout          android:background="@drawable/guide03"          android:layout_width="fill_parent"         android:layout_height="fill_parent">          </FrameLayout>           <FrameLayout         android:background="@drawable/guide04"         android:layout_width="fill_parent"         android:layout_height="fill_parent">        </FrameLayout>           <FrameLayout         android:background="@drawable/guide05"         android:layout_width="fill_parent"         android:layout_height="fill_parent">        </FrameLayout>            </com.genius.scroll.MyScrollLayout>      <LinearLayout       android:orientation="horizontal"       android:id="@+id/llayout"       android:layout_width="wrap_content"       android:layout_height="wrap_content"       android:layout_marginBottom="24.0dip"       android:layout_alignParentBottom="true"       android:layout_centerHorizontal="true">              <ImageView android:clickable="true"            android:padding="15.0dip"           android:layout_gravity="center_vertical"           android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:src="@drawable/guide_round" />         <ImageView android:clickable="true"            android:padding="15.0dip"            android:layout_gravity="center_vertical"           android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:src="@drawable/guide_round" />         <ImageView android:clickable="true"            android:padding="15.0dip"            android:layout_gravity="center_vertical"           android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:src="@drawable/guide_round" />         <ImageView android:clickable="true"            android:padding="15.0dip"            android:layout_gravity="center_vertical"           android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:src="@drawable/guide_round" />         <ImageView android:clickable="true"            android:padding="15.0dip"            android:layout_gravity="center_vertical"           android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:src="@drawable/guide_round" />     </LinearLayout>    </RelativeLayout></pre>    <br />            <span style="font-size:16px;"> 底部的LinearLayout是放了5个按钮,上面使用到了一个自定义的控件:MyScrollLayout下面再看下这个自定义控件:里面使用frameLayout放了5张图片。</span>    <p></p>    <p></p>    <pre class="brush:java; toolbar: true; auto-links: false;">public class MyScrollLayout extends ViewGroup{      private static final String TAG = "ScrollLayout";           private VelocityTracker mVelocityTracker;     // 用于判断甩动手势         private static final int SNAP_VELOCITY = 600;             private Scroller  mScroller;      // 滑动控制器      private int mCurScreen;                private int mDefaultScreen = 0;                private float mLastMotionX;                 private OnViewChangeListener mOnViewChangeListener;    public MyScrollLayout(Context context) {   super(context);   init(context);  }   public MyScrollLayout(Context context, AttributeSet attrs) {   super(context, attrs);   init(context);  }   public MyScrollLayout(Context context, AttributeSet attrs, int defStyle) {   super(context, attrs, defStyle);    init(context);  }   private void init(Context context)  {   mCurScreen = mDefaultScreen;                        mScroller = new Scroller(context);        }   @Override  protected void onLayout(boolean changed, int l, int t, int r, int b) {   // TODO Auto-generated method stub      if (changed) {                  int childLeft = 0;                  final int childCount = getChildCount();                                   for (int i=0; i<childCount; i++) {                      final View childView = getChildAt(i);                      if (childView.getVisibility() != View.GONE) {                          final int childWidth = childView.getMeasuredWidth();                          childView.layout(childLeft, 0,                                   childLeft+childWidth, childView.getMeasuredHeight());                          childLeft += childWidth;                      }                  }              }      }   @Override  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {   // TODO Auto-generated method stub   super.onMeasure(widthMeasureSpec, heightMeasureSpec);     final int width = MeasureSpec.getSize(widthMeasureSpec);             final int widthMode = MeasureSpec.getMode(widthMeasureSpec);                final int count = getChildCount();                for (int i = 0; i < count; i++) {                    getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);                }                         scrollTo(mCurScreen * width, 0);    }    public void snapToDestination() {              final int screenWidth = getWidth();              final int destScreen = (getScrollX()+ screenWidth/2)/screenWidth;              snapToScreen(destScreen);       }       public void snapToScreen(int whichScreen) {               // get the valid layout page              whichScreen = Math.max(0, Math.min(whichScreen, getChildCount()-1));              if (getScrollX() != (whichScreen*getWidth())) {                                   final int delta = whichScreen*getWidth()-getScrollX();                         mScroller.startScroll(getScrollX(), 0,                           delta, 0, Math.abs(delta)*2);                           mCurScreen = whichScreen;                  invalidate();       // Redraw the layout                               if (mOnViewChangeListener != null)              {               mOnViewChangeListener.OnViewChange(mCurScreen);              }          }          }       @Override  public void computeScroll() {   // TODO Auto-generated method stub   if (mScroller.computeScrollOffset()) {                 scrollTo(mScroller.getCurrX(), mScroller.getCurrY());               postInvalidate();             }     }   @Override  public boolean onTouchEvent(MotionEvent event) {   // TODO Auto-generated method stub                                  final int action = event.getAction();              final float x = event.getX();              final float y = event.getY();                           switch (action) {              case MotionEvent.ACTION_DOWN:                        Log.i("", "onTouchEvent  ACTION_DOWN");                       if (mVelocityTracker == null) {                    mVelocityTracker = VelocityTracker.obtain();                    mVelocityTracker.addMovement(event);         }                        if (!mScroller.isFinished()){                      mScroller.abortAnimation();                  }                              mLastMotionX = x;                          break;                               case MotionEvent.ACTION_MOVE:               int deltaX = (int)(mLastMotionX - x);                         if (IsCanMove(deltaX)){            if (mVelocityTracker != null){                  mVelocityTracker.addMovement(event);               }                   mLastMotionX = x;                     scrollBy(deltaX, 0);              }                    break;                               case MotionEvent.ACTION_UP:                            int velocityX = 0;              if (mVelocityTracker != null){               mVelocityTracker.addMovement(event);                mVelocityTracker.computeCurrentVelocity(1000);                 velocityX = (int) mVelocityTracker.getXVelocity();              }                                               if (velocityX > SNAP_VELOCITY && mCurScreen > 0) {                               Log.e(TAG, "snap left");                      snapToScreen(mCurScreen - 1);                     } else if (velocityX < -SNAP_VELOCITY                             && mCurScreen < getChildCount() - 1) {                             Log.e(TAG, "snap right");                      snapToScreen(mCurScreen + 1);                     } else {                         snapToDestination();                     }                                              if (mVelocityTracker != null) {                         mVelocityTracker.recycle();                         mVelocityTracker = null;                     }                     break;                }                           return true;      }   private boolean IsCanMove(int deltaX)  {   if (getScrollX() <= 0 && deltaX < 0 ){    return false;   }    if  (getScrollX() >=  (getChildCount() - 1) * getWidth() && deltaX > 0){    return false;   }     return true;  }    public void SetOnViewChangeListener(OnViewChangeListener listener)  {   mOnViewChangeListener = listener;  } }</pre>    <br />    <span style="font-size:16px;">首先注意,他继承了ViewGroup类,在这里面主要重写了onMeasure()、onTouchEvent()等方法,在这里使用了一个自定义的接口private OnViewChangeListener mOnViewChangeListener。看下它的定义:</span>    <p></p>    <p></p>    <pre class="brush:java; toolbar: true; auto-links: false;">public interface OnViewChangeListener {  public void OnViewChange(int view); }</pre>    <br />    <span style="font-size:16px;">这个接口里之定义了一个回调方法:OnViewChange()这个方法的具体实现,是在主Activity中:</span>    <p></p>    <p></p>    <pre class="brush:java; toolbar: true; auto-links: false;">public class SwitchViewDemoActivity extends Activity implements OnViewChangeListener, OnClickListener{     /** Called when the activity is first created. */   private MyScrollLayout mScrollLayout;   private ImageView[] mImageViews;   private int mViewCount;   private int mCurSel;       @Override     public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.main);                 init();     }          private void init()     {      mScrollLayout = (MyScrollLayout) findViewById(R.id.ScrollLayout);        LinearLayout linearLayout = (LinearLayout) findViewById(R.id.llayout);          mViewCount = mScrollLayout.getChildCount();      mImageViews = new ImageView[mViewCount];          for(int i = 0; i < mViewCount; i++)     {       mImageViews[i] = (ImageView) linearLayout.getChildAt(i);       mImageViews[i].setEnabled(true);       mImageViews[i].setOnClickListener(this);       mImageViews[i].setTag(i);      }           mCurSel = 0;      mImageViews[mCurSel].setEnabled(false);           mScrollLayout.SetOnViewChangeListener(this);     }      private void setCurPoint(int index)     {      if (index < 0 || index > mViewCount - 1 || mCurSel == index)     {       return ;      }           mImageViews[mCurSel].setEnabled(true);      mImageViews[index].setEnabled(false);           mCurSel = index;     }      @Override  public void OnViewChange(int view) {   // TODO Auto-generated method stub   setCurPoint(view);  }   @Override  public void onClick(View v) {   // TODO Auto-generated method stub   int pos = (Integer)(v.getTag());   setCurPoint(pos);   mScrollLayout.snapToScreen(pos);  } }</pre>    <br />    <span style="font-size:16px;">这个OnViewChange()方法,主要调用了setCurPoint()方法,就是完成界面的跳转。在MyScrollLayout中的snapToScreen()方法中就是典型的回调方法:</span>    <p></p>    <p></p>    <pre class="brush:java; toolbar: true; auto-links: false;">public void snapToScreen(int whichScreen) {               // get the valid layout page              whichScreen = Math.max(0, Math.min(whichScreen, getChildCount()-1));              if (getScrollX() != (whichScreen*getWidth())) {                                   final int delta = whichScreen*getWidth()-getScrollX();                         mScroller.startScroll(getScrollX(), 0,                           delta, 0, Math.abs(delta)*2);                           mCurScreen = whichScreen;                  invalidate();       // Redraw the layout                               if (mOnViewChangeListener != null)              {               mOnViewChangeListener.OnViewChange(mCurScreen);              }          }          } </pre>    <br />    <pre class="brush:java; toolbar: true; auto-links: false;">mOnViewChangeListener.OnViewChange(mCurScreen);</pre>    <br />    <p><span style="font-size:16px;">这句代码就是典型的回调。</span></p>    <p><span style="font-size:16px;">在MyScrollLayout的onTouchEvent()的方法里面是对触屏事件做出的响应:</span></p>    <p></p>    <pre class="brush:java; toolbar: true; auto-links: false;">final int action = event.getAction();              final float x = event.getX();              final float y = event.getY();                           switch (action) {              case MotionEvent.ACTION_DOWN:                        Log.i("", "onTouchEvent  ACTION_DOWN");                       if (mVelocityTracker == null) {                    mVelocityTracker = VelocityTracker.obtain();                    mVelocityTracker.addMovement(event);         }                        if (!mScroller.isFinished()){                      mScroller.abortAnimation();                  }                              mLastMotionX = x;                          break;                               case MotionEvent.ACTION_MOVE:               int deltaX = (int)(mLastMotionX - x);                         if (IsCanMove(deltaX)){            if (mVelocityTracker != null){                  mVelocityTracker.addMovement(event);               }                   mLastMotionX = x;                     scrollBy(deltaX, 0);              }                    break;                               case MotionEvent.ACTION_UP:                            int velocityX = 0;              if (mVelocityTracker != null){               mVelocityTracker.addMovement(event);                mVelocityTracker.computeCurrentVelocity(1000);                 velocityX = (int) mVelocityTracker.getXVelocity();              }                                               if (velocityX > SNAP_VELOCITY && mCurScreen > 0) {                               Log.e(TAG, "snap left");                      snapToScreen(mCurScreen - 1);                     } else if (velocityX < -SNAP_VELOCITY                             && mCurScreen < getChildCount() - 1) {                             Log.e(TAG, "snap right");                      snapToScreen(mCurScreen + 1);                     } else {                         snapToDestination();                     }                                              if (mVelocityTracker != null) {                         mVelocityTracker.recycle();                         mVelocityTracker = null;                     }                     break;                }            </pre>    <br /> 通过判断移动距离和移动方向做出不同的响应。    <p></p>    <p></p>    <p><span style="font-size:16px;"><br /> </span></p>    <p><span style="font-size:16px;">其他的代码都比较好懂了,有什么问题欢迎大家讨论,下面是代码的下载地址:</span></p>    <p><span style="font-size:16px;"><a href="/misc/goto?guid=4959500740040691286">http://download.csdn.net/detail/aomandeshangxiao/4017928</a><br /> </span></p>