类似人人网的侧滑动层叠窗口实现及代码
最近由于项目需要要实现类似人人网的侧滑层叠窗口,就是在一个 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
图二