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

一、效果演示

(说明:目前没有安装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. }

转载请说明出处: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)

Android自定义组件——四个方向滑动的菜单实现的更多相关文章

  1. Android自定义组件系列【15】——四个方向滑动的菜单实现

    今天无意中实现了一个四个方向滑动的菜单,感觉挺好玩,滑动起来很顺手,既然已经做出来了就贴出来让大家也玩弄一下. 一.效果演示 (说明:目前没有安装Android模拟器,制作的动态图片太卡了,就贴一下静 ...

  2. Android自定义组件系列【4】——自定义ViewGroup实现双侧滑动

    在上一篇文章<Android自定义组件系列[3]--自定义ViewGroup实现侧滑>中实现了仿Facebook和人人网的侧滑效果,这一篇我们将接着上一篇来实现双面滑动的效果. 1.布局示 ...

  3. Android自定义组件系列【7】——进阶实践(4)

    上一篇<Android自定义组件系列[6]--进阶实践(3)>中补充了关于Android中事件分发的过程知识,这一篇我们接着来分析任老师的<可下拉的PinnedHeaderExpan ...

  4. Android自定义视图四:定制onMeasure强制显示为方形

    这个系列是老外写的,干货!翻译出来一起学习.如有不妥,不吝赐教! Android自定义视图一:扩展现有的视图,添加新的XML属性 Android自定义视图二:如何绘制内容 Android自定义视图三: ...

  5. Android自定义组件之自动换行及宽度自适应View:WordWrapView

    目的: 自定义一个ViewGroup,里面的子view都是TextView,每个子view  TextView的宽度随内容自适应且每行的子View的个数自适应,并可以自动换行 一:效果图 二:代码 整 ...

  6. Android自定义组件系列【5】——进阶实践(2)

    上一篇<Android自定义组件系列[5]--进阶实践(1)>中对任老师的<可下拉的PinnedHeaderExpandableListView的实现>前一部分进行了实现,这一 ...

  7. Android自定义组件系列【6】——进阶实践(3)

    上一篇<Android自定义组件系列[5]--进阶实践(2)>继续对任老师的<可下拉的PinnedHeaderExpandableListView的实现>进行了分析,这一篇计划 ...

  8. Android自定义组件系列【3】——自定义ViewGroup实现侧滑

    有关自定义ViewGroup的文章已经很多了,我为什么写这篇文章,对于初学者或者对自定义组件比较生疏的朋友虽然可以拿来主义的用了,但是要一步一步的实现和了解其中的过程和原理才能真真脱离别人的代码,举一 ...

  9. Android 自定义组件之如何实现自定义组件

    参考链接:http://blog.csdn.net/jjwwmlp456/article/details/41076699 简介 Android提供了用于构建UI的强大的组件模型.两个基类:View和 ...

随机推荐

  1. CI框架 -- 核心文件 之 Benchmark.php

    Benchmark.php文件中定义的CI_Benchmark类可以让你标记点,并计算它们之间的时间差.还可以显示内存消耗. Benchmarking类库,它是被系统自动被加载的,不需要手工加载 cl ...

  2. 详解Paste deploy

    原创作品,转载注明本文出处:http://www.cnblogs.com/Security-Darren/p/4087587.html 谈到WSGI,就免不了要了解paste,其中paste depl ...

  3. jquery 插件和后台模板搜集

    弹框 alert confirmhttp://www.jq22.com/jquery-info2607 jQuery表格排序筛选插件http://www.jq22.com/jquery-info880 ...

  4. VMware克隆虚拟机后无法启动网卡

    最简单的办法: 修改这个文件:/etc/udev/rules.d/70_persistent-net.rules 把eth1修改为eth0,记下里面的mac地址 修改/etc/sysconfig/ne ...

  5. 每天一个linux命令:traceroute命令

    通过traceroute我们可以知道信息从你的计算机到互联网另一端的主机是走的什么路径.当然每次数据包由某一同样的出发点(source)到达某一同样的目的地(destination)走的路径可能会不一 ...

  6. Java反射 Introspector

    一.解释 Introspector  内省,自我检查. 位于java中的java.beans包中,其原文说明文为: The Introspector class provides a standard ...

  7. 深入理解Java虚拟机(一)

    一.运行时数据区域 ​ 1.程序计数器: 当前线程执行字节码的行号指示器(通过改变计数器的值来选择下条需要执行的字节码指令) 每个线程有独立的程序计数器(线程私有,为了切换线程时能恢复到挣钱的执行位置 ...

  8. 怎么用ABBYY重组PDF文档

    ABBYY PDF Transformer+是一款可创建.编辑以及将PDF文件转换为其他可编辑格式的通用工具,除此之外,还可以使用ABBYY PDF Transformer+重新组织PDF文档,如在文 ...

  9. 16个非常酷的jQuery插件

    摘要: 下面所有的插件有很大的功能,我相信大多数会帮助你即将到来的项目.借助他们可以使你的网站更加绚丽多彩. Lens Flare in JavaScript 这个jQuery插件可以帮助你处理图片, ...

  10. (翻译)2016美国数学建模MCM F题(政策)翻译:难民移民政策建模

    PROBLEM F:Modeling Refugee Immigration Policies With hundreds of thousands of refugees moving across ...