• 实现左右屏切换


     http://blog.csdn.net/sharetop/article/details/6313654

    其实要实现这个效果在Android中并非难事,因为官方的Launcher已经有现成的源代码放在那儿了,就是那个Workspace.java。大家可以去http://android.git.kernel.org/ 下载。

    而我们要做的事情就是分析它并精简它(毕竟我们只是打算左右滑动罢了,并不需要能创建快捷方式文件夹之类的东西,更不需要在上面拖放图标)。

    1. public class Workspace extends ViewGroup   
    2.  implements DropTarget, DragSource, DragScroller {  
    3.   
    4. }  

    因此,不管是Drop还是Drag,统统不需要了:

    1. public class Workspace extends ViewGroup {  
    2.   
    3. }  

    同时,把那些个接口所要求实现的方法,以及那些与Drag/Drop相关的成员变量都去掉吧。
    看看我精简后剩下什么成员变量:

    1. private static final int INVALID_SCREEN = -1;  
    2.   
    3. private int mDefaultScreen;  
    4.   
    5. private boolean mFirstLayout = true;  
    6.   
    7. private int mCurrentScreen;  
    8. private int mNextScreen = INVALID_SCREEN;  
    9. private Scroller mScroller;  
    10.   
    11.   
    12. private float mLastMotionX;  
    13. private float mLastMotionY;  
    14.   
    15. private final static int TOUCH_STATE_REST = 0;  
    16. private final static int TOUCH_STATE_SCROLLING = 1;  
    17.   
    18. private int mTouchState = TOUCH_STATE_REST;  
    19.   
    20. private int mTouchSlop;  


    以上足矣。

    然后在Eclipse中会有大量的错误,没关系,删吧。

    addView 是用来在代码中添加新的子view的方法,不需要,我们只需要在layout xml中直接指定就好了。
    getOpenFolder/getOpenFolders 文件夹相关的,当然不需要了。
    addInCurrentScreen/addWidget 都没什么用处了,可以删掉。
    与Cell相关的那些也可以删掉。

    因为我们的代码不能直接访问mScrollX,所以需要换成getScrollX()。这一点是需要特别注意的。

    看看我精简后都剩下些什么方法:


    最后只要不报错,就OK了。

    我们来分析一下几个关键的方法,其一是 onTouchEvent:

    1. @Override  
    2. public boolean onTouchEvent(MotionEvent ev) {  
    3.      
    4.   
    5.     final int action = ev.getAction();  
    6.     final float x = ev.getX();  
    7.   
    8.     switch (action) {  
    9.     case MotionEvent.ACTION_DOWN:  
    10.   
    11.         if (!mScroller.isFinished()) {  
    12.             mScroller.abortAnimation();  
    13.         }  
    14.   
    15.         // Remember where the motion event started   
    16.         mLastMotionX = x;  
    17.         break;  
    18.     case MotionEvent.ACTION_MOVE:  
    19.  //跟着手指拖动屏幕的处理。   
    20.         if (mTouchState == TOUCH_STATE_SCROLLING) {  
    21.             // Scroll to follow the motion event   
    22.             final int deltaX = (int) (mLastMotionX - x);  
    23.             mLastMotionX = x;  
    24.              
    25.             if (deltaX < 0) {  
    26.                 if (getScrollX() > 0) {  
    27.                  scrollBy(Math.max(-1*getScrollX(), deltaX), 0);                          
    28.                 }  
    29.             } else if (deltaX > 0) {  
    30.                 final int availableToScroll = getChildAt(getChildCount() - 1).getRight() -  
    31.                         getScrollX() - getWidth();  
    32.                 if (availableToScroll > 0) {  
    33.                  scrollBy(Math.min(availableToScroll, deltaX), 0);  
    34.                 }  
    35.             }  
    36.         }  
    37.         break;  
    38.     case MotionEvent.ACTION_UP:  
    39.  //抬起手指后,切换屏幕的处理   
    40.         if (mTouchState == TOUCH_STATE_SCROLLING) {  
    41.          snapToDestination();  
    42.         }  
    43.         mTouchState = TOUCH_STATE_REST;  
    44.         break;  
    45.     case MotionEvent.ACTION_CANCEL:  
    46.         mTouchState = TOUCH_STATE_REST;  
    47.     }  
    48.   
    49.     return true;  
    50. }  


    其二 snapToDestination和snapToScreen:

    1.   private void snapToDestination() {  
    2. //计算应该去哪个屏   
    3.        final int screenWidth = getWidth();  
    4.        final int whichScreen = (getScrollX() + (screenWidth / 2)) / screenWidth;  
    5. //切换   
    6.        snapToScreen(whichScreen);  
    7.    }  
    8.   
    9.    void snapToScreen(int whichScreen) {  
    10.        if (!mScroller.isFinished()) return;  
    11.   
    12.        whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));  
    13.        boolean changingScreens = whichScreen != mCurrentScreen;  
    14.          
    15.        mNextScreen = whichScreen;  
    16.          
    17.        View focusedChild = getFocusedChild();  
    18.        if (focusedChild != null && changingScreens && focusedChild == getChildAt(mCurrentScreen)) {  
    19.            focusedChild.clearFocus();  
    20.        }  
    21.   
    22.        //让mScroller启动滚动   
    23.        final int cx = getScrollX();  
    24.        final int newX = whichScreen * getWidth();  
    25.        final int delta = newX - cx;  
    26.        mScroller.startScroll(cx, 0, delta, 0, Math.abs(delta) * 4);  
    27.        invalidate();  
    28.    }  

    其三 computeScroll,让Workspace滚动到合适的位置:

    1. @Override  
    2. public void computeScroll() {  
    3.     if (mScroller.computeScrollOffset()) {  
    4.         scrollTo(mScroller.getCurrX(),mScroller.getCurrY());  
    5.         postInvalidate();  
    6.     } else if (mNextScreen != INVALID_SCREEN) {  
    7.         mCurrentScreen = Math.max(0, Math.min(mNextScreen, getChildCount() - 1));  
    8.         mNextScreen = INVALID_SCREEN;              
    9.     }  
    10.       
    11. }  

    基本上就是这些了,其它方法都是辅助的,很好理解。

    其实有一个问题,我们发现UCWeb主页下面有三个点指示当前所处的位置,这个指示器我的想法是可以放在Workspace外面来做,利用Workspace当前的mCurrentScreen值显示出当前正处于哪个屏。

    给出我的layout xml描述:

    1.  <cn.sharetop.demo.ui.Workspace  
    2.   android:id="@id/friends_switcher"  
    3.   android:layout_width="fill_parent"   
    4.   android:layout_height="640.0dip"   
    5.   android:layout_weight="1.0"  
    6.   xmessenger:defaultScreen="0"  
    7.   >  
    8.   <include layout="@layout/screen1" />  
    9.   <include layout="@layout/screen2" />  
    10.     
    11.  </cn.sharetop.demo.ui.Workspace>  
    12. <TextView   
    13.   android:layout_width="fill_parent"   
    14.   android:layout_height="wrap_content"   
    15.   android:textColor="#000000"   
    16.   android:background="@android:color/transparent"   
    17.   android:gravity="center"   
    18.   android:text="[1]2" />  

    就这样了。这个分页指示器就留给你自己去发挥了。

  • 相关阅读:
    oracle中xhost报错
    cronolog切割apache和tomcat日志
    rsync配置和同步数据
    Jenkins+GitHub+maven
    Git只获取部分目录的内容
    git命令综合
    tomcat(不仅仅是tomcat)通过熵池解决在linux启动应用慢
    iptables之ipset集群工具
    Python中yield表达式的使用
    对于python中出现UnicodeDecodeError问题的解决方案
  • 原文地址:https://www.cnblogs.com/greywolf/p/2831398.html
Copyright © 2020-2023  润新知