Android--侧滑菜单应用的实现
来源:互联网 发布:搞笑的淘宝收货人名字 编辑:程序博客网 时间:2024/05/22 03:05
侧滑菜单应用现在非常多,而且实现方式也多种多样。通过在网上的多方查找,我找到郭霖少侠的这篇文章:http://blog.csdn.net/guolin_blog/article/details/8744400,研究之后收获颇多。同时记得以前看过一篇讲Scroller实现滑屏的文章:http://www.cnblogs.com/wanqieddy/archive/2012/05/05/2484534.html。
那为何不用scroller来实现以下侧滑菜单?闲的蛋疼,那就试试吧,在这里先感谢以上两篇博文给我的启发。
原理:通过scrollBy和scrollTo来移动右侧的content布局,实际上整个过程中,左侧的menu布局未发生滚动,这样出来的效果是右侧content布局覆盖住左侧menu布局。当然scroll的方式也可以实现menu和content同时平移的效果,这个只需要在布局文件上动动手脚就行了,在此先按下不表。
下面是本文的实现效果
activity_main.xml文件:
首先放入menu布局,因为是RelativeLayout布局因此先放入的会被覆盖,然后是滑动布局,在滑动布局中加入content布局,因为content布局会随滑动布局一起移动。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <include android:id="@+id/menu" layout="@layout/menu" /> <com.noter.layout.SlideLayout android:id="@+id/slide_layout" android:layout_width="fill_parent" android:layout_height="fill_parent" > <include android:id="@+id/content" layout="@layout/content_diary" /> </com.noter.layout.SlideLayout></RelativeLayout>
menu.xml和conent_diary.xml这两个布局文件就不用讲了,大家跟着感觉走,想放什么放什么吧。
SlideLayout.java文件:大部分代码都很简单,看注释就能懂。这里只说几个要点,我也是调试过之后才明白的:
1. getScrollX()得到的是当前View的最左边所在的X坐标。程序初始化后此值为0,View向右滑动后,相当于屏幕坐标系向负方向移动了一段,因此此时此值为负数;反之则相反。
2. Scroller实际上只是保存和提供自动滑动时所需的数值,真正完成滑动的还是scrollTo和scrollBy两个函数。
3. 我写的SlideLayout继承自RelativeLayout,其实也可以继承自ViewGroup,但是就需要自己重写onMeasure和onLayout函数,来布局子控件。这个实现中没有特殊的布局要求,所以用RelatiLayout就可以啦。
package com.noter.layout;import android.content.Context;import android.graphics.Rect;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.VelocityTracker;import android.view.View;import android.view.ViewConfiguration;import android.widget.RelativeLayout;import android.widget.Scroller;public class SlideLayout extends RelativeLayout {private static String TAG = "SlideMenuLayout";private Context mContext;private Scroller mScroller; //Android 提供的滑动辅助类private int mTouchSlop = 0 ; //在被判定为滚动之前用户手指可以移动的最大值private VelocityTracker mVelocityTracker; //用于计算手指滑动的速度public static final int SNAP_VELOCITY = 200; //滚动显示和隐藏左侧布局时,手指滑动需要达到的速度:每秒200个像素点private int mMaxScrollX = 0; //最大滚动距离,等于menu的宽度public void setMaxScrollX(int maxScrollX) {this.mMaxScrollX = maxScrollX;}private float mDownX; //一次按下抬起的动作中,按下时的X坐标,用于和抬起时的X比较,判断移动距离。少于mTouchSlop则判定为原地点击private float mLastX; //记录滑动过程中的X坐标private boolean isMenuOpen = false; //菜单界面是否被打开,只有完全打开才为truepublic boolean isMenuOpen() {return isMenuOpen;}private View mContent;public SlideLayout(Context context, AttributeSet attrs) {super(context, attrs);mContext = context;init();}private void init() {Log.v(TAG, "init start");mScroller = new Scroller(mContext);mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();}@Overridepublic void computeScroll() {if (mScroller.computeScrollOffset()) {scrollTo(mScroller.getCurrX(), mScroller.getCurrY());postInvalidate();}}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {super.onLayout(changed, l, t, r, b);if(changed){mContent = getChildAt(0);}}@Overridepublic boolean onTouchEvent(MotionEvent event) {createVelocityTracker(event);int curScrollX = getScrollX();// 检查触摸点是否在滑动布局(内容content)中,如果不是则返回false,即本View不处理该事件if (mContent != null) {Rect rect = new Rect();mContent.getHitRect(rect);if (!rect.contains((int)event.getX() + curScrollX, (int)event.getY())) {return false;}}float x = event.getX(); //取得本次event的X坐标switch (event.getAction()) {case MotionEvent.ACTION_DOWN:mDownX = x;mLastX = x;break;case MotionEvent.ACTION_MOVE:int deltaX = (int)(mLastX - x);if((curScrollX + deltaX) < -mMaxScrollX) {deltaX = -mMaxScrollX - curScrollX;}if((curScrollX + deltaX) > 0){deltaX = -curScrollX;}if (deltaX != 0) {scrollBy(deltaX, 0);}mLastX = x;break;case MotionEvent.ACTION_UP:int velocityX = getScrollVelocity();int offsetX = (int) (x - mDownX);//成立表明移动距离已经达到被判断为滑动的最低标准//不成立表明不被判断为滑动,则认为是单一的点击,则关闭menuif(Math.abs(offsetX) >= mTouchSlop) {//成立表明手指移动速度达标,则进行自动滑动;//不成立表明速度不达标,但仍然需要判断当前SlideLayout的位置//如果已经超过一半,则继续自动完成剩下的滑动,如果没有超过一半,则反向滑动if(Math.abs(velocityX) >= SNAP_VELOCITY) {if(velocityX > 0){openMenu();} else if(velocityX < 0) {closeMenu();}} else {if (curScrollX >= -mMaxScrollX / 2) {closeMenu();} else {openMenu();}}} else {closeMenu();}recycleVelocityTracker();break;}return true;}private void createVelocityTracker(MotionEvent event) {if (mVelocityTracker == null) {mVelocityTracker = VelocityTracker.obtain();}mVelocityTracker.addMovement(event);}//获取手指在View上的滑动速度,以每秒钟移动了多少像素值为单位private int getScrollVelocity() {mVelocityTracker.computeCurrentVelocity(1000);return (int) mVelocityTracker.getXVelocity();}private void recycleVelocityTracker() {mVelocityTracker.recycle();mVelocityTracker = null;}//打开Menu布局public void openMenu() {int curScrollX = getScrollX();scrollToDestination(-mMaxScrollX - curScrollX);isMenuOpen = true;}//关闭Menu布局public void closeMenu() {int curScrollX = getScrollX();scrollToDestination(-curScrollX);isMenuOpen = false;}private void scrollToDestination(int x) {if (x == 0)return;mScroller.startScroll(getScrollX(), 0, x, 0, Math.abs(x));invalidate();}}
最后是代码下载,Enjoy it!
侧滑菜单实例
侧滑菜单(修正版) 修改了1楼提到的bug
侧滑菜单(平移版)
- Android--侧滑菜单应用的实现
- Android--侧滑菜单应用的实现
- Android--侧滑菜单应用的实现
- Android底部菜单和侧滑菜单的综合应用
- 【Android 界面效果31】Android--侧滑菜单应用的实现
- android 侧滑菜单的简单实现
- Android侧滑菜单的实现
- Android 侧滑菜单的实现
- Android侧滑菜单的实现
- android: 侧滑菜单的实现(ViewDragHelper)
- Android 侧滑菜单实现
- android 侧滑菜单 实现
- android 侧滑菜单实现
- android 实现侧滑菜单
- android实现侧滑菜单
- Android侧滑菜单实现
- Android侧滑菜单实现
- Android实现侧滑菜单
- Java byte数组和int互转
- OpenGL: 实现立体显示
- 编程之美4.5 磁带文件存放优化
- 从内存中加载动态库
- 获取json数据,低版本android无法解析
- Android--侧滑菜单应用的实现
- linux 链接脚本
- 我的学习之旅:android文件下载功能的实现
- How to Build ffmpeg with NDK r9
- Java命令行运行参数说明大全(偷来的)
- ArrayBlockingQueue 实现线程同步效果例子
- POJ 2182 Lost Cows
- hdu1856 More is better(并查集)
- 设置 quick-cocos2d-x 在 Mac 下的编译环境