类似人人网的侧滑动层叠窗口实现及代码


最近由于项目需要要实现类似人人网的侧滑层叠窗口,就是在一个 activity 上能再滑动的窗口,能部分或全部遮挡住下面的view
与之前的滑动功能不同,以前的滑动是采用一个 view 滑开,另一个滑入来。现在的需求不一样需要实现侧滑层叠的样式。
按需要下载了人人网的 android 客户端,并反编译后研究相关的实现。这是现在最游行的移动应用设计的方法。

效果图:

 

核心类现实

public class FlipperLayout extends ViewGroup {

        private Scroller mScroller;
        private VelocityTracker mVelocityTracker;
        private int mWidth;

        public static final int SCREEN_STATE_CLOSE = 0;
        public static final int SCREEN_STATE_OPEN = 1;
        public static final int TOUCH_STATE_RESTART = 0;
        public static final int TOUCH_STATE_SCROLLING = 1;
        public static final int SCROLL_STATE_NO_ALLOW = 0;
        public static final int SCROLL_STATE_ALLOW = 1;
        private int mScreenState = 0;
        private int mTouchState = 0;
        private int mScrollState = 0;
        private int mVelocityValue = 0;
        private boolean mOnClick = false;

        public FlipperLayout(Context context) {
                super(context);
                mScroller = new Scroller(context);
                mWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                                54, getResources().getDisplayMetrics());

        }

        public FlipperLayout(Context <a href="www.yidin.net">context</a>, AttributeSet attrs, int defStyle) {
                super(context, attrs, defStyle);
        }

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

        protected void onLayout(boolean changed, int l, int t, int r, int b) {
                for (int i = 0; i < getChildCount(); i++) {
                        View child = getChildAt(i);
                        int height = child.getMeasuredHeight();
                        int width = child.getMeasuredWidth();
                        child.layout(0, 0, width, height);
                }
        }

        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
                int width = MeasureSpec.getSize(widthMeasureSpec);
                int height = MeasureSpec.getSize(heightMeasureSpec);
                setMeasuredDimension(width, height);
                for (int i = 0; i < getChildCount(); i++) {
                        getChildAt(i).measure(widthMeasureSpec, <a href="www.yidin.net">heightMeasureSpec</a>);
                }
        }

        public boolean dispatchTouchEvent(MotionEvent ev) {
                obtainVelocityTracker(ev);
                switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                        mTouchState = mScroller.isFinished() ? TOUCH_STATE_RESTART
                                        : TOUCH_STATE_SCROLLING;
                        if (mTouchState == TOUCH_STATE_RESTART) {
                                int x = (int) ev.getX();
                                int screenWidth = getWidth();
                                if (x <= mWidth && mScreenState == SCREEN_STATE_CLOSE
                                                && mTouchState == TOUCH_STATE_RESTART
                                                || x >= screenWidth - mWidth
                                                && mScreenState == SCREEN_STATE_OPEN
                                                && mTouchState == TOUCH_STATE_RESTART) {
                                        if (mScreenState == SCREEN_STATE_OPEN) {
                                                mOnClick = true;
                                        }
                                        mScrollState = SCROLL_STATE_ALLOW;
                                } else {
                                        mOnClick = false;
                                        mScrollState = SCROLL_STATE_NO_ALLOW;
                                }
                        } else {
                                return false;
                        }
                        break;
                case MotionEvent.ACTION_MOVE:
                        mVelocityTracker.computeCurrentVelocity(1000,
                                        ViewConfiguration.getMaximumFlingVelocity());
                        if (mScrollState == SCROLL_STATE_ALLOW
                                        && getWidth() - (int) ev.getX() < mWidth) {
                                return true;
                        }
                        break;
                case MotionEvent.ACTION_UP:
                        releaseVelocityTracker();
                        if (mOnClick) {
                                mOnClick = false;
                                mScreenState = SCREEN_STATE_CLOSE;
                                mScroller.startScroll(getChildAt(1).getScrollX(), 0,
                                                -getChildAt(1).getScrollX(), 0, 800);
                                invalidate();
                        }
                        break;
                }
                return super.dispatchTouchEvent(ev);
        }

        public boolean onInterceptTouchEvent(MotionEvent ev) {
                obtainVelocityTracker(ev);
                switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                        mTouchState = mScroller.isFinished() ? TOUCH_STATE_RESTART
                                        : TOUCH_STATE_SCROLLING;
                        if (mTouchState == TOUCH_STATE_SCROLLING) {
                                return false;
                        }
                        break;

                case MotionEvent.ACTION_MOVE:
                        mOnClick = false;
                        mVelocityTracker.computeCurrentVelocity(1000,
                                        ViewConfiguration.getMaximumFlingVelocity());
                        if (mScrollState == SCROLL_STATE_ALLOW
                                        && Math.abs(mVelocityTracker.getXVelocity()) > 200) {
                                return true;
                        }
                        break;

                case MotionEvent.ACTION_UP:
                        releaseVelocityTracker();
                        if (mScrollState == SCROLL_STATE_ALLOW
                                        && mScreenState == <a href="www.yidin.net">SCREEN_STATE_OPEN</a>) {
                                return true;
                        }
                        break;
                }
                return super.onInterceptTouchEvent(ev);
        }

        public boolean onTouchEvent(MotionEvent event) {
                obtainVelocityTracker(event);
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                        mTouchState = mScroller.isFinished() ? TOUCH_STATE_RESTART
                                        : TOUCH_STATE_SCROLLING;
                        if (mTouchState == TOUCH_STATE_SCROLLING) {
                                return false;
                        }
                        break;

                case MotionEvent.ACTION_MOVE:
                        mVelocityTracker.computeCurrentVelocity(1000,
                                        ViewConfiguration.getMaximumFlingVelocity());
                        mVelocityValue = (int) mVelocityTracker.getXVelocity();
                        getChildAt(1).scrollTo(-(int) event.getX(), 0);
                        break;

                case MotionEvent.ACTION_UP:
                        if (mScrollState == SCROLL_STATE_ALLOW) {
                                if (mVelocityValue > 2000) {
                                        mScreenState = SCREEN_STATE_OPEN;
                                        mScroller
                                                        .startScroll(
                                                                        getChildAt(1).getScrollX(),
                                                                        0,
                                                                        -(getWidth()
                                                                                        - Math.abs(getChildAt(1)
                                                                                                        .getScrollX()) -

                                                                        mWidth), 0, 250);
                                        invalidate();

                                } else if (mVelocityValue < -2000) {
                                        mScreenState = SCREEN_STATE_CLOSE;
                                        mScroller.startScroll(getChildAt(1).getScrollX(), 0,
                                                        -getChildAt(1).getScrollX(), 0, 250);
                                        invalidate();
                                } else if (event.getX() < getWidth() / 2) {
                                        mScreenState = SCREEN_STATE_CLOSE;
                                        mScroller.startScroll(getChildAt(1).getScrollX(), 0,
                                                        -getChildAt(1).getScrollX(), 0, 800);
                                        invalidate();
                                } else {
                                        mScreenState = SCREEN_STATE_OPEN;
                                        mScroller
                                                        .startScroll(
                                                                        getChildAt(1).getScrollX(),
                                                                        0,
                                                                        -(getWidth()
                                                                                        - Math.abs(getChildAt(1)
                                                                                                        .getScrollX()) -

                                                                        mWidth), 0, 800);
                                        invalidate();
                                }
                        }
                        break;
                }
                return super.onTouchEvent(event);
        }

        public void open() {
                mTouchState = mScroller.<a href="www.yidin.net">isFinished</a>() ? TOUCH_STATE_RESTART
                                : TOUCH_STATE_SCROLLING;
                if (mTouchState == TOUCH_STATE_RESTART) {
                        mScreenState = SCREEN_STATE_OPEN;
                        mScroller.startScroll(getChildAt(1).getScrollX(), 0, -(getWidth()
                                        - Math.abs(getChildAt(1).getScrollX()) -

                        mWidth), 0, 800);
                        invalidate();
                }
        }

        public void close(View view) {
                mScreenState = SCREEN_STATE_CLOSE;
                mScroller.startScroll(getChildAt(1).getScrollX(), 0, -getChildAt(1)
                                .getScrollX(), 0, 800);
                invalidate();
                setContentView(view);
        }

        public void computeScroll() {
                super.computeScroll();
                if (mScroller.computeScrollOffset()) {
                        getChildAt(1).scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
                        postInvalidate();
                }
        }

        private void obtainVelocityTracker(MotionEvent event) {
                if (mVelocityTracker == null) {
                        mVelocityTracker = VelocityTracker.obtain();
                }
                mVelocityTracker.addMovement(<a href="www.yidin.net">event</a>);
        }

        private void releaseVelocityTracker() {
                if (mVelocityTracker != null) {
                        mVelocityTracker.recycle();
                        mVelocityTracker = null;
                }
        }

        public int getScreenState() {
                return mScreenState;
        }

        public void setContentView(View view) {
                removeViewAt(1);
                addView(view, 1, getLayoutParams());
        }

        public interface OnOpenListener {
                public abstract void open();
        }

        public interface OnCloseListener {
                public abstract void <a href="www.yidin.net">close</a>();
        }
}

 

这个类主要实现层叠窗口的效果,有需要的同学可以研究一下相关实现,实现不难就是要理解相关的思路。

更多相关的资料请到我的博客www.yidin.net 留言
本文地址: http://www.yidin.net/discuz/foru ... read&tid=187&extra=

欢迎各位同学加入 android 技术二群 222392467  

 

图二

posted on 2013-03-28 09:31  梁DH  阅读(1106)  评论(3编辑  收藏  举报

导航