参考: 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

Java代码
  1. packagecom.lp;
  2. importandroid.content.Context;
  3. importandroid.graphics.Canvas;
  4. importandroid.util.AttributeSet;
  5. importandroid.util.Log;
  6. importandroid.view.MotionEvent;
  7. importandroid.view.VelocityTracker;
  8. importandroid.view.View;
  9. importandroid.view.ViewConfiguration;
  10. importandroid.view.ViewGroup;
  11. importandroid.widget.Scroller;
  12. /**
  13. *仿Launcher中的WorkSapce,可以左右滑动切换屏幕的类
  14. */
  15. publicclassScrollLayoutextendsViewGroup{
  16. privatestaticfinalStringTAG="ScrollLayout";
  17. privateScrollermScroller;
  18. privateVelocityTrackermVelocityTracker;
  19. privateintmCurScreen;
  20. privateintmDefaultScreen=0;
  21. privatestaticfinalintTOUCH_STATE_REST=0;
  22. privatestaticfinalintTOUCH_STATE_SCROLLING=1;
  23. privatestaticfinalintSNAP_VELOCITY=600;
  24. privateintmTouchState=TOUCH_STATE_REST;
  25. privateintmTouchSlop;
  26. privatefloatmLastMotionX;
  27. privatefloatmLastMotionY;
  28. publicScrollLayout(Contextcontext,AttributeSetattrs){
  29. this(context,attrs,0);
  30. //TODOAuto-generatedconstructorstub
  31. }
  32. publicScrollLayout(Contextcontext,AttributeSetattrs,intdefStyle){
  33. super(context,attrs,defStyle);
  34. //TODOAuto-generatedconstructorstub
  35. mScroller=newScroller(context);
  36. //默认显示第一屏
  37. mCurScreen=mDefaultScreen;
  38. mTouchSlop=ViewConfiguration.get(getContext()).getScaledTouchSlop();
  39. }
  40. @Override
  41. protectedvoidonLayout(booleanchanged,intl,intt,intr,intb){
  42. //TODOAuto-generatedmethodstub
  43. if(changed){
  44. intchildLeft=0;
  45. finalintchildCount=getChildCount();
  46. for(inti=0;i<childCount;i++){
  47. finalViewchildView=getChildAt(i);
  48. if(childView.getVisibility()!=View.GONE){
  49. finalintchildWidth=childView.getMeasuredWidth();
  50. childView.layout(childLeft,0,
  51. childLeft+childWidth,childView.getMeasuredHeight());
  52. childLeft+=childWidth;
  53. //很明显0-320|320-640|640-960...(假设屏幕宽320)
  54. }
  55. }
  56. }
  57. }
  58. @Override
  59. protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){
  60. Log.e(TAG,"onMeasure");
  61. super.onMeasure(widthMeasureSpec,heightMeasureSpec);
  62. finalintwidth=MeasureSpec.getSize(widthMeasureSpec);
  63. finalintwidthMode=MeasureSpec.getMode(widthMeasureSpec);
  64. if(widthMode!=MeasureSpec.EXACTLY){
  65. thrownewIllegalStateException("ScrollLayoutonlycanmCurScreenrunatEXACTLYmode!");
  66. }
  67. finalintheightMode=MeasureSpec.getMode(heightMeasureSpec);
  68. if(heightMode!=MeasureSpec.EXACTLY){
  69. thrownewIllegalStateException("ScrollLayoutonlycanrunatEXACTLYmode!");
  70. }
  71. //ThechildrenaregiventhesamewidthandheightasthescrollLayout
  72. finalintcount=getChildCount();
  73. for(inti=0;i<count;i++){
  74. getChildAt(i).measure(widthMeasureSpec,heightMeasureSpec);
  75. }
  76. //Log.e(TAG,"movingtoscreen"+mCurScreen);
  77. //x坐标y坐标
  78. //移动到第几屏
  79. scrollTo(mCurScreen*width,0);
  80. }
  81. /**
  82. *Accordingtothepositionofcurrentlayout
  83. *scrolltothedestinationpage.
  84. *判断滑动的位置
  85. *如果大于当前屏中间的位置则换屏
  86. *否则仍然是这个屏
  87. *getScrollXx方向的偏移量
  88. */
  89. publicvoidsnapToDestination(){
  90. finalintscreenWidth=getWidth();
  91. //判断
  92. finalintdestScreen=(getScrollX()+screenWidth/2)/screenWidth;
  93. snapToScreen(destScreen);
  94. }
  95. publicvoidsnapToScreen(intwhichScreen){
  96. //getthevalidlayoutpage
  97. whichScreen=Math.max(0,Math.min(whichScreen,getChildCount()-1));
  98. if(getScrollX()!=(whichScreen*getWidth())){
  99. finalintdelta=whichScreen*getWidth()-getScrollX();
  100. //开始滚动
  101. //x,y,x方向移动量,y方向移动量,滚动持续时间,负数往左滚
  102. mScroller.startScroll(getScrollX(),0,
  103. delta,0,Math.abs(delta)*2);
  104. mCurScreen=whichScreen;
  105. invalidate();//Redrawthelayout
  106. }
  107. }
  108. publicvoidsetToScreen(intwhichScreen){
  109. whichScreen=Math.max(0,Math.min(whichScreen,getChildCount()-1));
  110. mCurScreen=whichScreen;
  111. scrollTo(whichScreen*getWidth(),0);
  112. }
  113. publicintgetCurScreen(){
  114. returnmCurScreen;
  115. }
  116. //只有当前LAYOUT中的某个CHILD导致SCROLL发生滚动,才会致使自己的COMPUTESCROLL被调用
  117. @Override
  118. publicvoidcomputeScroll(){
  119. //TODOAuto-generatedmethodstub
  120. Log.e(TAG,"computeScroll");
  121. //如果返回true,表示动画还没有结束
  122. //因为前面startScroll,所以只有在startScroll完成时才会为false
  123. if(mScroller.computeScrollOffset()){
  124. Log.e(TAG,mScroller.getCurrX()+"======"+mScroller.getCurrY());
  125. //产生了动画效果每次滚动一点
  126. scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
  127. postInvalidate();
  128. }
  129. }
  130. @Override
  131. publicbooleanonTouchEvent(MotionEventevent){
  132. //TODOAuto-generatedmethodstub
  133. Log.e(TAG,"onTouchEventstart");
  134. if(mVelocityTracker==null){
  135. mVelocityTracker=VelocityTracker.obtain();
  136. }
  137. mVelocityTracker.addMovement(event);
  138. finalintaction=event.getAction();
  139. finalfloatx=event.getX();
  140. finalfloaty=event.getY();
  141. switch(action){
  142. caseMotionEvent.ACTION_DOWN:
  143. Log.e(TAG,"eventdown!"+mScroller.isFinished());
  144. //如果屏幕的滚动动画没有结束你就按下了就结束动画
  145. if(!mScroller.isFinished()){
  146. mScroller.abortAnimation();
  147. }
  148. mLastMotionX=x;
  149. break;
  150. caseMotionEvent.ACTION_MOVE:
  151. Log.e(TAG,"eventmove!");
  152. //取得偏移量
  153. intdeltaX=(int)(mLastMotionX-x);
  154. Log.e(TAG,"detaX:"+deltaX);
  155. mLastMotionX=x;
  156. //x方向的偏移量y方向的偏移量
  157. scrollBy(deltaX,0);
  158. break;
  159. caseMotionEvent.ACTION_UP:
  160. Log.e(TAG,"event:up");
  161. //if(mTouchState==TOUCH_STATE_SCROLLING){
  162. finalVelocityTrackervelocityTracker=mVelocityTracker;
  163. velocityTracker.computeCurrentVelocity(1000);
  164. intvelocityX=(int)velocityTracker.getXVelocity();
  165. Log.e(TAG,"velocityX:"+velocityX);
  166. if(velocityX>SNAP_VELOCITY&&mCurScreen>0){
  167. //Flingenoughtomoveleft
  168. Log.e(TAG,"snapleft");
  169. snapToScreen(mCurScreen-1);
  170. }elseif(velocityX<-SNAP_VELOCITY
  171. &&mCurScreen<getChildCount()-1){
  172. //Flingenoughtomoveright
  173. Log.e(TAG,"snapright");
  174. snapToScreen(mCurScreen+1);
  175. }else{
  176. //一般都掉用这个
  177. snapToDestination();
  178. }
  179. if(mVelocityTracker!=null){
  180. mVelocityTracker.recycle();
  181. mVelocityTracker=null;
  182. }
  183. //}
  184. mTouchState=TOUCH_STATE_REST;
  185. break;
  186. caseMotionEvent.ACTION_CANCEL:
  187. mTouchState=TOUCH_STATE_REST;
  188. break;
  189. }
  190. returntrue;
  191. }
  192. //这个感觉没什么作用不管true还是false都是会执行onTouchEvent的因为子view里面onTouchEvent返回false了
  193. @Override
  194. publicbooleanonInterceptTouchEvent(MotionEventev){
  195. //TODOAuto-generatedmethodstub
  196. Log.e(TAG,"onInterceptTouchEvent-slop:"+mTouchSlop);
  197. finalintaction=ev.getAction();
  198. if((action==MotionEvent.ACTION_MOVE)&&
  199. (mTouchState!=TOUCH_STATE_REST)){
  200. returntrue;
  201. }
  202. finalfloatx=ev.getX();
  203. finalfloaty=ev.getY();
  204. switch(action){
  205. caseMotionEvent.ACTION_MOVE:
  206. Log.e(TAG,"onInterceptTouchEventmove");
  207. finalintxDiff=(int)Math.abs(mLastMotionX-x);
  208. if(xDiff>mTouchSlop){
  209. mTouchState=TOUCH_STATE_SCROLLING;
  210. }
  211. break;
  212. caseMotionEvent.ACTION_DOWN:
  213. Log.e(TAG,"onInterceptTouchEventdown");
  214. mLastMotionX=x;
  215. mLastMotionY=y;
  216. Log.e(TAG,mScroller.isFinished()+"");
  217. mTouchState=mScroller.isFinished()?TOUCH_STATE_REST:TOUCH_STATE_SCROLLING;
  218. break;
  219. caseMotionEvent.ACTION_CANCEL:
  220. caseMotionEvent.ACTION_UP:
  221. Log.e(TAG,"onInterceptTouchEventuporcancel");
  222. mTouchState=TOUCH_STATE_REST;
  223. break;
  224. }
  225. Log.e(TAG,mTouchState+"===="+TOUCH_STATE_REST);
  226. returnmTouchState!=TOUCH_STATE_REST;
  227. }
  228. }



main.xml

Java代码
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <com.lp.ScrollLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:id="@+id/ScrollLayoutTest"
  5. android:layout_width="fill_parent"
  6. android:layout_height="fill_parent">
  7. <LinearLayout
  8. android:background="#FF00"
  9. android:layout_width="fill_parent"
  10. android:layout_height="fill_parent"></LinearLayout>
  11. <FrameLayout
  12. android:background="#F0F0"
  13. android:layout_width="fill_parent"
  14. android:layout_height="fill_parent"></FrameLayout>
  15. <FrameLayout
  16. android:background="#F00F"
  17. android:layout_width="fill_parent"
  18. android:layout_height="fill_parent">
  19. </FrameLayout>
  20. <LinearLayout
  21. android:background="#FF00"
  22. android:layout_width="fill_parent"
  23. android:layout_height="fill_parent">
  24. <Button
  25. android:layout_width="wrap_content"
  26. android:layout_height="wrap_content"
  27. android:text="Button1"/>
  28. </LinearLayout>
  29. <LinearLayout
  30. android:layout_width="wrap_content"
  31. android:layout_height="wrap_content">
  32. <Button
  33. android:layout_width="wrap_content"
  34. android:layout_height="wrap_content"
  35. android:text="Button2"/>
  36. </LinearLayout>
  37. </com.lp.ScrollLayout>

更多相关文章

  1. Android(安卓)Weekly Notes Issue #234
  2. android dialog和activity 改变出现消失的 动画样式
  3. android属性动画最简单使用
  4. 判断android手机屏幕方向的方法
  5. android Dialog底部弹出框、自定义Dialog非常实用
  6. android - 自定义Activity跳转效果
  7. android模拟器分辨率设置以及获得模拟器分辨率代码片段
  8. 使用 adb 命令向 Android(安卓)发送广播
  9. android dpi dp 和px之间的关系

随机推荐

  1. 使用百度地图SDK 这是之前版本 现在的sdk
  2. 基于 Android NDK 的学习之旅----- C调用
  3. Android的ActivityNotFoundException异常
  4. Android 多线程之 AsyncTask
  5. Android(安卓)-- Vibrator
  6. android 是什么
  7. Android的常见错误及解决办法
  8. Unity 与 Android (Android Studio)的交
  9. android中android:wight详解
  10. 横屏和竖屏切换不用销毁重新建立android: