人人滑动式菜单

文章出处:http://blog.csdn.net/knlnzhao/article/details/7920766

http://www.eoeandroid.com/forum.php?mod=viewthread&tid=183314

最近发现有好多软件都采用了滑动式菜单的效果,例如人人,云中书城等等。这种效果给人以耳目一新的感觉,所以自己也特别想实现一个。由于鄙人才疏学浅,属于菜鸟级的人物,第一次想到的当然是在网上找相关的demo。百度过来谷歌过去,发现相关的demo少的可怜,只找到一个某位大牛jfeinstein10写的SlidingMenu库。欣喜之余,下载下来看看,发现真心麻烦啊,于是下定决心自己写一个。

实现SlidingMenu的方法如下:

自定义ViewGroup类ViewFlipper如下:

[html]  view plain copy print ?
  1.    
  2. package knlnzhao.slidingmenu;  
  3.   
  4. import android.content.Context;  
  5. import android.util.AttributeSet;  
  6. import android.view.View;  
  7. import android.view.ViewGroup;  
  8. import android.widget.Scroller;  
  9.   
  10. public class FlipperView extends ViewGroup {  
  11.   
  12.     private int distance;// 完全显示菜单需要移动的距离  
  13.     private View menu;  
  14.     private View main;  
  15.     private Scroller scroller;  
  16.     private boolean menuVisible = false;  
  17.   
  18.     public FlipperView(Context context, AttributeSet attrs) {  
  19.         super(context, attrs);  
  20.         // TODO Auto-generated constructor stub  
  21.         scroller = new Scroller(context);  
  22.     }  
  23.   
  24.     @Override  
  25.     protected void onLayout(boolean changed, int l, int t, int r, int b) {  
  26.         // TODO Auto-generated method stub  
  27.   
  28.         distance = getWidth() * 4 / 5;// 获得平滑移动的距离,也是菜单的宽度  
  29.   
  30.         // 布局菜单和主页面视图  
  31.         menu = getChildAt(0);// 获得菜单视图  
  32.         menu.setVisibility(VISIBLE);  
  33.         menu.measure(  
  34.                 MeasureSpec.makeMeasureSpec(distance, MeasureSpec.EXACTLY),  
  35.                 MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXACTLY));  
  36.         menu.layout(-distance, 0, 0, getHeight());  
  37.   
  38.         main = getChildAt(1);// 获得主页面视图  
  39.         main.setVisibility(VISIBLE);  
  40.         // 相当于fill_parent  
  41.         main.measure(  
  42.                 MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXACTLY),  
  43.                 MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.EXACTLY));  
  44.         main.layout(0, 0, getWidth(), getHeight());  
  45.   
  46.     }  
  47.   
  48.     public void showMenu() {  
  49.         if (!menuVisible) {  
  50.             scroller.startScroll(getScrollX(), 0, -distance, 0, 300);  
  51.             invalidate();  
  52.             menuVisible = true;  
  53.         }  
  54.   
  55.     }  
  56.   
  57.     public void hideMenu() {  
  58.         if (menuVisible) {  
  59.             scroller.startScroll(getScrollX(), 0, distance, 0, 300);  
  60.             invalidate();  
  61.             menuVisible = false;  
  62.         }  
  63.   
  64.     }  
  65.   
  66.     @Override  
  67.     public void computeScroll() {  
  68.         // TODO Auto-generated method stub  
  69.         // 当滚动没有完成  
  70.         if (scroller.computeScrollOffset()) {  
  71.             scrollTo(scroller.getCurrX(), 0);  
  72.             postInvalidate();  
  73.         }  
  74.     }  
  75.   
  76. }   


ViewFlipper中包含有两个子布局,一个子布局是menu布局,另一个子布局是主要显示内容布局。在ViewFlipper的onLayout函数中,对这两个子布局进行布局。显示菜单和隐藏菜单是有两个函数实现,分别是

[html]  view plain copy print ?
  1.    
  2. public void showMenu() {  
  3.         if (!menuVisible) {  
  4.             scroller.startScroll(getScrollX(), 0, -distance, 0, 300);  
  5.             invalidate();  
  6.             menuVisible = true;  
  7.         }  
  8.   
  9.     }  
  10.   
  11.     public void hideMenu() {  
  12.         if (menuVisible) {  
  13.             scroller.startScroll(getScrollX(), 0, distance, 0, 300);  
  14.             invalidate();  
  15.             menuVisible = false;  
  16.         }  
  17.   
  18.     }   


这两个函数都用到了ViewGroup中负责移动子视图的Scroller类。通过调用函数

[html]  view plain copy print ?
  1. startScroll(int startX, int startY, int dx, int dy, int duration)   


 

来实现菜单移动的动画效果。这个函数里面的四个参数比较令人费解,仔细琢磨解释一下,如果理解不对,也请各位大牛指正。

startX:在水平方向上,已经滚动的距离。

startY:在竖直方向上,已经滚动的距离。

dx:在水平方向需要滚动的总距离,注意是总距离,包括已经滚动的距离。

dy:在竖直方向上需要滚动的总距离。

这样,自定义的ViewGroup类ViewFlipper就完成了。接下来就要填写内容,包括菜单和主页面了。

菜单menu.xml如下:

[html]  view plain copy print ?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="200.0dip" android:layout_height="fill_parent" android:orientation="vertical" android:background="@color/dark_blue">  
  3.       
  4.     <button android:id="@+id/close" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="关闭菜单"/>  
  5.       
  6.     <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="这是菜单" android:textsize="20.0sp" android:textcolor="#ff000000" android:layout_gravity="center"/>  
  7.  </linearlayout>  


主页面content.xml如下

[html]  view plain copy print ?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="200.0dip" android:layout_height="fill_parent" android:orientation="vertical" android:background="@color/dark_blue">  
  3.       
  4.     <button android:id="@+id/close" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="打开菜单"/>  
  5.       
  6.     <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="这是主页面" android:textsize="20.0sp" android:textcolor="#ff000000" android:layout_gravity="center"/>  
  7. </linearlayout>  


在SlidingMenuActivity的内容描述文件main.xml中做如下定义:

[html]  view plain copy print ?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. lt;linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical">  
  3.      
  4.    <knlnzhao slidingmenu="" flipperview="" android:id="@+id/flipper" android:layout_width="fill_parent" android:layout_height="fill_parent">  
  5.   
  6. lt;/knlnzhao></linearlayout>  


在启动的Activity中做如下代码:

[html]  view plain copy print ?
  1. package knlnzhao.slidingmenu;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.view.GestureDetector;  
  6. import android.view.LayoutInflater;  
  7. import android.view.MotionEvent;  
  8. import android.view.View;  
  9. import android.view.ViewConfiguration;  
  10. import android.view.GestureDetector.OnGestureListener;  
  11. import android.widget.Button;  
  12.   
  13. public class SlidingMenuActivity extends Activity {  
  14.     private FlipperView flipper;  
  15.     private Button open;  
  16.     private Button close;  
  17.     private GestureDetector detector;  
  18.   
  19.     /** Called when the activity is first created. */  
  20.     @Override  
  21.     public void onCreate(Bundle savedInstanceState) {  
  22.         super.onCreate(savedInstanceState);  
  23.         setContentView(R.layout.main);  
  24.   
  25.         flipper = (FlipperView) findViewById(R.id.flipper);  
  26.         View menu = LayoutInflater.from(this).inflate(R.layout.menu, null);  
  27.         View content = LayoutInflater.from(this)  
  28.                 .inflate(R.layout.content, null);  
  29.         flipper.addView(menu);  
  30.         flipper.addView(content);  
  31.   
  32.         open = (Button) content.findViewById(R.id.open);  
  33.         close = (Button) menu.findViewById(R.id.close);  
  34.   
  35.         open.setOnClickListener(new View.OnClickListener() {  
  36.   
  37.             public void onClick(View v) {  
  38.                 // TODO Auto-generated method stub  
  39.                 flipper.showMenu();  
  40.             }  
  41.         });  
  42.   
  43.         close.setOnClickListener(new View.OnClickListener() {  
  44.   
  45.             public void onClick(View v) {  
  46.                 // TODO Auto-generated method stub  
  47.                 flipper.hideMenu();  
  48.             }  
  49.         });  
  50.   
  51.         detector = new GestureDetector(new OnGestureListener() {  
  52.   
  53.             public boolean onSingleTapUp(MotionEvent e) {  
  54.                 // TODO Auto-generated method stub  
  55.                 return false;  
  56.             }  
  57.   
  58.             public void onShowPress(MotionEvent e) {  
  59.                 // TODO Auto-generated method stub  
  60.   
  61.             }  
  62.   
  63.             public boolean onScroll(MotionEvent e1, MotionEvent e2,  
  64.                     float distanceX, float distanceY) {  
  65.                 // TODO Auto-generated method stub  
  66.                 return false;  
  67.             }  
  68.   
  69.             public void onLongPress(MotionEvent e) {  
  70.                 // TODO Auto-generated method stub  
  71.   
  72.             }  
  73.   
  74.             public boolean onFling(MotionEvent e1, MotionEvent e2,  
  75.                     float velocityX, float velocityY) {  
  76.                 // TODO Auto-generated method stub  
  77.                 // 判断是否达到最小滑动速度,取绝对值  
  78.                 if (Math.abs(velocityX) > ViewConfiguration.get(  
  79.                         SlidingMenuActivity.this).getScaledMinimumFlingVelocity()) {  
  80.                     if (velocityX > 0 ) {//向右滑动  
  81.                         flipper.showMenu();  
  82.                     } else if (velocityX < 0) {//向左滑动  
  83.                         flipper.hideMenu();  
  84.                     }  
  85.                 }  
  86.                 return true;  
  87.             }  
  88.   
  89.             public boolean onDown(MotionEvent e) {  
  90.                 // TODO Auto-generated method stub  
  91.                 return false;  
  92.             }  
  93.         });  
  94.           
  95.     }  
  96.   
  97.     @Override  
  98.     public boolean onTouchEvent(MotionEvent event) {  
  99.         // TODO Auto-generated method stub  
  100.         detector.onTouchEvent(event);  
  101.         return true;  
  102.     }  
  103. }   


 

主要包括对FlipperView进行填充,滑动操作等等。

奉上运行效果图:

技术选型 【后端】:Java 【框架】:springboot 【前端】:vue 【JDK版本】:JDK1.8 【服务器】:tomcat7+ 【数据库】:mysql 5.7+ 项目包含前后台完整源码。 项目都经过严格调试,确保可以运行! 具体项目介绍可查看博主文章或私聊获取 助力学习实践,提升编程技能,快来获取这份宝贵的资源吧! 在当今快速发展的信息技术领域,技术选型是决定一个项目成功与否的重要因素之一。基于以下的技术栈,我们为您带来了一份完善且经过实践验证的项目资源,让您在学习和提升编程技能的道路上事半功倍。以下是该项目的技术选型和其组件的详细介绍。 在后端技术方面,我们选择了Java作为编程语言。Java以其稳健性、跨平台性和丰富的库支持,在企业级应用中处于领导地位。项目采用了流行的Spring Boot框架,这个框架以简化Java企业级开发而闻名。Spring Boot提供了简洁的配置方式、内置的嵌入式服务器支持以及强大的生态系统,使开发者能够更高效地构建和部署应用。 前端技术方面,我们使用了Vue.js,这是一个用于构建用户界面的渐进式JavaScript框架。Vue以其易上手、灵活和性能出色而受到开发者的青睐,它的组件化开发思想也有助于提高代码的复用性和可维护性。 项目的编译和运行环境选择了JDK 1.8。尽管Java已经推出了更新的版本,但JDK 1.8依旧是一种成熟且稳定的选择,广泛应用于各类项目中,确保了兼容性和稳定性。 在服务器方面,本项目部署在Tomcat 7+之上。Tomcat是Apache软件基金会下的一个开源Servlet容器,也是应用最为广泛的Java Web服务器之一。其稳定性和可靠的性能表现为Java Web应用提供了坚实的支持。 数据库方面,我们采用了MySQL 5.7+。MySQL是一种高效、可靠且使用广泛的关系型数据库管理系统,5.7版本在性能和功能上都有显著的提升。 值得一提的是,该项目包含了前后台的完整源码,并经过严格调试,确保可以顺利运行。通过项目的学习和实践,您将能更好地掌握从后端到前端的完整开发流程,提升自己的编程技能。欢迎参考博主的详细文章或私信获取更多信息,利用这一宝贵资源来推进您的技术成长之路!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值