最近根據項目的要求,須要實現從右側滑出的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