從右側滑出的遮蓋型SlidingMenu

最近根據項目的要求,須要實現從右側滑出的slidingmenu,且原有界面不能移動,直接被滑出的菜單覆蓋。查了相關資料和開源代碼,後根據http://www.oschina.net/code/snippet_219356_19035此文章的開源項目,本身修改了個工具類,實現相應的效果。 需注意getScrollX()方法的的做用,個人理解是,獲取控件的偏移位置(即0-控件滑動的距離),若初始化後控件並無移動過,則getScrollX()返回的距離應爲0。 有興趣的朋友也可去上面的連接下載原有的項目研究下。java

/**
 * 側滑工具類 ,右側滑動視圖
 * 使用方法:先設置中間的內容佈局,在設置右邊的側滑佈局,方法分別為setCenterView(),setRightView()
 * 
 * @author Administrator
 * 
 */
<!-- lang: java -->
    public class SlidingMenu extends RelativeLayout {
private final String Tag = "slidingMenu";
private View mSlidingView;
private View mDetailView;
private RelativeLayout bgShade;
private int screenWidth;
private int screenHeight;
private Scroller mScroller;
private VelocityTracker mVelocityTracker;
private int mTouchSlop;
private float mLastMotionX;
private float mLastMotionY;
private static final int VELOCITY = 50;
private boolean mIsBeingDragged = true;
private boolean tCanSlideRight = false;
private boolean hasClickRight = false;

public SlidingMenu(Context context) {
	super(context);
	init(context);
}

private void init(Context context) {

	bgShade = new RelativeLayout(context);
	mScroller = new Scroller(getContext());
	// 得到可以進行手勢滑動的距離
	mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
	WindowManager windowManager = ((Activity) context).getWindow()
			.getWindowManager();
	Display display = windowManager.getDefaultDisplay();
	screenWidth = display.getWidth();
	screenHeight = display.getHeight();
	LayoutParams bgParams = new LayoutParams(screenWidth, screenHeight);
	bgParams.addRule(RelativeLayout.CENTER_IN_PARENT);
	bgShade.setLayoutParams(bgParams);

}

public SlidingMenu(Context context, AttributeSet attrs) {
	super(context, attrs);
	init(context);
}

public SlidingMenu(Context context, AttributeSet attrs, int defStyle) {
	super(context, attrs, defStyle);
	init(context);
}

public void addViews(View center, View right) {
	setRightView(right);
	setCenterView(center);
}

public void setRightView(View view) {
	LayoutParams behindParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
			LayoutParams.FILL_PARENT);
	behindParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
	addView(view, behindParams);
	mDetailView = view;
	mDetailView.bringToFront();// 確保rightview置頂
	ViewTreeObserver vto = mDetailView.getViewTreeObserver();
	vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {// 調用layout或調用visibility時調用此方法

		@Override
		public void onGlobalLayout() {// 設置後rightview是疊加在centerview上面,因此須要先將rightview移動到右側不可見區域
			mDetailView.getViewTreeObserver().removeGlobalOnLayoutListener(
					this);
			Log.i(Tag, "width:" + mDetailView.getWidth());
			mDetailView.scrollTo(-mDetailView.getWidth(),
					mDetailView.getScrollY());
		}
	});

}

public void setCenterView(View view) {
	LayoutParams aboveParams = new LayoutParams(LayoutParams.FILL_PARENT,
			LayoutParams.FILL_PARENT);

	LayoutParams bgParams = new LayoutParams(screenWidth, screenHeight);
	bgParams.addRule(RelativeLayout.CENTER_IN_PARENT);

	addView(bgShade, bgParams);
	addView(view, aboveParams);
	mSlidingView = view;
	// mSlidingView.bringToFront();
}

@Override
public void scrollTo(int x, int y) {
	super.scrollTo(x, y);
	postInvalidate();
}

@Override
public void computeScroll() {
	if (!mScroller.isFinished()) {
		if (mScroller.computeScrollOffset()) {
			int oldX = mDetailView.getScrollX();
			int oldY = mDetailView.getScrollY();
			int x = mScroller.getCurrX();
			int y = mScroller.getCurrY();
			if (oldX != x || oldY != y) {
				if (mDetailView != null) {
					mDetailView.scrollTo(x, y);
					if (x < 0)
						bgShade.scrollTo(x + 20, y);// 背景陰影右偏
					else
						bgShade.scrollTo(x - 20, y);// 背景陰影左偏
				}
			}
			invalidate();
		}
	}
}

private boolean canSlideRight = true;

// 設置是否可手動滑動
public void setCanSliding(boolean right) {
	canSlideRight = right;
}

/* 攔截touch事件 */
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {

	final int action = ev.getAction();
	final float x = ev.getX();
	final float y = ev.getY();
	switch (action) {
	case MotionEvent.ACTION_DOWN:
		mLastMotionX = x;
		mLastMotionY = y;
		mIsBeingDragged = false;
		if (canSlideRight) {
			mDetailView.setVisibility(View.VISIBLE);
		}
		break;

	case MotionEvent.ACTION_MOVE:
		final float dx = x - mLastMotionX;
		final float xDiff = Math.abs(dx);
		final float yDiff = Math.abs(y - mLastMotionY);
		if (xDiff > mTouchSlop && xDiff > yDiff) {
			if (canSlideRight) {
				float oldScrollX = mDetailView.getScrollX();
				if (oldScrollX < 0) {
					mIsBeingDragged = true;
					mLastMotionX = x;
				} else {
					if (dx > 0) {
						mIsBeingDragged = true;
						mLastMotionX = x;
					}
				}
			}

		}
		break;

	}
	return mIsBeingDragged;
}

/* 處理攔截後的touch事件 */
@Override
public boolean onTouchEvent(MotionEvent ev) {
	if (mVelocityTracker == null) {
		mVelocityTracker = VelocityTracker.obtain();
	}
	mVelocityTracker.addMovement(ev);

	final int action = ev.getAction();
	final float x = ev.getX();
	final float y = ev.getY();

	switch (action) {
	case MotionEvent.ACTION_DOWN:
		if (!mScroller.isFinished()) {
			mScroller.abortAnimation();
		}
		mLastMotionX = x;
		mLastMotionY = y;

		// if (mDetailView.getScrollX() == getDetailViewWidth()
		// && mLastMotionX < getMenuViewWidth()) {
		// return false;
		// }

		break;
	case MotionEvent.ACTION_MOVE:
		if (mIsBeingDragged) {
			final float deltaX = mLastMotionX - x;
			mLastMotionX = x;
			float oldScrollX = mDetailView.getScrollX();
			float scrollX = oldScrollX + deltaX;
			if (canSlideRight) {// 此控件爲右側的menu,活動區域應該是在初始位置右側,也就是scroll值只能是小於等於0
				if (scrollX > 0)
					scrollX = 0;
			}
			if (deltaX < 0 && oldScrollX < 0) { // scrollX的範圍值
				final float rightBound = -getDetailViewWidth();
				final float leftBound = 0;
				if (scrollX > leftBound) {
					scrollX = leftBound;
				} else if (scrollX < rightBound) {
					scrollX = rightBound;
				}
			}
			if (mDetailView != null) {// 隨手勢滾動view
				mDetailView.scrollTo((int) scrollX,
						mDetailView.getScrollY());
				if (scrollX < 0)
					bgShade.scrollTo((int) scrollX + 20,
							mSlidingView.getScrollY());
				else
					bgShade.scrollTo((int) scrollX - 20,
							mSlidingView.getScrollY());
			}

		}
		break;
	case MotionEvent.ACTION_CANCEL:
	case MotionEvent.ACTION_UP:
		if (mIsBeingDragged) {
			final VelocityTracker velocityTracker = mVelocityTracker;
			velocityTracker.computeCurrentVelocity(100);
			float xVelocity = velocityTracker.getXVelocity();// 滑動的速度
			int oldScrollX = mDetailView.getScrollX();
			int dx = 0;
			if (oldScrollX <= 0 && canSlideRight) {
				if (xVelocity > VELOCITY) {// 向右滑動,超出指定速度時
					dx = -getDetailViewWidth() - oldScrollX;
				} else if (xVelocity < -VELOCITY) {// 向左滑動,超出指定速度時
					dx = -oldScrollX;
					// if (hasClickRight) {
					// hasClickRight = false;
					// setCanSliding( tCanSlideRight);
					// }
				} else if (oldScrollX < -getDetailViewWidth() / 2) {// 指定速度內
					dx = -getDetailViewWidth() - oldScrollX;
				} else if (oldScrollX >= -getDetailViewWidth() / 2) {// 指定速度內
					dx = -oldScrollX;
					// if (hasClickRight) {
					// hasClickRight = false;
					// setCanSliding( tCanSlideRight);
					// }
				}
			}

			smoothScrollTo(dx);

		}

		break;
	}

	return true;
}
//得到右側視圖的寬度
private int getDetailViewWidth() {
	if (mDetailView == null) {
		return 0;
	}
	return mDetailView.getWidth();
}

// 自動滾動view
void smoothScrollTo(int dx) {
	int duration = 500;
	int oldScrollX = mDetailView.getScrollX();
	mScroller.startScroll(oldScrollX, mDetailView.getScrollY(), dx,
			mDetailView.getScrollY(), duration);
	invalidate();
}

/* 顯示右側邊的view */
public void showRightView() {
	int menuWidth = mDetailView.getWidth();
	int oldScrollX = mDetailView.getScrollX();
	System.out.println("x : " + oldScrollX);
	if (oldScrollX == 0) {
		mDetailView.setVisibility(View.VISIBLE);
		smoothScrollTo(-menuWidth);
		tCanSlideRight = canSlideRight;
		hasClickRight = true;
		setCanSliding(true);
	} else if (oldScrollX == -menuWidth) {
		smoothScrollTo(menuWidth);
		if (hasClickRight) {
			hasClickRight = false;
			setCanSliding(tCanSlideRight);
		}
	}
}

}ide

相關文章
相關標籤/搜索