【Android 界面效果31】Android--侧滑菜单应用的实现
侧滑菜单应用现在非常多,而且实现方式也多种多样。通过在网上的多方查找,我找到郭霖少侠的这篇文章: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; //菜单界面是否被打开,只有完全打开才为true
- public 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();
- }
- @Override
- public void computeScroll() {
- if (mScroller.computeScrollOffset()) {
- scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
- postInvalidate();
- }
- }
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
- if(changed){
- mContent = getChildAt(0);
- }
- }
- @Override
- public 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);
- //成立表明移动距离已经达到被判断为滑动的最低标准
- //不成立表明不被判断为滑动,则认为是单一的点击,则关闭menu
- if(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 界面效果31】Android--侧滑菜单应用的实现的更多相关文章
- Android 实现形态各异的双向侧滑菜单 自定义控件来袭
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/39670935,本文出自:[张鸿洋的博客] 1.概述 关于自定义控件侧滑已经写了两 ...
- Android 实现形态各异的双向侧滑菜单 自定义控件来袭(转载)
1.概述 关于自定义控件侧滑已经写了两篇了~~今天决定把之前的单向改成双向,当然了,单纯的改动之前的代码也没意思,今天不仅会把之前的单向改为双向,还会多添加一种侧滑效果,给大家带来若干种形态各异的双向 ...
- Xamarin.Android中使用ResideMenu实现侧滑菜单
上次使用Xamarin.Android实现了一个比较常用的功能PullToRefresh,详情见:Xamarin. Android实现下拉刷新功能 这次将实现另外一个手机App中比较常用的功能:侧滑菜 ...
- android L 新控件侧滑菜单DrawerLayout 使用教程
介绍 drawerLayout是Support Library包中实现了侧滑菜单效果的控件,可以说drawerLayout是因为第三方控件如MenuDrawer等的出现之后,google借鉴而出现的产 ...
- 【Android 界面效果21】Android ViewPager使用详解
这是谷歌官方给我们提供的一个兼容低版本安卓设备的软件包,里面包囊了只有在安卓3.0以上可以使用的api.而viewpager就是其中之一利用它,我们可以做很多事情,从最简单的导航,到页面菜单等等.那如 ...
- 【Android 界面效果18】Android软件开发之常用系统控件界面整理
[java] view plaincopyprint? <span style="font-size:18px">1.文本框TextView TextView的作用 ...
- 【Android 界面效果17】Android手机平板两不误,使用Fragment实现兼容手机和平板的程序
记得我之前参与开发过一个华为的项目,要求程序可以支持好几种终端设备,其中就包括Android手机和Android Pad.然后为了节省人力,公司无节操地让Android手机和Android Pad都由 ...
- Android自定义顶部栏及侧滑菜单和fragment+viewpag滑动切换的实现
嘿嘿嘿,关于android滑动的操作,是不是经常都会用到呢. 我肯定也要学习一下啦. https://blog.csdn.net/u013184970/article/details/82882107 ...
- 【Android 界面效果25】android中include标签的使用
在一个项目中我们可能会需要用到相同的布局设计,如果都写在一个xml文件中,代码显得很冗余,并且可读性也很差,所以我们可以把相同布局的代码单独写成一个模块,然后用到的时候可以通过<include ...
随机推荐
- MFC如何添加系统消息处理函数?
http://zhidao.baidu.com/question/318026804.html 在MFC程序中,我们并不经常直接调用Windows API,而是从MFC类创建对象并调用属于这些对象的成 ...
- C++的双冒号(域解析符)
在C++中,“::”表示“作用域标识符”或者叫“作用域分解运算符”,比如:“类名::函数名”,这样是表示该函数是该类的成员函数, 但是象下面这种写法:“::函数名”,作用域标识符前面没有任何对象,代表 ...
- LightOJ 1282 Leading and Trailing (快数幂 + 数学)
http://lightoj.com/volume_showproblem.php?problem=1282 Leading and Trailing Time Limit:2000MS Me ...
- oracle学习 十 数据库的语句优化(持续更)
平时关注Oracle数据库的网友都知道,Oracle性能优化保证了Oracle数据库的健壮性.下面就此提出需要注意的两个原则. 原则一:注意WHERE子句中的连接顺序: ORACLE采用自下而上的 ...
- Unity3d:加载Gif格式图片
unity里不支持Gif格式的图片,网上搜索也没有相关资料,殊不知我们已经太相信度娘了,而没有了自己的分析,我们知道Gif图是由多个静态图做成的,那我们就回归本土,第一步:把gif拆成n个静态图放在集 ...
- ao的编辑操作
自从10.0以后,ArcMap的编辑界面发生了变化,原本的“目标图层”和“编辑任务”不见了,取而代之的是“要素构造”窗口,里面融合了目标图层和编辑任务功能.查看sdk发现,多了几个接口,前面已经讲过. ...
- Linux下getopt()函数的简单使用
最近在弄Linux C编程,本科的时候没好好学啊,希望学弟学妹们引以为鉴. 好了,虽然啰嗦了点,但确实是忠告.步入正题: 我们的主角----getopt()函数. 英雄不问出处,getopt()函数的 ...
- java中Arrays类中,binarySearch()方法的返回值问题
最近在复习Java知识,发现果然不经常使用忘得非常快... 看到binarySearch()方法的使用时,发现书上有点错误,于是就自己上机实验了一下,最后总结一下该方法的返回值. 总结:binaryS ...
- 【腾讯内部干货分享】分析Dalvik字节码进行减包优化
http://wetest.qq.com/lab/view/?id=96?from=ads_test2_qqtips&sessionUserType=BFT.PARAMS.192184.TAS ...
- Spring三种实例化Bean的方法
1.实例化bean的三种方法:(1) 构造器<!-- 体验1 --><bean id="personService" class="com.persia ...
