Android自定义组件——四个方向滑动的菜单实现

时间:2023-03-09 08:31:36
Android自定义组件——四个方向滑动的菜单实现

今天无意中实现了一个四个方向滑动的菜单,感觉挺好玩,滑动起来很顺手,既然已经做出来了就贴出来让大家也玩弄一下。

一、效果演示

(说明:目前没有安装Android模拟器,制作的动态图片太卡了,就贴一下静态图片吧,实际效果可以下载源代码查看)

Android自定义组件——四个方向滑动的菜单实现

(向上滑动)

Android自定义组件——四个方向滑动的菜单实现

(向下滑动)

Android自定义组件——四个方向滑动的菜单实现

(向左滑动)

Android自定义组件——四个方向滑动的菜单实现

(向右滑动)

二、实现过程介绍

1、放置5个View (分别是上下左右中)

  1. @Override
  2. protected void onLayout(boolean changed, int l, int t, int r, int b) {
  3. mTopView.layout(0, -mViewHeight, mViewWidth, 0);
  4. mBottomView.layout(0, mViewHeight, mViewWidth, 2 * mViewHeight);
  5. mCenterView.layout(0, 0, mViewWidth, mViewHeight);
  6. mLeftView.layout(-mViewWidth, 0, 0, mViewHeight);
  7. mRightView.layout(mViewWidth, 0, 2 * mViewWidth, mViewHeight);
  8. }

Android自定义组件——四个方向滑动的菜单实现

转载请说明出处:http://blog.csdn.net/dawanganban

2、通过onTouchEvent事件来判断移动方向

  1. private float mDownY;
  2. private float mDownX;
  3. @Override
  4. public boolean onTouchEvent(MotionEvent event) {
  5. int disY;
  6. int disX;
  7. float eventY = event.getY();
  8. float eventX = event.getX();
  9. switch (event.getAction()) {
  10. case MotionEvent.ACTION_DOWN:
  11. mDownY = eventY;
  12. mDownX = eventX;
  13. break;
  14. case MotionEvent.ACTION_UP:
  15. disY = (int)(eventY - mDownY);
  16. disX = (int)(eventX - mDownX);
  17. if(Math.abs(disY) > Math.abs(disX)){
  18. if(Math.abs(disY) > MIN_VIEW_HEIGHT / 2){
  19. if(disY > 0){ //向下滑动
  20. Log.d(TAG, "TO_BOTTOM");
  21. changeToBottom();
  22. }else{        //向上滑动
  23. Log.d(TAG, "TO_TOP");
  24. changeToTop();
  25. }
  26. }
  27. }else{
  28. if(Math.abs(disX) > MIN_VIEW_WIDTH / 2){
  29. if(disX > 0){ //向右滑动
  30. Log.d(TAG, "TO_RIGHT");
  31. changeToRight();
  32. }else{        //向左滑动
  33. Log.d(TAG, "TO_LEFT");
  34. changeToLeft();
  35. }
  36. }
  37. }
  38. break;
  39. default:
  40. break;
  41. }
  42. return true;
  43. }

3、通过computerScroll()方法实现平滑移动

  1. @Override
  2. public void computeScroll() {
  3. super.computeScroll();
  4. if(mScroller.computeScrollOffset()){
  5. scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
  6. postInvalidate();
  7. }
  8. }

4、判断临界条件(否则会一直向一个方向滑动)

  1. int[] location = new int[2];
  2. mCenterView.getLocationOnScreen(location);
  3. if(location[1] >= mViewHeight - MIN_VIEW_HEIGHT * 2) return;

例如上面代码就是判断向下滑动的临界条件,location[1]代表中间View的y坐标(相对于屏幕)。

三、整个View的源码

  1. package com.example.testmx4update;
  2. import android.content.Context;
  3. import android.graphics.Color;
  4. import android.util.AttributeSet;
  5. import android.util.Log;
  6. import android.view.MotionEvent;
  7. import android.view.View;
  8. import android.view.ViewGroup;
  9. import android.widget.Scroller;
  10. /**
  11. * 自定义可以拖动的View
  12. * @author 阳光小强  http://blog.csdn.net/dawanganban
  13. *
  14. */
  15. public class MyCanPullView extends ViewGroup{
  16. private static final int MIN_VIEW_HEIGHT = 200;
  17. private static final int MIN_VIEW_WIDTH = 400;
  18. private static final String TAG = "TEST";
  19. private int mViewHeight;
  20. private int mViewWidth;
  21. private View mTopView;
  22. private View mBottomView;
  23. private View mCenterView;
  24. private View mLeftView;
  25. private View mRightView;
  26. private Scroller mScroller;
  27. public MyCanPullView(Context context, AttributeSet attrs) {
  28. super(context, attrs);
  29. initView(context);
  30. mScroller = new Scroller(context);
  31. }
  32. private void initView(Context context) {
  33. setTopView(context);
  34. setBottomView(context);
  35. setCenterView(context);
  36. setLeftView(context);
  37. setRightView(context);
  38. }
  39. private float mDownY;
  40. private float mDownX;
  41. @Override
  42. public boolean onTouchEvent(MotionEvent event) {
  43. int disY;
  44. int disX;
  45. float eventY = event.getY();
  46. float eventX = event.getX();
  47. switch (event.getAction()) {
  48. case MotionEvent.ACTION_DOWN:
  49. mDownY = eventY;
  50. mDownX = eventX;
  51. break;
  52. case MotionEvent.ACTION_UP:
  53. disY = (int)(eventY - mDownY);
  54. disX = (int)(eventX - mDownX);
  55. if(Math.abs(disY) > Math.abs(disX)){
  56. if(Math.abs(disY) > MIN_VIEW_HEIGHT / 2){
  57. if(disY > 0){ //向下滑动
  58. Log.d(TAG, "TO_BOTTOM");
  59. changeToBottom();
  60. }else{        //向上滑动
  61. Log.d(TAG, "TO_TOP");
  62. changeToTop();
  63. }
  64. }
  65. }else{
  66. if(Math.abs(disX) > MIN_VIEW_WIDTH / 2){
  67. if(disX > 0){ //向右滑动
  68. Log.d(TAG, "TO_RIGHT");
  69. changeToRight();
  70. }else{        //向左滑动
  71. Log.d(TAG, "TO_LEFT");
  72. changeToLeft();
  73. }
  74. }
  75. }
  76. break;
  77. default:
  78. break;
  79. }
  80. return true;
  81. }
  82. private void changeToBottom(){
  83. int[] location = new int[2];
  84. mCenterView.getLocationOnScreen(location);
  85. if(location[1] >= mViewHeight - MIN_VIEW_HEIGHT * 2) return;
  86. int dy = (int)(mViewHeight - MIN_VIEW_HEIGHT);
  87. mScroller.startScroll(0, getScrollY(), 0, -dy, 500);
  88. invalidate();
  89. }
  90. private void changeToTop(){
  91. int[] location = new int[2];
  92. mTopView.getLocationOnScreen(location);
  93. if(location[1] <= -mViewHeight - MIN_VIEW_HEIGHT / 2) return;
  94. int dy = (int)(mViewHeight - MIN_VIEW_HEIGHT);
  95. mScroller.startScroll(0, getScrollY(), 0, dy, 500);
  96. invalidate();
  97. }
  98. private void changeToRight(){
  99. int[] location = new int[2];
  100. mCenterView.getLocationOnScreen(location);
  101. if(location[0] >= mViewWidth - MIN_VIEW_WIDTH * 2) return;
  102. int dx = (int)(mViewWidth - MIN_VIEW_WIDTH);
  103. mScroller.startScroll(getScrollX(), 0, -dx, 0, 500);
  104. invalidate();
  105. }
  106. private void changeToLeft(){
  107. Log.d(TAG, "TO_LEFT");
  108. int[] location = new int[2];
  109. mLeftView.getLocationOnScreen(location);
  110. if(location[0] <= -mViewWidth - MIN_VIEW_WIDTH / 2) return;
  111. int dx = (int)(mViewWidth - MIN_VIEW_WIDTH);
  112. mScroller.startScroll(getScrollX(), 0, dx, 0, 500);
  113. invalidate();
  114. }
  115. @Override
  116. public void computeScroll() {
  117. super.computeScroll();
  118. if(mScroller.computeScrollOffset()){
  119. scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
  120. postInvalidate();
  121. }
  122. }
  123. @Override
  124. protected void onLayout(boolean changed, int l, int t, int r, int b) {
  125. mTopView.layout(0, -mViewHeight, mViewWidth, 0);
  126. mBottomView.layout(0, mViewHeight, mViewWidth, 2 * mViewHeight);
  127. mCenterView.layout(0, 0, mViewWidth, mViewHeight);
  128. mLeftView.layout(-mViewWidth, 0, 0, mViewHeight);
  129. mRightView.layout(mViewWidth, 0, 2 * mViewWidth, mViewHeight);
  130. }
  131. @Override
  132. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  133. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  134. //获取整个View的宽高
  135. mViewWidth = MeasureSpec.getSize(widthMeasureSpec);
  136. mViewHeight = MeasureSpec.getSize(heightMeasureSpec);
  137. }
  138. private void setTopView(Context context){
  139. View topButton = new View(context);
  140. topButton.setBackgroundColor(Color.RED);
  141. mTopView = topButton;
  142. this.addView(mTopView);
  143. }
  144. private void setBottomView(Context context){
  145. View bottomButton = new View(context);
  146. bottomButton.setBackgroundColor(Color.GREEN);
  147. mBottomView = bottomButton;
  148. this.addView(mBottomView);
  149. }
  150. private void setCenterView(Context context){
  151. View centerButton = new View(context);
  152. centerButton.setBackgroundColor(Color.WHITE);
  153. mCenterView = centerButton;
  154. this.addView(mCenterView);
  155. }
  156. private void setLeftView(Context context){
  157. View leftButton = new View(context);
  158. leftButton.setBackgroundColor(Color.BLUE);
  159. mLeftView = leftButton;
  160. this.addView(mLeftView);
  161. }
  162. private void setRightView(Context context){
  163. View rightButton = new View(context);
  164. rightButton.setBackgroundColor(Color.YELLOW);
  165. mRightView = rightButton;
  166. this.addView(mRightView);
  167. }
  168. }

获取全部源代码,请加群在群共享中获取(142979499)