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