触摸事件、侧滑菜单

触摸事件

 
侧滑菜单---
github-SlidingMenu
1.在ViewGroup中,让自己内容移动有以下三个方法个方法:
  • layout(l,t,r,b);
  • offsetTopAndBottom(offset)和offsetLeftAndRight(offset);
  • scrollTo和scrollBy方法;
注意:滚动的并不是viewgroup内容本身,而是它的矩形边框
 它是瞬间移动的
 
2.在自定义ViewGroup中一般不需要去实现onMeasure,
 我们去实现系统已有的ViewGroup,比如FrameLayout,
 它会帮我们区实现onMeasure方法
 
 
3.让view在一段时间内移动到某个位置
a.使用自定义动画(让view在一段时间内做某件事)
  
b.使用Scroller(模拟一个执行流程,)
 
layout会影响measure过的宽高
 
scrollTo理解
布局:
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. tools:context=".MainActivity">
  6. <com.ly.slidemenu.view.SlideMenu
  7. android:id="@+id/slideMenu"
  8. android:layout_width="match_parent"
  9. android:layout_height="match_parent">
  10. <!--菜单界面的布局-->
  11. <include layout="@layout/layout_menu"/>
  12. <!--主界面的布局-->
  13. <include layout="@layout/layout_main"/>
  14. </com.ly.slidemenu.view.SlideMenu>
  15. </RelativeLayout>
SlideMenu
  1. publicclassSlideMenuextendsFrameLayout{
  2. privateView menuView,mainView;
  3. privateint menuWidth =0;
  4. privateScroller scroller;
  5. publicSlideMenu(Context context,AttributeSet attrs){
  6. super(context, attrs);
  7. init();
  8. }
  9. publicSlideMenu(Context context){
  10. super(context);
  11. init();
  12. }
  13. privatevoid init(){
  14. scroller =newScroller(getContext());
  15. }
  16. /**
  17. * 当1级的子view全部加载完调用,可以用初始化子view的引用,view.inflate完后
  18. * 注意,这里无法获取子view的宽高
  19. */
  20. @Override
  21. protectedvoid onFinishInflate(){
  22. super.onFinishInflate();
  23. menuView = getChildAt(0);
  24. mainView = getChildAt(1);
  25. menuWidth = menuView.getLayoutParams().width;//可以通过这样获得
  26. }
  27. /**
  28. * widthMeasureSpec和heightMeasureSpec是系统测量SlideMenu时传入的参数,
  29. * 这2个参数测量出的宽高能让SlideMenu充满窗体,其实是正好等于屏幕宽高
  30. */
  31. //继承已有viewgroup就不需要这些了,相对布局也行,但是桢布局更快
  32. // @Override
  33. // protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  34. // super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  35. //
  36. // int measureSpec = MeasureSpec.makeMeasureSpec(menuWidth, MeasureSpec.EXACTLY);
  37. //
  38. // //测量所有子view的宽高
  39. // //通过getLayoutParams方法可以获取到布局文件中指定宽高
  40. // menuView.measure(measureSpec, heightMeasureSpec);
  41. // //直接使用SlideMenu的测量参数,因为它的宽高都是充满父窗体
  42. // mainView.measure(widthMeasureSpec, heightMeasureSpec);
  43. //
  44. // }
  45. //为了侧边栏可以上下滑动菜单,可以根据移动的值处理掉事件,其他情况下不处理,交给主页面
  46. @Override
  47. publicboolean onInterceptTouchEvent(MotionEvent ev){
  48. switch(ev.getAction()){
  49. caseMotionEvent.ACTION_DOWN:
  50. downX =(int) ev.getX();
  51. break;
  52. caseMotionEvent.ACTION_MOVE:
  53. int deltaX =(int)( ev.getX()- downX);
  54. if(Math.abs(deltaX)>8){
  55. returntrue;
  56. }
  57. break;
  58. }
  59. returnsuper.onInterceptTouchEvent(ev);
  60. // return super.onInterceptTouchEvent(ev);
  61. }
  62. /**
  63. * l: 当前子view的左边在父view的坐标系中的x坐标
  64. * t: 当前子view的顶边在父view的坐标系中的y坐标
  65. */
  66. @Override
  67. protectedvoid onLayout(boolean changed,int l,int t,int r,int b){
  68. // Log.e("MAIN", "L: "+l+" t: "+t +" r: "+r + " b: "+b);
  69. menuView.layout(-menuWidth,0,0, menuView.getMeasuredHeight());
  70. mainView.layout(0,0, r, b);
  71. }
  72. privateint downX;
  73. @Override
  74. publicboolean onTouchEvent(MotionEvent event){
  75. switch(event.getAction()){
  76. caseMotionEvent.ACTION_DOWN:
  77. downX =(int) event.getX();
  78. break;
  79. caseMotionEvent.ACTION_MOVE:
  80. int moveX =(int) event.getX();
  81. int deltaX =(int)( moveX- downX);
  82. int newScrollX = getScrollX()- deltaX;//移动的距离,每次移动都不一样,所以需要计算下新的
  83. if(newScrollX<-menuWidth)newScrollX =-menuWidth;
  84. if(newScrollX>0)newScrollX =0;
  85. Log.e("Main","scrollX: "+getScrollX());
  86. scrollTo(newScrollX,0);
  87. downX = moveX;
  88. break;
  89. caseMotionEvent.ACTION_UP:
  90. //1.使用自定义动画
  91. // ScrollAnimation scrollAnimation;
  92. // if(getScrollX()>-menuWidth/2){
  93. // //关闭菜单
  94. //// scrollTo(0, 0);
  95. // scrollAnimation = new ScrollAnimation(this, 0);
  96. // }else {
  97. // //打开菜单
  98. //// scrollTo(-menuWidth, 0);
  99. // scrollAnimation = new ScrollAnimation(this, -menuWidth);
  100. // }
  101. // startAnimation(scrollAnimation);
  102. //2.使用Scroller
  103. if(getScrollX()>-menuWidth/2){
  104. // //关闭菜单
  105. closeMenu();
  106. }else{
  107. //打开菜单
  108. openMenu();
  109. }
  110. break;
  111. }
  112. returntrue;
  113. }
  114. privatevoid closeMenu(){
  115. scroller.startScroll(getScrollX(),0,0-getScrollX(),0,400);//持续的时间
  116. invalidate();
  117. }
  118. privatevoid openMenu(){
  119. scroller.startScroll(getScrollX(),0,-menuWidth-getScrollX(),0,400);
  120. invalidate();
  121. }
  122. /**
  123. * Scroller不主动去调用这个方法
  124. * 而invalidate()可以掉这个方法
  125. * invalidate->draw->computeScroll
  126. */
  127. @Override
  128. publicvoid computeScroll(){
  129. super.computeScroll();
  130. if(scroller.computeScrollOffset()){//返回true,表示动画没结束
  131. scrollTo(scroller.getCurrX(),0);
  132. invalidate();
  133. }
  134. }
  135. /**
  136. * 切换菜单的开和关
  137. */
  138. publicvoid switchMenu(){
  139. if(getScrollX()==0){
  140. //需要打开
  141. openMenu();
  142. }else{
  143. //需要关闭
  144. closeMenu();
  145. }
  146. }
  147. }
ScrollAnimation
  1. /**
  2. * 让指定view在一段时间内scrollTo到指定位置
  3. * @author Administrator
  4. *
  5. */
  6. publicclassScrollAnimationextendsAnimation{
  7. privateView view;
  8. privateint targetScrollX;
  9. privateint startScrollX;
  10. privateint totalValue;
  11. publicScrollAnimation(View view,int targetScrollX){
  12. super();
  13. this.view = view;
  14. this.targetScrollX = targetScrollX;
  15. startScrollX = view.getScrollX();
  16. totalValue =this.targetScrollX - startScrollX;
  17. int time =Math.abs(totalValue);
  18. setDuration(time);
  19. }
  20. /**
  21. * 在指定的时间内一直执行该方法,直到动画结束
  22. * interpolatedTime:0-1 标识动画执行的进度或者百分比
  23. * time : 0 - 0.5 - 0.7 - 1
  24. * value: 10 - 60 - 80 - 110
  25. * 当前的值 = 起始值 + 总的差值*interpolatedTime
  26. */
  27. @Override
  28. protectedvoid applyTransformation(float interpolatedTime,
  29. Transformation t){
  30. super.applyTransformation(interpolatedTime, t);
  31. int currentScrollX =(int)(startScrollX + totalValue*interpolatedTime);
  32. view.scrollTo(currentScrollX,0);
  33. }
  34. }
MainActivity
  1. publicclassMainActivityextendsActivity{
  2. privateImageView btn_back;
  3. privateSlideMenu slideMenu;
  4. @Override
  5. protectedvoid onCreate(Bundle savedInstanceState){
  6. super.onCreate(savedInstanceState);
  7. requestWindowFeature(Window.FEATURE_NO_TITLE);
  8. setContentView(R.layout.activity_main);
  9. btn_back =(ImageView) findViewById(R.id.btn_back);
  10. slideMenu =(SlideMenu) findViewById(R.id.slideMenu);
  11. btn_back.setOnClickListener(newOnClickListener(){
  12. @Override
  13. publicvoid onClick(View v){
  14. slideMenu.switchMenu();
  15. }
  16. });
  17. }
  18. }
 





原文地址:https://www.cnblogs.com/sixrain/p/5041931.html