从右侧滑出的遮盖型SlidingMenu

最近根据项目的要求,需要实现从右侧滑出的slidingmenu,且原有界面不能移动,直接被滑出的菜单覆盖。查了相关资料和开源代码,后根据http://www.oschina.net/code/snippet_219356_19035此文章的开源项目,自己修改了个工具类,实现相应的效果。
需注意getScrollX()方法的的作用,我的理解是,获取控件的偏移位置(即0-控件滑动的距离),若初始化后控件并没有移动过,则getScrollX()返回的距离应为0。
有兴趣的朋友也可去上面的链接下载原有的项目研究下。


 * 側滑工具類 ,右側滑動視圖
 * 使用方法:先設置中間的內容佈局,在設置右邊的側滑佈局,方法分別為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);
        }
    }
}

}

你可能感兴趣的:(SlidingMenu,侧滑,右侧)