2011.06.08——— android 1.6 launcher研究之launcher的左右滑动
参考:http://blog.csdn.net/assassin4824/archive/2011/05/30/6454923.aspx
http://blog.sina.com.cn/s/blog_4d142b550100s1sx.html
http://blog.csdn.net/xiaoxiaobian3310903/archive/2011/05/24/6443250.aspx
http://www.ibm.com/developerworks/cn/opensource/os-cn-android-anmt2/

ScrollLayout.java

package com.lp;  import android.content.Context;  import android.graphics.Canvas;  import android.util.AttributeSet;  import android.util.Log;  import android.view.MotionEvent;  import android.view.VelocityTracker;  import android.view.View;  import android.view.ViewConfiguration;  import android.view.ViewGroup;  import android.widget.Scroller;  /**  * 仿Launcher中的WorkSapce,可以左右滑动切换屏幕的类  */  public class ScrollLayout extends ViewGroup {      private static final String TAG = "ScrollLayout";      private Scroller mScroller;      private VelocityTracker mVelocityTracker;            private int mCurScreen;      private int mDefaultScreen = 0;            private static final int TOUCH_STATE_REST = 0;      private static final int TOUCH_STATE_SCROLLING = 1;            private static final int SNAP_VELOCITY = 600;            private int mTouchState = TOUCH_STATE_REST;      private int mTouchSlop;      private float mLastMotionX;      private float mLastMotionY;      public ScrollLayout(Context context, AttributeSet attrs) {          this(context, attrs, 0);          // TODO Auto-generated constructor stub      }      public ScrollLayout(Context context, AttributeSet attrs, int defStyle) {          super(context, attrs, defStyle);          // TODO Auto-generated constructor stub          mScroller = new Scroller(context);          //默认显示第一屏        mCurScreen = mDefaultScreen;          mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();      }      @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;                      //很明显 0 - 320 | 320 - 640 | 640 - 960 ...(假设屏幕宽320)                }              }          }      }      @Override        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {             Log.e(TAG, "onMeasure");          super.onMeasure(widthMeasureSpec, heightMeasureSpec);                 final int width = MeasureSpec.getSize(widthMeasureSpec);             final int widthMode = MeasureSpec.getMode(widthMeasureSpec);             if (widthMode != MeasureSpec.EXACTLY) {                 throw new IllegalStateException("ScrollLayout only canmCurScreen run at EXACTLY mode!");           }                 final int heightMode = MeasureSpec.getMode(heightMeasureSpec);             if (heightMode != MeasureSpec.EXACTLY) {                 throw new IllegalStateException("ScrollLayout only can run at EXACTLY mode!");          }                 // The children are given the same width and height as the scrollLayout             final int count = getChildCount();             for (int i = 0; i < count; i++) {                 getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);             }             // Log.e(TAG, "moving to screen "+mCurScreen);            //x坐标 y坐标        //移动到第几屏        scrollTo(mCurScreen * width, 0);               }              /**      * According to the position of current layout      * scroll to the destination page.     * 判断滑动的位置      * 如果大于当前屏中间的位置 则换屏     * 否则 仍然是这个屏      * getScrollX x方向的偏移量     */         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();             //开始滚动            //x,y,x方向移动量,y方向移动量,滚动持续时间,负数往左滚            mScroller.startScroll(getScrollX(), 0,                       delta, 0, Math.abs(delta)*2);              mCurScreen = whichScreen;              invalidate();       // Redraw the layout          }      }            public void setToScreen(int whichScreen) {          whichScreen = Math.max(0, Math.min(whichScreen, getChildCount()-1));          mCurScreen = whichScreen;          scrollTo(whichScreen*getWidth(), 0);      }            public int getCurScreen() {          return mCurScreen;      }      //只有当前LAYOUT中的某个CHILD导致SCROLL发生滚动,才会致使自己的COMPUTESCROLL被调用    @Override      public void computeScroll() {          // TODO Auto-generated method stub          Log.e(TAG,"computeScroll");        //如果返回true,表示动画还没有结束        //因为前面startScroll,所以只有在startScroll完成时 才会为false        if (mScroller.computeScrollOffset()) {              Log.e(TAG, mScroller.getCurrX()+"======"+mScroller.getCurrY());            //产生了动画效果 每次滚动一点            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());             postInvalidate();          }      }      @Override      public boolean onTouchEvent(MotionEvent event) {          // TODO Auto-generated method stub          Log.e(TAG,"onTouchEvent start");        if (mVelocityTracker == null) {              mVelocityTracker = VelocityTracker.obtain();          }          mVelocityTracker.addMovement(event);                    final int action = event.getAction();          final float x = event.getX();          final float y = event.getY();                    switch (action) {          case MotionEvent.ACTION_DOWN:              Log.e(TAG, "event down! "+mScroller.isFinished());              //如果屏幕的滚动动画没有结束 你就按下了 就结束动画            if (!mScroller.isFinished()){                  mScroller.abortAnimation();              }              mLastMotionX = x;              break;                        case MotionEvent.ACTION_MOVE:              Log.e(TAG, "event move!");             //取得偏移量            int deltaX = (int)(mLastMotionX - x);             Log.e(TAG,"detaX: "+deltaX);            mLastMotionX = x;              //x方向的偏移量 y方向的偏移量            scrollBy(deltaX, 0);              break;                        case MotionEvent.ACTION_UP:              Log.e(TAG, "event : up");                 // if (mTouchState == TOUCH_STATE_SCROLLING) {                 final VelocityTracker velocityTracker = mVelocityTracker;                 velocityTracker.computeCurrentVelocity(1000);                 int velocityX = (int) velocityTracker.getXVelocity();                 Log.e(TAG, "velocityX:"+velocityX);                             if (velocityX > SNAP_VELOCITY && mCurScreen > 0) {                     // Fling enough to move left                     Log.e(TAG, "snap left");                  snapToScreen(mCurScreen - 1);                 } else if (velocityX < -SNAP_VELOCITY                         && mCurScreen < getChildCount() - 1) {                     // Fling enough to move right                     Log.e(TAG, "snap right");                  snapToScreen(mCurScreen + 1);                 } else {                     //一般都掉用这个                snapToDestination();                 }                 if (mVelocityTracker != null) {                     mVelocityTracker.recycle();                     mVelocityTracker = null;                 }                 // }                 mTouchState = TOUCH_STATE_REST;                 break;          case MotionEvent.ACTION_CANCEL:              mTouchState = TOUCH_STATE_REST;              break;          }                    return true;      }      //这个感觉没什么作用 不管true还是false 都是会执行onTouchEvent的 因为子view里面onTouchEvent返回false了    @Override      public boolean onInterceptTouchEvent(MotionEvent ev) {          // TODO Auto-generated method stub          Log.e(TAG, "onInterceptTouchEvent-slop:"+mTouchSlop);                    final int action = ev.getAction();          if ((action == MotionEvent.ACTION_MOVE) &&                   (mTouchState != TOUCH_STATE_REST)) {              return true;          }                    final float x = ev.getX();          final float y = ev.getY();                    switch (action) {          case MotionEvent.ACTION_MOVE:              Log.e(TAG,"onInterceptTouchEvent move");            final int xDiff = (int)Math.abs(mLastMotionX-x);              if (xDiff>mTouchSlop) {                  mTouchState = TOUCH_STATE_SCROLLING;                                }              break;                        case MotionEvent.ACTION_DOWN:              Log.e(TAG,"onInterceptTouchEvent down");            mLastMotionX = x;              mLastMotionY = y;              Log.e(TAG,mScroller.isFinished()+"");            mTouchState = mScroller.isFinished()? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;              break;                        case MotionEvent.ACTION_CANCEL:          case MotionEvent.ACTION_UP:              Log.e(TAG,"onInterceptTouchEvent up or cancel");            mTouchState = TOUCH_STATE_REST;              break;          }          Log.e(TAG,mTouchState+"===="+TOUCH_STATE_REST);        return mTouchState != TOUCH_STATE_REST;      }        }  



main.xml

<?xml version="1.0" encoding="utf-8"?>  <com.lp.ScrollLayout    xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/ScrollLayoutTest"    android:layout_width="fill_parent"    android:layout_height="fill_parent">  <LinearLayout    android:background="#FF00"    android:layout_width="fill_parent"    android:layout_height="fill_parent"></LinearLayout>      <FrameLayout    android:background="#F0F0"    android:layout_width="fill_parent"    android:layout_height="fill_parent"></FrameLayout>      <FrameLayout    android:background="#F00F"    android:layout_width="fill_parent"    android:layout_height="fill_parent">    </FrameLayout>      <LinearLayout    android:background="#FF00"    android:layout_width="fill_parent"    android:layout_height="fill_parent">    <Button      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:text="Button1" />    </LinearLayout>  <LinearLayout    android:layout_width="wrap_content"    android:layout_height="wrap_content">    <Button      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:text="Button2" />    </LinearLayout>  </com.lp.ScrollLayout>  

更多相关文章

  1. android滑动改变状态栏颜色及透明度
  2. android随意记
  3. android scrollview组件禁止滑动的方法
  4. Android(安卓)Design Support Library学习
  5. Android(安卓)中支持的几种传感器(加速度、陀螺仪、亮度、地磁、
  6. Android(安卓)Listview 隐藏滚动条
  7. Android类似于滚动通知栏信息播报功能
  8. Android(安卓)关于 OnScrollListener 事件顺序次数的简要分析
  9. ListView滑动变黑的处理

随机推荐

  1. 在MySQL中将数据从LATIN1转换为UTF8
  2. mysql升级的一些踩坑点
  3. JSON保存在数据库中并使用JQuery加载
  4. mysql忘记root密码做法
  5. Mongodb Mysql NoSQL的区别和联系
  6. 使用sharpdevelop连接MySQL
  7. 链接表和SQL SELECT查询
  8. 常见几种数据库中自增字段的设置方法(转)
  9. sql语句之union与join的区别
  10. MySql中有哪些存储引擎