[UI]抽屉菜单DrawerLayout分析(三)
2015-10-03 17:01
555 查看
在[UI]抽屉菜单DrawerLayout分析(一)和[UI]抽屉菜单DrawerLayout分析(二)中分别介绍了DrawerLayout得基本框架结构和ViewDragerHelper的作用以及手势分发,本文一起来分析其中的Scroller的使用情况。
DragActionMethodFlow
从Scroller一直往上追溯,可以得到如图的调用流程。
当滑动屏幕时,DrawerLayout中的手势分发被触发,先执行onInterceptTouchEvent根据返回结果确定是否执行onTouchEvent,之后就是一些和ViewDragHelper之间的回调接口处理。
接下来追踪一下什么时候从Scroller中取出x,y来使用:
Scroller
在View里面有一个实现为空的computeScroll,DrawerLayout对它进行重写,这个方法应该是在view自动重绘是会被调用,回到continueSettling:
当状态处于STATE_SETTLING时开始获取Scroller中的x,y值,结合当前运动view的left,top位置,计算出偏移量,通过offsetLeftAndRight设置,里面是一些具体的位置改变,挺复杂的。
小结
至此DrawerLayout的基本工作流程分析完毕,简单做一个总结,v4包提供了ViewDragHelper类,里面封装了对scroller合view的位移操作,和Callback接口,通过DrawerLayout内的onInterceptTouchEvent和onTouchEvent的重载,触发ViewDragHelper内的相关方法,同时在DrawerLayout内实现ViewDragHelp.Callback.
作者:小文字
出处:http://www.cnblogs.com/avenwu/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
在ViewDragerHelper中可以发现private ScrollerCompat mScroller;说明抽屉菜单的具体滑动也是依赖于Scroller的使用,检索一下mScroller的引用,定位到forceSettleCapturedViewAt,这个方法回调用Scroller的startScroll来计算位移,它本身适用于计算和保存位移在特定时间的变化情况,最终的在绘制view时我可以获取其保存的x,y坐标值。
/** * Settle the captured view at the given (left, top) position. * * @param finalLeft Target left position for the captured view * @param finalTop Target top position for the captured view * @param xvel Horizontal velocity * @param yvel Vertical velocity * @return true if animation should continue through {@link #continueSettling(boolean)} calls */ private boolean forceSettleCapturedViewAt(int finalLeft, int finalTop, int xvel, int yvel) { final int startLeft = mCapturedView.getLeft(); final int startTop = mCapturedView.getTop(); final int dx = finalLeft - startLeft; final int dy = finalTop - startTop; if (dx == 0 && dy == 0) { // Nothing to do. Send callbacks, be done. mScroller.abortAnimation(); setDragState(STATE_IDLE); returnfalse; } final int duration = computeSettleDuration(mCapturedView, dx, dy, xvel, yvel); mScroller.startScroll(startLeft, startTop, dx, dy, duration); setDragState(STATE_SETTLING); returntrue; }
这里用的是v4扩展包里的ScrollerCompat用于低版本兼容,它继承自ScrollerCompatImpl,可以看到里面主要的方法声明:
interface ScrollerCompatImpl{ Object createScroller(Context context, Interpolator interpolator); boolean isFinished(Object scroller); int getCurrX(Object scroller); int getCurrY(Object scroller); float getCurrVelocity(Object scroller); boolean computeScrollOffset(Object scroller); void startScroll(Object scroller, int startX, int startY, int dx, int dy); void startScroll(Object scroller, int startX, int startY, int dx, int dy, int duration); void fling(Object scroller, int startX, int startY, int velX, int velY, int minX, int maxX, int minY, int maxY); void fling(Object scroller, int startX, int startY, int velX, int velY, int minX, int maxX, int minY, int maxY, int overX, int overY); void abortAnimation(Object scroller); void notifyHorizontalEdgeReached(Object scroller, int startX, int finalX, int overX); void notifyVerticalEdgeReached(Object scroller, int startY, int finalY, int overY); boolean isOverScrolled(Object scroller); int getFinalX(Object scroller); int getFinalY(Object scroller); }
DragActionMethodFlow
从Scroller一直往上追溯,可以得到如图的调用流程。
当滑动屏幕时,DrawerLayout中的手势分发被触发,先执行onInterceptTouchEvent根据返回结果确定是否执行onTouchEvent,之后就是一些和ViewDragHelper之间的回调接口处理。
接下来追踪一下什么时候从Scroller中取出x,y来使用:
Scroller
在View里面有一个实现为空的computeScroll,DrawerLayout对它进行重写,这个方法应该是在view自动重绘是会被调用,回到continueSettling:
/** * Move the captured settling view by the appropriate amount for the current time. * If <code>continueSettling</code> returns true, the caller should call it again * on the next frame to continue. * * @param deferCallbacks true if state callbacks should be deferred via posted message. * Set this to true if you are calling this method from * {@link android.view.View#computeScroll()} or similar methods * invoked as part of layout or drawing. * @return true if settle is still in progress */ public boolean continueSettling(boolean deferCallbacks) { if (mDragState == STATE_SETTLING) { boolean keepGoing = mScroller.computeScrollOffset(); final int x = mScroller.getCurrX(); final int y = mScroller.getCurrY(); final int dx = x - mCapturedView.getLeft(); final int dy = y - mCapturedView.getTop(); if (dx != 0) { mCapturedView.offsetLeftAndRight(dx); } if (dy != 0) { mCapturedView.offsetTopAndBottom(dy); } if (dx != 0 || dy != 0) { mCallback.onViewPositionChanged(mCapturedView, x, y, dx, dy); } if (keepGoing && x == mScroller.getFinalX() && y == mScroller.getFinalY()) { // Close enough. The interpolator/scroller might think we're still moving // but the user sure doesn't. mScroller.abortAnimation(); keepGoing = mScroller.isFinished(); } if (!keepGoing) { if (deferCallbacks) { mParentView.post(mSetIdleRunnable); } else { setDragState(STATE_IDLE); } } } return mDragState == STATE_SETTLING; }
当状态处于STATE_SETTLING时开始获取Scroller中的x,y值,结合当前运动view的left,top位置,计算出偏移量,通过offsetLeftAndRight设置,里面是一些具体的位置改变,挺复杂的。
/** * Offset this view's horizontal location by the specified amount of pixels. * * @param offset the number of pixels to offset the view by */ public void offsetLeftAndRight(int offset) { if (offset != 0) { updateMatrix(); final boolean matrixIsIdentity = mTransformationInfo == null || mTransformationInfo.mMatrixIsIdentity; if (matrixIsIdentity) { if (mDisplayList != null) { invalidateViewProperty(false, false); } else { final ViewParent p = mParent; if (p != null && mAttachInfo != null) { final Rect r = mAttachInfo.mTmpInvalRect; int minLeft; int maxRight; if (offset < 0) { minLeft = mLeft + offset; maxRight = mRight; } else { minLeft = mLeft; maxRight = mRight + offset; } r.set(0, 0, maxRight - minLeft, mBottom - mTop); p.invalidateChild(this, r); } } } else { invalidateViewProperty(false, false); } mLeft += offset; mRight += offset; if (mDisplayList != null) { mDisplayList.offsetLeftAndRight(offset); invalidateViewProperty(false, false); } else { if (!matrixIsIdentity) { invalidateViewProperty(false, true); } invalidateParentIfNeeded(); } } }
小结
至此DrawerLayout的基本工作流程分析完毕,简单做一个总结,v4包提供了ViewDragHelper类,里面封装了对scroller合view的位移操作,和Callback接口,通过DrawerLayout内的onInterceptTouchEvent和onTouchEvent的重载,触发ViewDragHelper内的相关方法,同时在DrawerLayout内实现ViewDragHelp.Callback.
作者:小文字
出处:http://www.cnblogs.com/avenwu/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
相关文章推荐
- GUI - Web前端开发框架
- 评价ui设计作品好坏的八个标准(界面/交互设计研究)
- 为Yahoo! UI Extensions Grid增加内置的可编辑器
- Cocos2d-x UI开发之文本类使用实例
- 在IE 浏览器中使用 jquery的fadeIn() 效果 英文字符字体加粗
- UI Events 用户界面事件
- 基于jQuery UI CSS Framework开发Widget的经验
- jquery ui 1.7 ui.tabs 动态添加与关闭(按钮关闭+双击关闭)
- jQuery UI设置固定日期选择特效代码分享
- jQuery UI的Dialog无法提交问题的解决方法
- jQuery ui实现动感的圆角渐变网站导航菜单效果代码
- 关于jQuery UI 使用心得及技巧
- jQuery ui 1.7更新小结
- 从零开始学习jQuery (十) jQueryUI常用功能实战
- jquery ui对话框实例代码
- jQuery UI AutoComplete 自动完成使用小记
- jQuery UI Autocomplete 体验分享
- Android UI使用HTML布局方法实例
- 浅谈AnDroidDraw+DroidDraw实现Android程序UI设计的分析说明
- aspx实现的 jquery ui 的 flexgrid demo