如何通过滑动屏幕电脑控制手机屏幕滑动物体移动

& & & & 转载请注明出处:
& & & & 前言: &虽然本文标题的有点标题党的感觉,但无论如何,通过这篇文章的学习以及你自己的实践认知,写个简单的滑屏小
&&&Demo还是just&so so的。
&&&&&&& 友情提示:
&&&&&&&&&&& 在继续往下面读之前,希望您对以下知识点有一定程度掌握,否则,继续看下去对您意义也不大。
&&&&&&&&&&&& 1、掌握View(视图)的"视图坐标"以及"布局坐标",以及scrollTo()和scrollBy()方法的作用&-----&必须理解
&&&&&&&&&&&&&&&&&&&&& 如果对这方面知识不太清楚的话,建议先看看我的这篇博客
& & & & & & & & & & & & &&,&
& & & & & & & & & &不夸张地说,这篇博客理论上来说是我们这篇博文的基础。
&&&&&&&&&&&& 2、知道onInterceptTouchEvent()以及onTouchEvent()对触摸事件的分发流程&&&& & &&---- 不是必须
&&&&&&&&&&&& 3、知道怎么绘制自定义ViewGroup即可&&&&&&&&&&&&& & & & & & & & & & & & & & ---- 不是必须
&&&& OK。 继续往下看,请一定有所准备 。大家跟着我一步一步来咯。
&知识点一:& 关于scrollTo()和scrollBy()以及偏移坐标的设置/取值问题
&&&&&&& 在前面一篇博文中《》,我们掌握了scrollTo()和
scrollBy()方法的作用,这两个方法的主要作用是将View/ViewGroup移至指定的坐标中,并且将偏移量保存起来。另外:
&&&&&&&&&&&&&&&&& mScrollX 代表X轴方向的偏移坐标
&&&&&&&&&&&&&&&&& mScrollY 代表Y轴方向的偏移坐标
&&&&&&&&&&关于偏移量的设置我们可以参看下源码:
package&com.qin.&&
public&class&View&{&&
&&&&....&&
&&&&protected&int&mScrollX;&&&&&
&&&&protected&int&mScrollY;&&&&&
&&&&public&final&int&getScrollX()&{&&
&&&&&&&&return&mScrollX;&&
&&&&public&final&int&getScrollY()&{&&
&&&&&&&&return&mScrollY;&&
&&&&public&void&scrollTo(int&x,&int&y)&{&&
&&&&&&&&&&
&&&&&&&&if&(mScrollX&!=&x&||&mScrollY&!=&y)&{&&
&&&&&&&&&&&&int&oldX&=&mScrollX;&&
&&&&&&&&&&&&int&oldY&=&mScrollY;&&
&&&&&&&&&&&&mScrollX&=&x;&&&&
&&&&&&&&&&&&mScrollY&=&y;&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&onScrollChanged(mScrollX,&mScrollY,&oldX,&oldY);&&
&&&&&&&&&&&&if&(!awakenScrollBars())&{&&
&&&&&&&&&&&&&&&&invalidate();&&&&
&&&&&&&&&&&&}&&
&&&&&&&&}&&
&&&&public&void&scrollBy(int&x,&int&y)&{&&
&&&&&&&&scrollTo(mScrollX&+&x,&mScrollY&+&y);&&
&&&& 于是,在任何时刻我们都可以获取该View/ViewGroup的偏移位置了,即调用getScrollX()方法和getScrollY()方法
&知识点二: Scroller类的介绍
&&&& & & 在初次看Launcher滑屏的时候,我就对Scroller类的学习感到非常蛋疼,完全失去了继续研究的欲望。如今,没得办法,
&&得重新看Launcher模块,基本上将Launcher大部分类以及功能给掌握了。当然,也花了一天时间来学习Launcher里的滑屏实现
&,基本上业是拨开云雾见真知了。
&&& && 我们知道想把一个View偏移至指定坐标(x,y)处,利用scrollTo()方法直接调用就OK了,但我们不能忽视的是,该方法本身
&& 来的的副作用:非常迅速的将View/ViewGroup偏移至目标点,而没有对这个偏移过程有任何控制,对用户而言可能是不太
&& 友好的。于是,基于这种偏移控制,Scroller类被设计出来了,该类的主要作用是为偏移过程制定一定的控制流程(后面我们会
&& 知道的更多),从而使偏移更流畅,更完美。
&&&&&可能上面说的比较悬乎,道理也没有讲透。下面我就根据特定情景帮助大家分析下:
&&&&&&&&情景:&从上海如何到武汉?
&& &&&&&&&&&普通的人可能会想,so easy : 飞机、轮船、11路公交车...
&&&&&&&&&&& 文艺的人可能会想,& 小 case : 时空忍术(火影的招数)、翻个筋斗(孙大圣的招数)...
&&&& 不管怎么样,我们想出来的套路可能有两种:
&&&&&&&&&&&&&& 1、有个时间控制过程才能抵达(缓慢的前进) & & & & & & & & & & & & & & &-----&&&& 对应于Scroller的作用
&&&&&&&&&&&&&&&&&&&&&&假设做火车,这个过程可能包括: 火车速率,花费周期等;
&&&&&&&&&&&&&& 2、瞬间抵达(超神太快了,都眩晕了,用户体验不太好) & & & & & & & & & & ------&& 对应于scrollTo()的作用
&&&&模拟Scroller类的实现功能:
&&&&&& &假设从上海做动车到武汉需要10个小时,行进距离为1000km ,火车速率200/h 。采用第一种时间控制方法到达武汉的
& &整个配合过程可能如下:
&&&&&&&&我们每隔一段时间(例如1小时),计算火车应该行进的距离,然后调用scrollTo()方法,行进至该处。10小时过完后,
&&&&我们也就达到了目的地了。
&&& 相信大家心里应该有个感觉了。我们就分析下源码里去看看Scroller类的相关方法.
&&&&&其源代码(部分)如下: 路径位于&\frameworks\base\core\java\android\widget\Scroller.java
public&class&Scroller&&{&&
&&&&private&int&mStartX;&&&&&&
&&&&private&int&mStartY;&&&&&&
&&&&private&int&mCurrX;&&&&&&&
&&&&private&int&mCurrY;&&&&&&&
&&&&private&float&mDeltaX;&&&&
&&&&private&float&mDeltaY;&&&&
&&&&private&boolean&mF&&&&
&&&&public&Scroller(Context&context)&{&&
&&&&&&&&this(context,&null);&&
&&&&public&final&boolean&isFinished()&{&&
&&&&&&&&return&mF&&
&&&&public&final&void&forceFinished(boolean&finished)&{&&
&&&&&&&&mFinished&=&&&
&&&&public&final&int&getCurrX()&{&&
&&&&&&&&return&mCurrX;&&
&&&&public&boolean&computeScrollOffset()&{&&
&&&&&&&&if&(mFinished)&{&&&&
&&&&&&&&&&&&return&false;&&
&&&&&&&&}&&
&&&&&&&&int&timePassed&=&(int)(AnimationUtils.currentAnimationTimeMillis()&-&mStartTime);&&
&&&&&&&&if&(timePassed&&&mDuration)&{&&
&&&&&&&&&&&&switch&(mMode)&{&&
&&&&&&&&&&&&case&SCROLL_MODE:&&
&&&&&&&&&&&&&&&&float&x&=&(float)timePassed&*&mDurationR&&
&&&&&&&&&&&&&&&&...&&
&&&&&&&&&&&&&&&&mCurrX&=&mStartX&+&Math.round(x&*&mDeltaX);&&
&&&&&&&&&&&&&&&&mCurrY&=&mStartY&+&Math.round(x&*&mDeltaY);&&
&&&&&&&&&&&&&&&&break;&&
&&&&&&&&&&&&...&&
&&&&&&&&}&&
&&&&&&&&else&{&&
&&&&&&&&&&&&mCurrX&=&mFinalX;&&
&&&&&&&&&&&&mCurrY&=&mFinalY;&&
&&&&&&&&&&&&mFinished&=&true;&&
&&&&&&&&}&&
&&&&&&&&return&true;&&
&&&&public&void&startScroll(int&startX,&int&startY,&int&dx,&int&dy,&int&duration)&{&&
&&&&&&&&mFinished&=&false;&&
&&&&&&&&mDuration&=&&&
&&&&&&&&mStartTime&=&AnimationUtils.currentAnimationTimeMillis();&&
&&&&&&&&mStartX&=&startX;&&&&&&&mStartY&=&startY;&&
&&&&&&&&mFinalX&=&startX&+&&&mFinalY&=&startY&+&&&
&&&&&&&&mDeltaX&=&&&&&&&&&&&&&mDeltaY&=&&&
&&&&&&&&...&&
& & &其中比较重要的两个方法为:
& & & & & &&public void startScroll(int startX, int startY, int dx, int dy, int duration)
& & & & & & & & & &函数功能说明:根据当前已经消逝的时间计算当前的坐标点,保存在mCurrX和mCurrY值中
& & & & & &&public void startScroll(int startX, int startY, int dx, int dy, int duration)
& & & & & & & & & 函数功能说明:开始一个动画控制,由(startX , startY)在duration时间内前进(dx,dy)个单位,到达坐标为
& & & & & & & & & & & (startX+dx , startY+dy)处。
& & & &&PS : 强烈建议大家看看该类的源码,便于后续理解。
知识点二:&computeScroll()方法介绍
&&&&&& 为了易于控制滑屏控制,Android框架提供了&computeScroll()方法去控制这个流程。在绘制View时,会在draw()过程调用该
& 方法。因此,&再配合使用Scroller实例,我们就可以获得当前应该的偏移坐标,手动使View/ViewGroup偏移至该处。
&&&&&computeScroll()方法原型如下,该方法位于ViewGroup.java类中& & &&
由父视图调用用来请求子视图根据偏移值&mScrollX,mScrollY重新绘制&&
&&&&public&void&computeScroll()&{&&&
&&&&&&&&&&
&&&&&&&&&&为了实现偏移控制,一般自定义View/ViewGroup都需要重载该方法 。
&&&& 其调用过程位于View绘制流程draw()过程中,如下:
@Override&&
protected&void&dispatchDraw(Canvas&canvas){&&
&&&&for&(int&i&=&0;&i&&&&i++)&{&&
&&&&&&&&final&View&child&=&children[getChildDrawingOrder(count,&i)];&&
&&&&&&&&if&((child.mViewFlags&&&VISIBILITY_MASK)&==&VISIBLE&||&child.getAnimation()&!=&null)&{&&
&&&&&&&&&&&&more&|=&drawChild(canvas,&child,&drawingTime);&&
&&&&&&&&}&&
protected&boolean&drawChild(Canvas&canvas,&View&child,&long&drawingTime)&{&&
&&&&puteScroll();&&
&& Demo说明:
&&&&&&&& & 我们简单的复用了之前写的一个自定义ViewGroup,与以前一次有区别的是,我们没有调用scrollTo()方法去进行瞬间
&&&&&& 偏移。&本次做法如下:
&&&&&&&&&&&&&&&&&& 第一、调用Scroller实例去产生一个偏移控制(对应于startScroll()方法)
&&&&&&&&&&&&&&& && 第二、手动调用invalid()方法去重新绘制,剩下的就是在&computeScroll()里根据当前已经逝去的时间,获取当前
&&&&&&&&&&&&&&&&&&&&&& 应该偏移的坐标(由Scroller实例对应的computeScrollOffset()计算而得),
&&&&&&&&&&&&&&&&&& 第三、当前应该偏移的坐标,调用scrollBy()方法去缓慢移动至该坐标处。
&&截图如下:
& & & & & & & & & & & & & & & &&& & & & & & & & & & & & &
& & & & & & & & & & & & & & & & & & & &&&原始界面 & & & & & & & & & & & & & & & & & & 点击按钮或者触摸屏之后的显示界面
& & &&& 附:由于滑动截屏很难,只是简单的截取了两个个静态图片,触摸的话可以实现左右滑动切屏了。
&&&&&&&&&&&更多知识点,请看代码注释。。
public&class&MultiViewGroup&extends&ViewGroup&{&&
&&&&public&void&startMove(){&&
&&&&&&&&curScreen&++&;&&
&&&&&&&&Log.i(TAG,&"----startMove----&curScreen&"&+&curScreen);&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&mScroller.startScroll((curScreen-1)&*&getWidth(),&0,&getWidth(),&0,3000);&&
&&&&&&&&&&
&&&&&&&&invalidate();&&
&&&&&&&&&&
&&&&&&&&&&
&&&&@Override&&
&&&&public&void&computeScroll()&{&&&&&
&&&&&&&&&&
&&&&&&&&Log.e(TAG,&"computeScroll");&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&if&(puteScrollOffset())&{&&
&&&&&&&&&&&&Log.e(TAG,&mScroller.getCurrX()&+&"======"&+&mScroller.getCurrY());&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&scrollTo(mScroller.getCurrX(),&mScroller.getCurrY());&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&Log.e(TAG,&"###&getleft&is&"&+&getLeft()&+&"&###&getRight&is&"&+&getRight());&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&postInvalidate();&&
&&&&&&&&}&&
&&&&&&&&else&&
&&&&&&&&&&&&Log.i(TAG,&"have&done&the&scoller&-----");&&
&&&&public&void&stopMove(){&&
&&&&&&&&&&
&&&&&&&&Log.v(TAG,&"----stopMove&----");&&
&&&&&&&&&&
&&&&&&&&if(mScroller&!=&null){&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&if(!mScroller.isFinished()){&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&int&scrollCurX=&mScroller.getCurrX()&;&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&int&descScreen&=&(&scrollCurX&+&getWidth()&/&2)&/&getWidth()&;&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&Log.i(TAG,&"-mScroller.is&not&finished&scrollCurX&+"&+&scrollCurX);&&
&&&&&&&&&&&&&&&&Log.i(TAG,&"-mScroller.is&not&finished&descScreen&+"&+&descScreen);&&
&&&&&&&&&&&&&&&&mScroller.abortAnimation();&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&scrollTo(descScreen&*getWidth()&,&0);&&
&&&&&&&&&&&&&&&&curScreen&=&descScreen&;&&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&else&&
&&&&&&&&&&&&&&&&Log.i(TAG,&"----OK&mScroller.is&&finished&----&");&&
&&&&&&&&}&&&&&
&如何实现触摸滑屏?&
&&&&& 其实网上有很多关于Launcher实现滑屏的博文,基本上也把道理阐释的比较明白了 。我这儿也是基于自己的理解,将一些
&重要方面的知识点给补充下,希望能帮助大家理解。
&&&&& 想要实现滑屏操作,值得考虑的事情包括如下几个方面:
& &&&&& 其中:onInterceptTouchEvent()主要功能是控制触摸事件的分发,例如是子视图的点击事件还是滑动事件。
&&&&&&& 其他所有处理过程均在onTouchEvent()方法里实现了。
&&&&&&&&&&& 1、屏幕的滑动要根据手指的移动而移动& ---- 主要实现在onTouchEvent()方法中
&&&&&&&&&& &2、当手指松开时,可能我们并没有完全滑动至某个屏幕上,这是我们需要手动判断当前偏移至去计算目标屏(当前屏或者
&&&&&&&&&& &&& 前后屏),并且优雅的偏移到目标屏(当然是用Scroller实例咯)。
&&&&&&&&& &3、调用computeScroll&()去实现缓慢移动过程。
& 知识点介绍:&&&&&&&&&&&&&&
& & VelocityTracker类
&&&&&&&&&& 功能:&&根据触摸位置计算每像素的移动速率。
&&&&&&&&&& 常用方法有:&&&&&
& & & & & & & & & & &public void&addMovement&(MotionEvent&ev)
& & & & & & & & & &功能:添加触摸对象MotionEvent , 用于计算触摸速率。 &&
& & & & & &&public void&computeCurrentVelocity&(int units)
& & & & & & & & & &功能:以每像素units单位考核移动速率。额,其实我也不太懂,赋予值1000即可。
& & & & & & & & & &参照源码 该units的意思如下:
& & & & & & & & & & & & & &参数&units : The units you would like the velocity in. &A value of 1& & & & & & & & & & & & & & &provides pixels per millisecond, 1000 provides pixels per second, etc.
& & & & & &&public float&getXVelocity&()
& & & & & & & & & & & & &&&功能:获得X轴方向的移动速率。
& & ViewConfiguration类
& & & & & &功能: 获得一些关于timeouts(时间)、sizes(大小)、distances(距离)的标准常量值 。
& & & & & &常用方法:
& & & & & & & & &&public int&getScaledEdgeSlop()
& & & & & & & & & & & 说明:获得一个触摸移动的最小像素值。也就是说,只有超过了这个值,才代表我们该滑屏处理了。
& & & & & & & &&&public static int&getLongPressTimeout()
& & & & & & & & & & &说明:获得一个执行长按事件监听(onLongClickListener)的值。也就是说,对某个View按下触摸时,只有超过了
&&&&&&&& 这个时间值在,才表示我们该对该View回调长按事件了;否则,小于这个时间点松开手指,只执行onClick监听
& & & &&我能写下来的也就这么多了,更多的东西参考代码注释吧。 在掌握了上面我罗列的知识后(重点scrollTo、Scroller类),
& &&其他方面的知识都是关于点与点之间的计算了以及触摸事件的分发了。这方面感觉也没啥可写的。
public&class&MultiViewGroup&extends&ViewGroup&{&&
&&&&private&static&String&TAG&=&"MultiViewGroup";&&
&&&&private&int&curScreen&=&0&;&&&&
&&&&private&Scroller&mScroller&=&null&;&&&
&&&&public&MultiViewGroup(Context&context)&{&&
&&&&&&&&super(context);&&
&&&&&&&&mContext&=&&&
&&&&&&&&init();&&
&&&&public&MultiViewGroup(Context&context,&AttributeSet&attrs)&{&&
&&&&&&&&super(context,&attrs);&&
&&&&&&&&mContext&=&&&
&&&&&&&&init();&&
&&&&private&void&init()&{&&&&&
&&&&&&&&...&&
&&&&&&&&&&
&&&&&&&&mScroller&=&new&Scroller(mContext);&&
&&&&&&&&&&
&&&&&&&&...&&
&&&&&&&&&&
&&&&&&&&mTouchSlop&=&ViewConfiguration.get(getContext()).getScaledTouchSlop();&&
&&&&@Override&&
&&&&public&void&computeScroll()&{&&&&&
&&&&&&&&&&
&&&&&&&&Log.e(TAG,&"computeScroll");&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&if&(puteScrollOffset())&{&&
&&&&&&&&&&&&Log.e(TAG,&mScroller.getCurrX()&+&"======"&+&mScroller.getCurrY());&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&scrollTo(mScroller.getCurrX(),&mScroller.getCurrY());&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&Log.e(TAG,&"###&getleft&is&"&+&getLeft()&+&"&###&getRight&is&"&+&getRight());&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&postInvalidate();&&
&&&&&&&&}&&
&&&&&&&&else&&
&&&&&&&&&&&&Log.i(TAG,&"have&done&the&scoller&-----");&&
&&&&private&static&final&int&TOUCH_STATE_REST&=&0;&&&&
&&&&private&static&final&int&TOUCH_STATE_SCROLLING&=&1;&&&&
&&&&private&int&mTouchState&=&TOUCH_STATE_REST;&&&
&&&&public&static&int&&SNAP_VELOCITY&=&600&;&&&&
&&&&private&int&mTouchSlop&=&0&;&&&&&&&&&&&&&&&&
&&&&private&float&mLastionMotionX&=&0&;&&&&&&&&&
&&&&private&VelocityTracker&mVelocityTracker&=&null&;&&
&&&&@Override&&
&&&&public&boolean&onInterceptTouchEvent(MotionEvent&ev)&{&&
&&&&&&&&&&
&&&&&&&&Log.e(TAG,&"onInterceptTouchEvent-slop:"&+&mTouchSlop);&&
&&&&&&&&final&int&action&=&ev.getAction();&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&if&((action&==&MotionEvent.ACTION_MOVE)&&&&(mTouchState&!=&TOUCH_STATE_REST))&{&&
&&&&&&&&&&&&return&true;&&
&&&&&&&&}&&
&&&&&&&&&&
&&&&&&&&final&float&x&=&ev.getX();&&
&&&&&&&&final&float&y&=&ev.getY();&&
&&&&&&&&switch&(action)&{&&
&&&&&&&&case&MotionEvent.ACTION_MOVE:&&
&&&&&&&&&&&&Log.e(TAG,&"onInterceptTouchEvent&move");&&
&&&&&&&&&&&&final&int&xDiff&=&(int)&Math.abs(mLastionMotionX&-&x);&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&if&(xDiff&&&mTouchSlop)&{&&
&&&&&&&&&&&&&&&&mTouchState&=&TOUCH_STATE_SCROLLING;&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&break;&&
&&&&&&&&case&MotionEvent.ACTION_DOWN:&&
&&&&&&&&&&&&Log.e(TAG,&"onInterceptTouchEvent&down");&&
&&&&&&&&&&&&mLastionMotionX&=&x;&&
&&&&&&&&&&&&mLastMotionY&=&y;&&
&&&&&&&&&&&&Log.e(TAG,&mScroller.isFinished()&+&"");&&
&&&&&&&&&&&&mTouchState&=&mScroller.isFinished()&?&TOUCH_STATE_REST&:&TOUCH_STATE_SCROLLING;&&
&&&&&&&&&&&&break;&&
&&&&&&&&case&MotionEvent.ACTION_CANCEL:&&
&&&&&&&&case&MotionEvent.ACTION_UP:&&
&&&&&&&&&&&&Log.e(TAG,&"onInterceptTouchEvent&up&or&cancel");&&
&&&&&&&&&&&&mTouchState&=&TOUCH_STATE_REST;&&
&&&&&&&&&&&&break;&&
&&&&&&&&}&&
&&&&&&&&Log.e(TAG,&mTouchState&+&"===="&+&TOUCH_STATE_REST);&&
&&&&&&&&return&mTouchState&!=&TOUCH_STATE_REST;&&
&&&&public&boolean&onTouchEvent(MotionEvent&event){&&
&&&&&&&&super.onTouchEvent(event);&&
&&&&&&&&&&
&&&&&&&&Log.i(TAG,&"---&onTouchEvent--&&"&);&&
&&&&&&&&&&
&&&&&&&&Log.e(TAG,&"onTouchEvent&start");&&
&&&&&&&&&&
&&&&&&&&if&(mVelocityTracker&==&null)&{&&
&&&&&&&&&&&&mVelocityTracker&=&VelocityTracker.obtain();&&
&&&&&&&&}&&
&&&&&&&&mVelocityTracker.addMovement(event);&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&float&x&=&event.getX();&&
&&&&&&&&float&y&=&event.getY();&&
&&&&&&&&switch(event.getAction()){&&
&&&&&&&&case&MotionEvent.ACTION_DOWN:&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&if(mScroller&!=&null){&&
&&&&&&&&&&&&&&&&if(!mScroller.isFinished()){&&
&&&&&&&&&&&&&&&&&&&&mScroller.abortAnimation();&&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&mLastionMotionX&=&x&;&&&
&&&&&&&&&&&&break&;&&
&&&&&&&&case&MotionEvent.ACTION_MOVE:&&
&&&&&&&&&&&&int&detaX&=&(int)(mLastionMotionX&-&x&);&&&
&&&&&&&&&&&&scrollBy(detaX,&0);&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&Log.e(TAG,&"---&MotionEvent.ACTION_MOVE--&&detaX&is&"&+&detaX&);&&
&&&&&&&&&&&&mLastionMotionX&=&x&;&&
&&&&&&&&&&&&break&;&&
&&&&&&&&case&MotionEvent.ACTION_UP:&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&final&VelocityTracker&velocityTracker&=&mVelocityTracker&&;&&
&&&&&&&&&&&&puteCurrentVelocity(1000);&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&int&velocityX&=&(int)&velocityTracker.getXVelocity()&;&&&&
&&&&&&&&&&&&Log.e(TAG&,&"---velocityX---"&+&velocityX);&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&if&(velocityX&&&SNAP_VELOCITY&&&&curScreen&&&0)&{&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&Log.e(TAG,&"snap&left");&&
&&&&&&&&&&&&&&&&snapToScreen(curScreen&-&1);&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&else&if(velocityX&&&-SNAP_VELOCITY&&&&curScreen&&&(getChildCount()-1)){&&
&&&&&&&&&&&&&&&&Log.e(TAG,&"snap&right");&&
&&&&&&&&&&&&&&&&snapToScreen(curScreen&+&1);&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&else{&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&snapToDestination();&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&if&(mVelocityTracker&!=&null)&{&&
&&&&&&&&&&&&&&&&mVelocityTracker.recycle();&&
&&&&&&&&&&&&&&&&mVelocityTracker&=&null;&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&mTouchState&=&TOUCH_STATE_REST&;&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&break;&&
&&&&&&&&case&MotionEvent.ACTION_CANCEL:&&
&&&&&&&&&&&&mTouchState&=&TOUCH_STATE_REST&;&&
&&&&&&&&&&&&break;&&
&&&&&&&&}&&
&&&&&&&&&&
&&&&&&&&return&true&;&&
&&&&private&void&snapToDestination(){&&
&&&&&&&&&&
&&&&&&&&int&scrollX&=&getScrollX()&;&&
&&&&&&&&int&scrollY&=&getScrollY()&;&&
&&&&&&&&&&
&&&&&&&&Log.e(TAG,&"###&onTouchEvent&snapToDestination&###&scrollX&is&"&+&scrollX);&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&int&destScreen&=&(getScrollX()&+&MultiScreenActivity.screenWidth&/&2&)&/&MultiScreenActivity.screenWidth&;&&
&&&&&&&&&&
&&&&&&&&Log.e(TAG,&"###&onTouchEvent&&ACTION_UP###&dx&destScreen&"&+&destScreen);&&
&&&&&&&&&&
&&&&&&&&snapToScreen(destScreen);&&
&&&&private&void&snapToScreen(int&whichScreen){&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&curScreen&=&whichScreen&;&&
&&&&&&&&&&
&&&&&&&&if(curScreen&&&getChildCount()&-&1)&&
&&&&&&&&&&&&curScreen&=&getChildCount()&-&1&;&&
&&&&&&&&&&
&&&&&&&&int&dx&=&curScreen&*&getWidth()&-&getScrollX()&;&&
&&&&&&&&&&
&&&&&&&&Log.e(TAG,&"###&onTouchEvent&&ACTION_UP###&dx&is&"&+&dx);&&
&&&&&&&&&&
&&&&&&&&mScroller.startScroll(getScrollX(),&0,&dx,&0,Math.abs(dx)&*&2);&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&invalidate();&&
&&&&public&void&startMove(){&&
&&&&&&&&...&&&&&&&
&&&&public&void&stopMove(){&&
&&&&&&&&...&&
&&&&@Override&&
&&&&protected&void&onMeasure(int&widthMeasureSpec,&int&heightMeasureSpec)&{&&
&&&&&&&...&&
&&&&@Override&&
&&&&protected&void&onLayout(boolean&changed,&int&l,&int&t,&int&r,&int&b)&{&&
&&&&&&&&...&&
&& 最后,希望大家能多多实践,最好能写个小Demo出来。那样才正在的掌握了所学所得。
& &本文代码示例下载地址:
& & & & & & & & & & && &&&(二合一的Demo)
& &&&最后, 请一定要自己实践理解。否则,效果也不会很好。
Views(...) Comments()主题 : unity iphone怎样实现手指触屏拖动物体移动
级别: 侠客
UID: 15636
可可豆: 824 CB
威望: 823 点
在线时间: 543(时)
发自: Web Page
来源于&&分类
unity iphone怎样实现手指触屏拖动物体移动&&&
如题:unity iphone怎样实现手指触屏拖动物体移动(手在物体上才起作用),手指离开时,物体也静止现在思绪比较混乱,希望大家给点提示。
我的博客:/lm3515/
级别: 精灵王
可可豆: 3927 CB
威望: 4087 点
在线时间: 3300(时)
发自: Web Page
很简单&& 在手指touch时发射射线去测试物体&&并且控制物体移动&&
只有当你射线检测到物体时&&物体才会移动&&也就是你手指离开了 物体也就静止了
级别: 侠客
UID: 15636
可可豆: 824 CB
威望: 823 点
在线时间: 543(时)
发自: Web Page
恩,已经快实现了谢谢楼上的
我的博客:/lm3515/
级别: 天使
发帖: 152456
可可豆: 2255438 CB
威望: 2255438 点
在线时间: 1740(时)
发自: Web Page
参看官方资源区的iPhoneRagdoll
我的博客:QQ:3122828,微博:@unity3
关注本帖(如果有新回复会站内信通知您)
苹果公司现任CEO是谁?2字 正确答案:库克
发帖、回帖都会得到可观的积分奖励。
按"Ctrl+Enter"直接提交
关注CocoaChina
关注微信 每日推荐
扫一扫 浏览移动版Android之实现滑动的七种方法总结
在android开发中,滑动对一个app来说,是非常重要的,流畅的滑动操作,能够给用户带来用好的体验,那么本次就来讲讲android中实现滑动有哪些方式。其实滑动一个View,本质上是移动一个View,改变其当前所属的位置,要实现View的滑动,就必须监听用户触摸的事件,且获取事件传入的坐标值,从而动画的改变位置而实现滑动。
*layout方法
*offsetLetfAndRight()与offsetTopAndBottom()
*LayoutParams
*scrollTo与scrollBy
*ViewDragHelper
android坐标系
首先要知道android的坐标系与我们平常学习的坐标系是不一样的,在android中是将左上方作为坐标原点,向右为x抽正方向,向下为y抽正方向,像在触摸事件中,getRawX(),getRawY()获取到的就是坐标中的坐标.
视图坐标系
android开发中除了上面的这种坐标以外,还有一种坐标,叫视图坐标系,他的原点不在是屏幕左上方,而是以父布局坐上角为坐标原点,像在触摸事件中,getX(),getY()获取到的就是视图坐标中的坐标.
触摸事件&MotionEvent
触摸事件MotionEvent在用户交互中,有非常重要的作用,因此必须要掌握他,我们先来看看Motievent中封装的一些常用的触摸事件常亮:
//单点触摸按下动作 public static final int ACTION_DOWN
= 0; //单点触摸离开动作 public static final int ACTION_UP
= 1; //触摸点移动动作 public static final int ACTION_MOVE
= 2; //触摸动作取消 public static final int ACTION_CANCEL
= 3; //触摸动作超出边界 public static final int ACTION_OUTSIDE
= 4; //多点触摸按下动作 public static final int ACTION_POINTER_DOWN
= 5; //多点触摸离开动作 public static final int ACTION_POINTER_UP
以上是比较常用的一些触摸事件,通常情况下,我们会在OnTouchEvent(MotionEvent event)方法中通过event.getAction()方法来获取触摸事件的类型,其代码模式如下:
@Overridepublic boolean onTouchEvent(MotionEvent event){
//获取当前输入点的坐标,(视图坐标)
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//处理输入按下事件
case MotionEvent.ACTION_MOVE:
//处理输入的移动事件
case MotionEvent.ACTION_UP:
//处理输入的离开事件
} //注意,这里必须返回true,否则只能响应按下事件}
以上只是一个空壳的架构,遇到的具体的场景,也有可能会新增多其他事件,或是用不到这么多事件等等,要根据实际情况来处理。在介绍如何实现滑动之前先来看看android中给我们提供了那些常用的获取坐标值,相对距离等的方法,主要是有以下两个类别:
View 提供的获取坐标方法
getTop(): 获取到的是View自身的顶边到其父布局顶边的距离
getBottom(): 获取到的是View自身的底边到其父布局顶边的距离
getLeft(): 获取到的是View自身的左边到其父布局左边的距离
getRight(): 获取到的是View自身的右边到其父布局左边的距离
MotionEvent提供的方法
getX(): 获取点击事件距离控件左边的距离,即视图坐标
getY(): 获取点击事件距离控件顶边的距离,即视图坐标
getRawX(): 获取点击事件距离整个屏幕左边的距离,即绝对坐标
getRawY(): 获取点击事件距离整个屏幕顶边的距离,即绝对坐标
介绍上面一些基本的知识点后,下面我们就来进入正题了,android中实现滑动的其中方法:
实现滑动的7种方法
其实不管是哪种滑动,他们的基本思路是不变的,都是:当触摸View时,记下当前的触摸坐标;当手指移动时,系统记下移动后的触摸点坐标,从而获得相对前一个点的偏移量,通过偏移量来修改View的坐标,并不断的更新,重复此动作,即可实现滑动的过程。
首先我们先来定义一个View,并置于LinearLayout中,我们的目的是要实现View随着我们手指的滑动而滑动,布局代码如下:
layout方法
我们知道,在进行View绘制时,会调用layout()方法来设置View的显示位置,而layout方法是通过left,top,right,bottom这四个参数来确定View的位置的,所以我们可以通过修改这四个参数的值,从而修改View的位置。首先我们在onTouchEvent方法中获取触摸点的坐标:
float x = event.getX();float y = event.getY();
接着在ACTION_DOWN的时候记下触摸点的坐标值:
case MotionEvent.ACTION_DOWN:
//记录按下触摸点的位置
最后在ACTION_MOVE的时候计算出偏移量,且将偏移量作用到layout方法中:
case MotionEvent.ACTION_MOVE:
//计算偏移量(此次坐标值-上次触摸点坐标值)
int offSetX = (int) (x - mLastX);
int offSetY = (int) (y - mLastY);
//在当前left,right,top.bottom的基础上加上偏移量
layout(getLeft() + offSetX,
getTop() + offSetY,
getRight() + offSetX,
getBottom() + offSetY
这样每次在手指移动的时候,都会调用layout方法重新更新布局,从而达到移动的效果,完整代码如下:
package com.liaojh.import android.content.Cimport android.util.AttributeSimport android.view.MotionEimport android.view.V/** * @author LiaoJH * @DATE 15/11/7 * @VERSION 1.0 * @DESC TODO */public class DragView extends View{
private float mLastX;
private float mLastY;
public DragView(Context context)
this(context, null);
}public DragView(Context context, AttributeSet attrs){
this(context, attrs, 0);}public DragView(Context context, AttributeSet attrs, int defStyleAttr){
super(context, attrs, defStyleAttr);}@Overridepublic boolean onTouchEvent(MotionEvent event){
//获取当前输入点的坐标,(视图坐标)
float x = event.getX();
float y = event.getY();
switch (event.getAction())
case MotionEvent.ACTION_DOWN:
//记录按下触摸点的位置
case MotionEvent.ACTION_MOVE:
//计算偏移量(此次坐标值-上次触摸点坐标值)
int offSetX = (int) (x - mLastX);
int offSetY = (int) (y - mLastY);
//在当前left,right,top.bottom的基础上加上偏移量
layout(getLeft() + offSetX,
getTop() + offSetY,
getRight() + offSetX,
getBottom() + offSetY
当然也可以使用getRawX(),getRawY()来获取绝对坐标,然后使用绝对坐标来更新View的位置,但要注意,在每次执行完ACTION_MOVE的逻辑之后,一定要重新设置初始坐标,这样才能准确获取偏移量,否则每次的偏移量都会加上View的父控件到屏幕顶边的距离,从而不是真正的偏移量了。
@Overridepublic boolean onTouchEvent(MotionEvent event){
//获取当前输入点的坐标,(绝对坐标)
float rawX = event.getRawX();
float rawY = event.getRawY();
switch (event.getAction())
case MotionEvent.ACTION_DOWN:
//记录按下触摸点的位置
mLastX = rawX;
mLastY = rawY;
case MotionEvent.ACTION_MOVE:
//计算偏移量(此次坐标值-上次触摸点坐标值)
int offSetX = (int) (rawX - mLastX);
int offSetY = (int) (rawY - mLastY);
//在当前left,right,top.bottom的基础上加上偏移量
layout(getLeft() + offSetX,
getTop() + offSetY,
getRight() + offSetX,
getBottom() + offSetY
//重新设置初始位置的值
mLastX = rawX;
mLastY = rawY;
offsetLeftAndRight()与offsetTopAndBottom()
这个方法相当于系统提供了一个对左右,上下移动的API的封装,在计算出偏移量之后,只需使用如下代码设置即可:
offsetLeftAndRight(offSetX); offsetTopAndBottom(offSetY);
偏移量的计算与上面一致,只是换了layout方法而已。
LayoutParams
LayoutParams保存了一个View的布局参数,因此可以在程序中通过动态的改变布局的位置参数,也可以达到滑动的效果,代码如下:
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) getLayoutParams(); lp.leftMargin = getLeft() + offSetX; lp.topMargin = getTop() + offSetY; setLayoutParams(lp);
使用此方式时需要特别注意:通过getLayoutParams()获取LayoutParams时,需要根据View所在的父布局的类型来设置不同的类型,比如这里,View所在的父布局是LinearLayout,所以可以强转成LinearLayout.LayoutParams。
在通过改变LayoutParams来改变View的位置时,通常改变的是这个View的Margin属性,其实除了LayoutParams之外,我们有时候还可以使用ViewGroup.MarginLayoutParams来改变View的位置,代码如下:
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) getLayoutParams();lp.leftMargin = getLeft() + offSetX;lp.topMargin = getTop() + offSetY;setLayoutParams(lp);//使用这种方式的好处就是不用考虑父布局类型
scrollTo与scrollBy
在一个View中,系统提供了scrollTo与scrollBy两种方式来改变一个View的位置,其中scrollTo(x,y)表示移动到一个具体的坐标点(x,y),而scrollBy(x,y)表示移动的增量。与前面几种计算偏移量相同,使用scrollBy来移动View,代码如下:
scrollBy(offSetX,offSetY);
然后我们拖动View,发现View并没有移动,这是为杂呢?其实,方法没有错,view也的确移动了,只是他移动的不是我们想要的东西。scrollTo,scrollBy方法移动的是view的content,即让view的内容移动,如果是在ViewGroup中使用scrollTo,scrollBy方法,那么移动的将是所有的子View,而如果在View中使用的话,就是view的内容,所以我们需要改一下我们之前的代码:
((View)getParent()).scrollBy(offSetX, offSetY);
这次是可以滑动了,但是我们发现,滑动的效果跟我们想象的不一样,完全相反了,这又是为什么呢?其实这是因为android中对于移动参考系选择的不同从而实现这样的效果,而我们想要实现我们滑动的效果,只需将偏移量设置为负值即可,代码如下:
((View) getParent()).scrollBy(-offSetX, -offSetY);
同样的在使用绝对坐标时,使用scrollTo也可以达到这样的效果。
如果让一个View向右移动200的距离,使用上面的方式,大家应该发现了一个问题,就是移动都是瞬间完成的,没有那种慢慢平滑的感觉,所以呢,android就给我们提供了一个类,叫scroller类,使用该类就可以实现像动画一样平滑的效果。
其实它实现的原理跟前面的scrooTo,scrollBy方法实现view的滑动原理类似,它是将ACTION_MOVE移动的一段位移划分成N段小的偏移量,然后再每一个偏移量里面使用scrollBy方法来实现view的瞬间移动,这样在整体的效果上就实现了平滑的效果,说白了就是利用人眼的视觉暂留特性。
下面我们就来实现这么一个例子,移动view到某个位置,松开手指,view都吸附到左边位置,一般来说,使用Scroller实现滑动,需经过以下几个步骤:
初始化Scroller
//初始化Scroller,使用默认的滑动时长与插值器mScroller = new Scroller(context);
重写computeScroll()方法
该方法是Scroller类的核心,系统会在绘制View的时候调用draw()方法中调用该方法,这个方法本质上是使用scrollTo方法,通过Scroller类可以获取到当前的滚动值,这样我们就可以实现平滑一定的效果了,一般模板代码如下:
@Overridepublic void computeScroll(){
puteScroll();
//判断Scroller是否执行完成
if (puteScrollOffset()) {
((View)getParent()).scrollTo(
mScroller.getCurrX(),
mScroller.getCurrY()
//调用invalidate()computeScroll()方法
invalidate();
Scroller类提供中的方法:
computeScrollOffset(): 判断是否完成了真个滑动getCurrX(): 获取在x抽方向上当前滑动的距离getCurrY(): 获取在y抽方向上当前滑动的距离
startScroll开启滑动
最后在需要使用平滑移动的事件中,使用Scroller类的startScroll()方法来开启滑动过程,startScroller()方法有两个重载的方法:
& public void startScroll(int startX, int startY, int dx, int dy)
& public void startScroll(int startX, int startY, int dx, int dy, int duration)
可以看到他们的区别只是多了duration这个参数,而这个是滑动的时长,如果没有使用默认时长,默认是250毫秒,而其他四个坐标则表示起始坐标与偏移量,可以通过getScrollX(),getScrollY()来获取父视图中content所滑动到的点的距离,不过要注意这个值的正负,它与scrollBy,scrollTo中说的是一样的。经过上面这三步,我们就可以实现Scroller的平滑一定了。
继续上面的例子,我们可以在onTouchEvent方法中监听ACTION_UP事件动作,调用startScroll方法,其代码如下:
case MotionEvent.ACTION_UP:
//当手指离开时,执行滑动过程
ViewGroup viewGroup = (ViewGroup) getParent();
mScroller.startScroll(
viewGroup.getScrollX(),
viewGroup.getScrollY(),
-viewGroup.getScrollX(),
//刷新布局,从而调用computeScroll方法
invalidate();
使用属性动画同样可以控制一个View的滑动,下面使用属相动画来实现上边的效果(关于属相动画,请关注其他的博文),代码如下:
case MotionEvent.ACTION_UP:
ViewGroup viewGroup = (ViewGroup) getParent();
//属性动画执行滑动
ObjectAnimator.ofFloat(this, &translationX&, viewGroup.getScrollX()).setDuration(500)
ViewDragHelper
一看这个类的名字,我们就知道他是与拖拽有关的,猜的没错,通过这个类我们基本可以实现各种不同的滑动,拖放效果,他是非常强大的一个类,但是它也是最为复杂的,但是不要慌,只要你不断的练习,就可以数量的掌握它的使用技巧。下面我们使用这个类来时实现类似于QQ滑动侧边栏的效果,相信广大朋友们多与这个现象是很熟悉的吧。
先来看看使用的步骤是如何的:
初始化ViewDragHelper
ViewDragHelper这个类通常是定义在一个ViewGroup的内部,并通过静态方法进行初始化,代码如下:
//初始化ViewDragHelper
viewDragHelper = ViewDragHelper.create(this,callback);
它的第一个参数是要监听的View,通常是一个ViewGroup,第二个参数是一个Callback回调,它是整个ViewDragHelper的逻辑核心,后面进行具体介绍。
重写拦截事件onInterceptTouchEvent与onTouchEvent方法,将事件传递交给ViewDragHelper进行处理,代码如下:
@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev){
//2. 将事件交给ViewDragHelper
viewDragHelper.shouldInterceptTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event){
//2. 将触摸事件传递给ViewDragHelper,不可少
viewDragHelper.processTouchEvent(event);}
处理computeScroll()方法
前面我们在使用Scroller类的时候,重写过该方法,在这里我们也需要重写该方法,因为ViewDragHelper内部也是使用Scroller类来实现的,代码如下:
//3. 重写computeScroll@Overridepublic void computeScroll(){
//持续平滑动画 (高频率调用)
if (viewDragHelper.continueSettling(true))
如果返回true, 动画还需要继续执行
ViewCompat.postInvalidateOnAnimation(this);}
处理回调Callback
通过如下代码创建一个Callback:
private ViewDragHelper.Callback callback = new ViewDragHelper.Callback(){
//此方法中可以指定在创建ViewDragHelper时,参数ViewParent中的那些子View可以被移动
//根据返回结果决定当前child是否可以拖拽
child 当前被拖拽的View
pointerId 区分多点触摸的id
public boolean tryCaptureView(View child, int pointerId)
//如果当前触摸的view是mMainView时开始检测
return mMainView ==
//水平方向的滑动
// 根据建议值 修正将要移动到的(横向)位置
// 此时没有发生真正的移动
public int clampViewPositionHorizontal(View child, int left, int dx)
//返回要滑动的距离,默认返回0,既不滑动
//参数参考clampViewPositionVertical
f (child == mMainView)
if (left & 300)
left = 300;
if (left & 0)
//垂直方向的滑动
// 根据建议值 修正将要移动到的(纵向)位置
// 此时没有发生真正的移动
public int clampViewPositionVertical(View child, int top, int dy)
//top : 垂直向上child滑动的距离,
//dy: 表示比较前一次的增量,通常只需返回top即可,如果需要精确计算padding等属性的话,就需要对left进行处理
return super.clampViewPositionVertical(child, top, dy); //0
到这里就可以拖拽mMainView移动了。
下面我们继续来优化这个代码,还记得之前我们使用Scroller时,当手指离开屏幕后,子view会吸附到左边位置,当时我们监听ACTION_UP,然后调用startScroll来实现的,这里我们使用ViewDragHelper来实现。
在ViewDragHelper.Callback中,系统提供了这么一个方法&onViewReleased(),我们可以通过重写这个方法,来实现之前的操作,当然这个方法内部也是通过Scroller来实现的,这也是为什么我们要重写computeScroll方法的原因,实现代码如下:
//拖动结束时调用
public void onViewReleased(View releasedChild, float xvel, float yvel)
if (mMainView.getLeft() & 150)
// 触发一个平滑动画,关闭菜单,相当于Scroll的startScroll方法
if (viewDragHelper.smoothSlideViewTo(mMainView, 0, 0))
// 返回true代表还没有移动到指定位置, 需要刷新界面.
// 参数传this(child所在的ViewGroup)
ViewCompat.postInvalidateOnAnimation(DragLayout.this);
//打开菜单
if (viewDragHelper.smoothSlideViewTo(mMainView, 300, 0)) ;
ViewCompat.postInvalidateOnAnimation(DragLayout.this);
super.onViewReleased(releasedChild, xvel, yvel);
当滑动的距离小于150时,mMainView回到原来的位置,当大于150时,滑动到300的位置,相当于打开了mMenuView,而且滑动的时候是很平滑的。此外还有一些方法:
public void onViewCaptured(View capturedChild, int activePointerId)
// 当capturedChild被捕获时,调用.
super.onViewCaptured(capturedChild, activePointerId);
public int getViewHorizontalDragRange(View child)
// 返回拖拽的范围, 不对拖拽进行真正的限制. 仅仅决定了动画执行速度
return 300;
//当View位置改变的时候, 处理要做的事情 (更新状态, 伴随动画, 重绘界面)
// 此时,View已经发生了位置的改变
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy)
// changedView 改变位置的View
// left 新的左边值
// dx 水平方向变化量
super.onViewPositionChanged(changedView, left, top, dx, dy);
说明:里面还有很多关于处理各种事件方法的定义,如:
onViewCaptured():用户触摸到view后回调
onViewDragStateChanged(state):这个事件在拖拽状态改变时回调,比如:idle,dragging等状态
onViewPositionChanged():这个是在位置改变的时候回调,常用于滑动时伴随动画的实现效果等
对于里面的方法,如果不知道什么意思,则可以打印log,看看参数的意思。
这里介绍的就是android实现滑动的七种方法,至于使用哪一种好,就要结合具体的项目需求场景了,毕竟硬生生的实现这个效果,而不管用户的使用体验式不切实际的,这里面个人觉得比较重要的是Scroller类的使用。属性动画以及ViewDragHelper类,特别是最后一个,也是最难最复杂的,但也是甩的最多的。}

我要回帖

更多关于 u3d控制物体移动 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信