Android侧滑菜单完整详细示例(精装版)

简介: MainActivity如下:package cn.patience7;import android.os.AsyncTask;import android.
MainActivity如下:
package cn.patience7;

import android.os.AsyncTask;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnPreDrawListener;
import android.widget.RelativeLayout;
import android.app.Activity;
import android.content.Context;

/**
 * Demo描述: 
 * 滑动菜单SlidingMenu完整详细示例
 * 
 * 布局文件:
 * 采用相对布局,两个界面是重叠在一起的,分别为aboveView和belowView.
 * 
 * 实现原理:
 * 对aboveView的Touch事件进行监听
 * 即mBboveView.setOnTouchListener(new TouchListenerImpl())
 * 在TouchListenerImpl中:
 * 1 ACTION_UP时将aboveView弹回到屏幕的左右两侧
 * 2 除ACTION_UP之外的Action交给手势GestureDetector处理
 * 
 * 所以通过aboveView的移动来遮掩或者显示belowView,从而达到 侧滑菜单的效果
 * 
 * 
 * 备注说明:
 * 该Demo与前面两个侧滑菜单实现原理是差不多但在代码实现上使用了GestureDetector
 */
public class MainActivity extends Activity {
	private View mAboveView;
	private View mBelowView;
	private float scrollX = 0;
	private Context mContext;
	private int screenWidth = 0;
	private boolean isMeasured = false;
	private int MAX_SCROLL_DISTANCE = 0;
	private GestureDetector mGestureDetector;
	private GestureListenerImpl mGestureListenerImpl;
	private SlowlyMoveAsyncTask mSlowlyMoveAsyncTask;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		initView();
	}

	private void initView() {
		mContext = this;
		mGestureListenerImpl = new GestureListenerImpl();
		mGestureDetector = new GestureDetector(mContext, mGestureListenerImpl);
		mGestureDetector.setIsLongpressEnabled(false);
		mAboveView = findViewById(R.id.aboveLinearLayout);
		mAboveView.setOnTouchListener(new TouchListenerImpl());
		mBelowView = findViewById(R.id.belowLinearLayout);
		initData();
	}

	/**
	 * 1 将aboveView的宽度设置为屏幕的宽度,从而完全遮掩belowView
	 * 2 MAX_SCROLL_DISTANCE为aboveView向屏幕左侧的最大滑动距离
	 */
	private void initData() {
		ViewTreeObserver viewTreeObserver = mAboveView.getViewTreeObserver();
		viewTreeObserver.addOnPreDrawListener(new OnPreDrawListener() {
			@Override
			public boolean onPreDraw() {
				if (!isMeasured) {
					screenWidth = getWindowManager().getDefaultDisplay().getWidth();
					RelativeLayout.LayoutParams aboveViewLayoutParams
					=(RelativeLayout.LayoutParams) mAboveView.getLayoutParams();
					aboveViewLayoutParams.width = screenWidth;
					mAboveView.setLayoutParams(aboveViewLayoutParams);
					MAX_SCROLL_DISTANCE = mBelowView.getWidth();
					isMeasured = true;
				}
				return true;
			}
		});
	}

	private class TouchListenerImpl implements OnTouchListener {
		@Override
		public boolean onTouch(View v, MotionEvent event) {
			if (event.getAction() == MotionEvent.ACTION_UP) {
				RelativeLayout.LayoutParams aboveViewLayoutParams
				=(RelativeLayout.LayoutParams) mAboveView.getLayoutParams();
				if (aboveViewLayoutParams.leftMargin > (-screenWidth / 2)) {
					// 手指往左滑时,未及屏幕一半时抬起.归位
					mSlowlyMoveAsyncTask = new SlowlyMoveAsyncTask();
					mSlowlyMoveAsyncTask.execute(20);
				} else {
					// 手指往左滑时,超过屏幕一半时抬起.归位
					mSlowlyMoveAsyncTask = new SlowlyMoveAsyncTask();
					mSlowlyMoveAsyncTask.execute(-20);
				}
			}
			return mGestureDetector.onTouchEvent(event);
		}
	}

	private class GestureListenerImpl implements GestureDetector.OnGestureListener {
		@Override
		public boolean onDown(MotionEvent arg0) {
			return true;
		}

		@Override
		public boolean onFling(MotionEvent arg0, MotionEvent arg1, float arg2,float arg3) {
			return false;
		}

		@Override
		public void onLongPress(MotionEvent arg0) {
		}

		@Override
		public boolean onScroll(MotionEvent arg0, MotionEvent arg1,float distanceX, float distanceY) {
			scrollX = scrollX + distanceX;
			RelativeLayout.LayoutParams aboveViewLayoutParams
			=(RelativeLayout.LayoutParams) mAboveView.getLayoutParams();
			aboveViewLayoutParams.leftMargin = (int) (aboveViewLayoutParams.leftMargin - scrollX);
			// 手指往右边滑动的极限,防止越界
			if (aboveViewLayoutParams.leftMargin >= 0) {
				aboveViewLayoutParams.leftMargin = 0;
			}
			// 手指往左边滑动的极限,防止越界
			if (-aboveViewLayoutParams.leftMargin >= MAX_SCROLL_DISTANCE) {
				aboveViewLayoutParams.leftMargin = -MAX_SCROLL_DISTANCE;
			}
			mAboveView.setLayoutParams(aboveViewLayoutParams);
			return false;
		}

		@Override
		public void onShowPress(MotionEvent motionEvent) {

		}

		@Override
		public boolean onSingleTapUp(MotionEvent motionEvent) {
			return false;
		}
	}

	// 以下为异步任务,负责处理手指抬起时布局向屏幕左右两侧弹回
	private class SlowlyMoveAsyncTask extends AsyncTask<Integer, Integer, Void> {
		@Override
		protected Void doInBackground(Integer... params) {
			RelativeLayout.LayoutParams aboveViewLayoutParams
			= (RelativeLayout.LayoutParams) mAboveView.getLayoutParams();
			int leftMargin = aboveViewLayoutParams.leftMargin;
			// 需要移动的次数
			int move_times = 0;
			// 总共需要弹回的距离
			int all_move_distance = 0;
			// 每次弹回的距离
			int every_move_distance = Math.abs(params[0]);

			// 往屏幕右边移动
			if (params[0] > 0) {
				all_move_distance = Math.abs(leftMargin);
				// 往屏幕左边移动
			} else {
				all_move_distance = MAX_SCROLL_DISTANCE - Math.abs(leftMargin);
			}

			// 计算需要移动的次数
			if (all_move_distance % every_move_distance == 0) {
				move_times = all_move_distance / every_move_distance;
			} else {
				move_times = all_move_distance / every_move_distance + 1;
			}

			System.out.println("--> all_move_distance=" + all_move_distance);
			System.out.println("--> every_move_distance=" + every_move_distance);
			System.out.println("--> move_times=" + move_times);

			// 移动的过程
			for (int i = 0; i < move_times; i++) {
				publishProgress(params[0]);
				try {
					Thread.sleep(20);
				} catch (Exception e) {
				}
			}
			return null;
		}

		@Override
		protected void onProgressUpdate(Integer... values) {
			super.onProgressUpdate(values);
			int every_move_distance = values[0];
			RelativeLayout.LayoutParams aboveViewLayoutParams
			= (RelativeLayout.LayoutParams) mAboveView.getLayoutParams();
			if (every_move_distance > 0) {
				if (aboveViewLayoutParams.leftMargin < 0) {
					aboveViewLayoutParams.leftMargin += every_move_distance;
					// 处理最后一次滑动后可能越界的情况
					if (aboveViewLayoutParams.leftMargin > 0) {
						aboveViewLayoutParams.leftMargin = 0;
					}
					mAboveView.setLayoutParams(aboveViewLayoutParams);
				}
			} else {
				if (aboveViewLayoutParams.leftMargin > (-MAX_SCROLL_DISTANCE)) {
					aboveViewLayoutParams.leftMargin -= (-every_move_distance);
					// 处理最后一次滑动后可能越界的情况
					if (aboveViewLayoutParams.leftMargin < -MAX_SCROLL_DISTANCE) {
						aboveViewLayoutParams.leftMargin = -MAX_SCROLL_DISTANCE;
					}
					mAboveView.setLayoutParams(aboveViewLayoutParams);
				}
			}
		}
	}
}

main.xml如下:
<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" >

    <LinearLayout
        android:id="@+id/belowLinearLayout"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_marginLeft="50dip" >

        <ImageView
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:scaleType="fitXY"
            android:src="@drawable/a" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/aboveLinearLayout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <ImageView
             android:id="@+id/imageView"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:scaleType="fitXY"
            android:src="@drawable/b" />
    </LinearLayout>

</RelativeLayout>


相关文章
|
3月前
|
存储 算法 开发工具
OpenCV 安卓编程示例:1~6 全
OpenCV 安卓编程示例:1~6 全
56 0
|
8月前
|
Android开发
Android 中选项菜单(Option menu)的用法
Android 中选项菜单(Option menu)的用法
82 0
|
4月前
|
Android开发
[Android]DrawerLayout滑动菜单+NavigationView
[Android]DrawerLayout滑动菜单+NavigationView
27 0
|
4月前
|
XML Java Android开发
Android App手势冲突处理中上下左右滑动的处理以及侧滑边缘菜单的讲解及实战(附源码 可直接使用)
Android App手势冲突处理中上下左右滑动的处理以及侧滑边缘菜单的讲解及实战(附源码 可直接使用)
67 0
|
4月前
|
XML Java Android开发
Android Studio App开发中工具栏Toolbar、溢出菜单OverflowMenu、标签布局TabLayout的讲解及实战(实现京东App的标签导航栏,附源码)
Android Studio App开发中工具栏Toolbar、溢出菜单OverflowMenu、标签布局TabLayout的讲解及实战(实现京东App的标签导航栏,附源码)
61 0
|
9月前
|
XML Android开发 数据格式
Android 彩色上下文菜单 Context
Android 彩色上下文菜单 Context
|
9月前
|
XML Android开发 数据格式
Android上机实验-4 菜单和对话框
Android上机实验-4 菜单和对话框
112 1
|
9月前
|
XML Java 测试技术
【Android开发日常】一文弄懂桌面图标快捷菜单 & 桌面小组件
开发可以定义快捷方式,以便在应用中执行特定操作。 这些快捷方式可在受支持的启动器或助理(如 Google 助理)中显示,方便用户快速启动应用中的常见任务或推荐任务。 通过本文你还将了解一些可提升快捷方式效果的最佳做法。
|
10月前
|
前端开发 Android开发
Android高仿qq及微信底部菜单的几种实现方式
Android高仿qq及微信底部菜单的几种实现方式
|
10月前
|
数据库 Android开发
重新构建711的Android项目(一),巧妙的小屏菜单查询框架实现
重新构建711的Android项目(一),巧妙的小屏菜单查询框架实现