代码讲解Android(安卓)Scroller、VelocityTracker
http://blog.csdn.net/bigconvience/article/details/26735705
http://blog.csdn.net/bigconvience/article/details/26735705
http://blog.csdn.net/bigconvience/article/details/26735705
http://blog.csdn.net/bigconvience/article/details/26735705
代码讲解Android Scroller、VelocityTracker
分类:Android UI 2014-05-23 19:16 388人阅读 评论(0) 收藏 举报 Android 界面在编写自定义滑动控件时常常会用到Android触摸机制和Scroller及VelocityTracker。Android Touch系统简介(二):实例详解onInterceptTouchEvent与onTouchEvent的调用过程对Android触摸机制需要用到的函数进行了详细的解释,本文主要介绍两个重要的类:Scroller及VelocityTracker。利用上述知识,最后给出了一个自定义滑动控件的demo,该demo类似于ImageGallery。ImageGallery一般是用GridView来实现的,可以左右滑动。本例子实现的控件直接继承一个ViewGroup,对其回调函数如 onTouchEvent、onInterceptTouchEvent、computeScroll等进行重载。弄懂该代码,对Android touch的认识将会更深一层。
VelocityTracker:用于对触摸点的速度跟踪,方便获取触摸点的速度。
用法:一般在onTouchEvent事件中被调用,先在down事件中获取一个VecolityTracker对象,然后在move或up事件中获取速度,调用流程可如下列所示:
[java] view plain copy
- VelocityTrackervTracker=null;
- @Override
- publicbooleanonTouchEvent(MotionEventevent){
- intaction=event.getAction();
- switch(action){
- caseMotionEvent.ACTION_DOWN:
- if(vTracker==null){
- vTracker=VelocityTracker.obtain();
- }else{
- vTracker.clear();
- }
- vTracker.addMovement(event);
- break;
- caseMotionEvent.ACTION_MOVE:
- vTracker.addMovement(event);
- //设置单位,1000表示每秒多少像素(pix/second),1代表每微秒多少像素(pix/millisecond)。
- vTracker.computeCurrentVelocity(1000);
- //从左向右划返回正数,从右向左划返回负数
- System.out.println("thexvelocityis"+vTracker.getXVelocity());
- //从上往下划返回正数,从下往上划返回负数
- System.out.println("theyvelocityis"+vTracker.getYVelocity());
- break;
- caseMotionEvent.ACTION_UP:
- caseMotionEvent.ACTION_CANCEL:
- vTracker.recycle();
- break;
- }
- returntrue;
- }
Scroller:用于跟踪控件滑动的轨迹,此类不会移动控件,需要你在View的一个回调函数computerScroll()中使用Scroller对象还获取滑动的数据来控制某个View。
[java] view plain copy
- /**
- *CalledbyaparenttorequestthatachildupdateitsvaluesformScrollX
- *andmScrollYifnecessary.Thiswilltypicallybedoneifthechildis
- *animatingascrollusinga{@linkandroid.widget.ScrollerScroller}
- *object.
- */
- publicvoidcomputeScroll()
- {
- }
下面给出一段代码:
[java] view plain copy
- @Override
- publicvoidcomputeScroll(){
- //TODOAuto-generatedmethodstub
- Log.e(TAG,"computeScroll");
- if(mScroller.computeScrollOffset()){//or!mScroller.isFinished()
- Log.e(TAG,mScroller.getCurrX()+"======"+mScroller.getCurrY());
- scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
- Log.e(TAG,"###getleftis"+getLeft()+"###getRightis"+getRight());
- postInvalidate();
- }
- else
- Log.i(TAG,"havedonethescoller-----");
- }
[java] view plain copy
- /**
- *Callthiswhenyouwanttoknowthenewlocation.Ifitreturnstrue,
- *theanimationisnotyetfinished.
- */
- publicbooleancomputeScrollOffset(){
- if(mFinished){
- returnfalse;
- }
- //滑动已经持续的时间
- inttimePassed=(int)(AnimationUtils.currentAnimationTimeMillis()-mStartTime);
- //若在规定时间还未用完,则继续设置新的滑动位置mCurrX和mCurry
- if(timePassed<mDuration){
- switch(mMode){
- caseSCROLL_MODE:
- floatx=timePassed*mDurationReciprocal;
- if(mInterpolator==null)
- x=viscousFluid(x);
- else
- x=mInterpolator.getInterpolation(x);
- mCurrX=mStartX+Math.round(x*mDeltaX);
- mCurrY=mStartY+Math.round(x*mDeltaY);
- break;
- caseFLING_MODE:
- finalfloatt=(float)timePassed/mDuration;
- finalintindex=(int)(NB_SAMPLES*t);
- floatdistanceCoef=1.f;
- floatvelocityCoef=0.f;
- if(index<NB_SAMPLES){
- finalfloatt_inf=(float)index/NB_SAMPLES;
- finalfloatt_sup=(float)(index+1)/NB_SAMPLES;
- finalfloatd_inf=SPLINE_POSITION[index];
- finalfloatd_sup=SPLINE_POSITION[index+1];
- velocityCoef=(d_sup-d_inf)/(t_sup-t_inf);
- distanceCoef=d_inf+(t-t_inf)*velocityCoef;
- }
- mCurrVelocity=velocityCoef*mDistance/mDuration*1000.0f;
- mCurrX=mStartX+Math.round(distanceCoef*(mFinalX-mStartX));
- //PintomMinX<=mCurrX<=mMaxX
- mCurrX=Math.min(mCurrX,mMaxX);
- mCurrX=Math.max(mCurrX,mMinX);
- mCurrY=mStartY+Math.round(distanceCoef*(mFinalY-mStartY));
- //PintomMinY<=mCurrY<=mMaxY
- mCurrY=Math.min(mCurrY,mMaxY);
- mCurrY=Math.max(mCurrY,mMinY);
- if(mCurrX==mFinalX&&mCurrY==mFinalY){
- mFinished=true;
- }
- break;
- }
- }
- else{
- mCurrX=mFinalX;
- mCurrY=mFinalY;
- mFinished=true;
- }
- returntrue;
- }
当我们执行ontouch或invalidate()或postInvalidate()都会导致这个方法的执行。
我们在开发控件时,常会有这样的需求:当单机某个按钮时,某个图片会在规定的时间内滑出窗口,而不是一下子进入窗口。实现这个功能可以使用Scroller来实现。
下面给出一段代码,该代码控制下一个界面在3秒时间内缓慢进入的效果。
[java] view plain copy
- publicvoidmoveToRightSide(){
- if(curScreen<=0){
- return;
- }
- curScreen--;
- Log.i(TAG,"----moveToRightSide----curScreen"+curScreen);
- mScroller.startScroll((curScreen+1)*getWidth(),0,-getWidth(),0,3000);
- scrollTo(curScreen*getWidth(),0);
- invalidate();
- }
当startScroll执行过程中即在duration时间内,computeScrollOffset 方法会一直返回true,但当动画执行完成后会返回返加false.
这个函数的源码如下所示,主要用于设置滑动参数
[java] view plain copy
- /**
- *Startscrollingbyprovidingastartingpoint,thedistancetotravel,
- *andthedurationofthescroll.
- *
- *@paramstartXStartinghorizontalscrolloffsetinpixels.Positive
- *numberswillscrollthecontenttotheleft.
- *@paramstartYStartingverticalscrolloffsetinpixels.Positivenumbers
- *willscrollthecontentup.
- *@paramdxHorizontaldistancetotravel.Positivenumberswillscrollthe
- *contenttotheleft.
- *@paramdyVerticaldistancetotravel.Positivenumberswillscrollthe
- *contentup.
- *@paramdurationDurationofthescrollinmilliseconds.
- */
- publicvoidstartScroll(intstartX,intstartY,intdx,intdy,intduration){
- mMode=SCROLL_MODE;
- mFinished=false;
- mDuration=duration;
- mStartTime=AnimationUtils.currentAnimationTimeMillis();
- mStartX=startX;
- mStartY=startY;
- mFinalX=startX+dx;
- mFinalY=startY+dy;
- mDeltaX=dx;
- mDeltaY=dy;
- mDurationReciprocal=1.0f/(float)mDuration;
- }
附上完整的实例代码:
自定义Android可滑动控件源码
运行效果图如下,滑动屏幕会显示不同的图片。更多 0
- 顶
- 0
- 踩
更多相关文章
- Android应用程序启动过程源代码分析(2)
- 《Android系统学习》第十章:Android消息处理、消息循环和消息队列
- NDK C++线程中如何调用JAVA API
- Android(安卓)Audio代码分析23 - attachAuxEffect函数
- Android(安卓)服务(本地服务示例)(二)
- [Android官方Demo系列] PageTransformer缩放滑动
- Android(安卓)Audio代码分析23 - attachAuxEffect函数
- 【笔记】android捕获触摸事件
- 箭头函数的基础使用